mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add 'preParse' plugin hook
This commit is contained in:
+2
-13
@@ -108,18 +108,7 @@ task("watch-tsc", series(lkgPreBuild, parallel(watchLib, watchDiagnostics, watch
|
||||
task("watch-tsc").description = "Watch for changes and rebuild the command-line compiler only.";
|
||||
|
||||
const buildApi = (() => {
|
||||
const flattenCompiler = async () => flatten("src/compiler/tsconfig.json", "built/local/api.tsconfig.json", {
|
||||
compilerOptions: {
|
||||
removeComments: false,
|
||||
stripInternal: true,
|
||||
emitDeclarationOnly: true,
|
||||
declaration: true,
|
||||
declarationMap: false,
|
||||
outFile: "api.out.js"
|
||||
}
|
||||
});
|
||||
|
||||
const buildApiOut = () => buildProject("built/local/api.tsconfig.json");
|
||||
const buildApiOut = () => buildProject("src/pluginApi/tsconfig.json", cmdLineOptions);
|
||||
|
||||
const generateApiDts = () => src("built/local/api.out.d.ts", { base: "built/local" })
|
||||
.pipe(newer("built/local/api.d.ts"))
|
||||
@@ -136,7 +125,7 @@ const buildApi = (() => {
|
||||
.pipe(rename("api.js"))
|
||||
.pipe(dest("built/local"));
|
||||
|
||||
return series(flattenCompiler, buildApiOut, generateApiDts, generateApiJs);
|
||||
return series(buildApiOut, generateApiDts, generateApiJs);
|
||||
})();
|
||||
task("api", series(lkgPreBuild, buildApi));
|
||||
task("api").description = "Build the compiler plugin API";
|
||||
|
||||
+140
-50
@@ -1,13 +1,16 @@
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
type Hook = "activate" | "deactivate" | "preEmit";
|
||||
type MatchingKeys<T, TMatch, K extends keyof T = keyof T> = K extends (T[K] extends TMatch ? K : never) ? K : never;
|
||||
type Hook = MatchingKeys<Required<CompilerPluginModule>, (context: CompilerPluginContext, ...args: any[]) => CompilerPluginResult | void>;
|
||||
type HookFunction<K extends Hook> = NonNullable<CompilerPluginModule[K]>;
|
||||
type HookReturnType<K extends Hook> = Exclude<ReturnType<HookFunction<K>>, void>;
|
||||
|
||||
type ExecuteUserCodeResult<T> =
|
||||
| { error: Diagnostic, result: undefined }
|
||||
| { error: undefined, result: T | undefined };
|
||||
|
||||
interface PluginEntry {
|
||||
active: boolean; // Tracks whether the plugin has been activated.
|
||||
state: "inactive" | "active" | "failed"; // Tracks whether the plugin has been activated.
|
||||
compilerPlugin: CompilerPlugin;
|
||||
}
|
||||
|
||||
@@ -31,7 +34,6 @@ namespace ts {
|
||||
*/
|
||||
/*@internal*/
|
||||
export function getPlugins(host: ModuleLoaderHost, initialDir: string, plugins: ReadonlyArray<string | [string, any?]>) {
|
||||
debugger;
|
||||
interface ResolvedModule {
|
||||
module: {};
|
||||
moduleName: string;
|
||||
@@ -195,92 +197,180 @@ namespace ts {
|
||||
return moduleName.replace(/^(@[^\\/]+[\\/])?/, "$1typescript-plugin-");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a wrapped view of a Program for use with a plugin.
|
||||
*/
|
||||
function getOrCreatePluginProgram(program: Program) {
|
||||
if (program.pluginProgram) {
|
||||
return program.pluginProgram;
|
||||
}
|
||||
|
||||
let disposed = false;
|
||||
program.pluginProgram = {
|
||||
getCompilerOptions: () => (checkDisposed(), program.getCompilerOptions()),
|
||||
getSourceFile: fileName => (checkDisposed(), program.getSourceFile(fileName)),
|
||||
getSourceFileByPath: path => (checkDisposed(), program.getSourceFileByPath(path)),
|
||||
getCurrentDirectory: () => (checkDisposed(), program.getCurrentDirectory()),
|
||||
getRootFileNames: () => (checkDisposed(), program.getRootFileNames()),
|
||||
getSourceFiles: () => (checkDisposed(), program.getSourceFiles()),
|
||||
emit: (targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) => (checkDisposed(), program.emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)),
|
||||
getOptionsDiagnostics: cancellationToken => (checkDisposed(), program.getOptionsDiagnostics(cancellationToken)),
|
||||
getGlobalDiagnostics: cancellationToken => (checkDisposed(), program.getGlobalDiagnostics(cancellationToken)),
|
||||
getSyntacticDiagnostics: (sourceFile, cancellationToken) => (checkDisposed(), program.getSyntacticDiagnostics(sourceFile, cancellationToken)),
|
||||
getSemanticDiagnostics: (sourceFile, cancellationToken) => (checkDisposed(), program.getSemanticDiagnostics(sourceFile, cancellationToken)),
|
||||
getDeclarationDiagnostics: (sourceFile, cancellationToken) => (checkDisposed(), program.getDeclarationDiagnostics(sourceFile, cancellationToken)),
|
||||
getConfigFileParsingDiagnostics: () => (checkDisposed(), program.getConfigFileParsingDiagnostics()),
|
||||
getTypeChecker: () => (checkDisposed(), program.getTypeChecker()),
|
||||
isSourceFileFromExternalLibrary: file => (checkDisposed(), program.isSourceFileFromExternalLibrary(file)),
|
||||
isSourceFileDefaultLibrary: file => (checkDisposed(), program.isSourceFileDefaultLibrary(file)),
|
||||
getProjectReferences: () => (checkDisposed(), program.getProjectReferences()),
|
||||
getResolvedProjectReferences: () => (checkDisposed(), program.getResolvedProjectReferences()),
|
||||
pluginDispose: () => { disposed = true },
|
||||
// internal members are not exposed.
|
||||
getMissingFilePaths: notImplemented,
|
||||
getSuggestionDiagnostics: notImplemented,
|
||||
getCommonSourceDirectory: notImplemented,
|
||||
getDiagnosticsProducingTypeChecker: notImplemented,
|
||||
dropDiagnosticsProducingTypeChecker: notImplemented,
|
||||
getClassifiableNames: notImplemented,
|
||||
getNodeCount: notImplemented,
|
||||
getIdentifierCount: notImplemented,
|
||||
getSymbolCount: notImplemented,
|
||||
getTypeCount: notImplemented,
|
||||
getFileProcessingDiagnostics: notImplemented,
|
||||
getResolvedTypeReferenceDirectives: notImplemented,
|
||||
getSourceFileFromReference: notImplemented,
|
||||
getLibFileFromReference: notImplemented,
|
||||
sourceFileToPackageName: undefined!,
|
||||
redirectTargetsMap: undefined!,
|
||||
isEmittedFile: notImplemented,
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache: notImplemented,
|
||||
getProjectReferenceRedirect: notImplemented,
|
||||
getResolvedProjectReferenceToRedirect: notImplemented,
|
||||
forEachResolvedProjectReference: notImplemented,
|
||||
getResolvedProjectReferenceByPath: notImplemented,
|
||||
getRefFileMap: notImplemented,
|
||||
emitBuildInfo: notImplemented,
|
||||
getRelationCacheSizes: notImplemented,
|
||||
dispose: notImplemented,
|
||||
};
|
||||
program.pluginProgram.pluginProgram = program.pluginProgram;
|
||||
return program.pluginProgram;
|
||||
|
||||
function checkDisposed() {
|
||||
if (disposed) throw new TypeError("Object is disposed.");
|
||||
disposed = true;
|
||||
program = undefined!;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a `CompilerPluginHost` used to manage plugin lifetime.
|
||||
*/
|
||||
/*@internal*/
|
||||
export function createPluginHost(plugins: ReadonlyArray<CompilerPlugin>): CompilerPluginHost {
|
||||
const entries: PluginEntry[] = plugins.map(compilerPlugin => ({ compilerPlugin, active: false }));
|
||||
export function createPluginHost(plugins: ReadonlyArray<CompilerPlugin>, compilerOptions: CompilerOptions): CompilerPluginHost {
|
||||
const entries: PluginEntry[] = plugins.map(compilerPlugin => ({ compilerPlugin, state: "inactive" }));
|
||||
|
||||
return {
|
||||
preParse,
|
||||
preEmit,
|
||||
deactivate
|
||||
};
|
||||
|
||||
function executeUserCode<K extends Hook>(compilerPlugin: CompilerPlugin, hook: K, ...args: Parameters<HookFunction<K>>): ExecuteUserCodeResult<ReturnType<HookFunction<K>>> {
|
||||
const hookFunction: HookFunction<K> | undefined = compilerPlugin.plugin[hook]!;
|
||||
if (typeof hookFunction === "function") {
|
||||
function selectPlugins({ eventName, state }: { eventName?: Hook, state?: "inactive" | "active" | "failed" }) {
|
||||
const result: PluginEntry[] = [];
|
||||
for (const entry of entries) {
|
||||
if (state !== undefined && entry.state !== state) continue;
|
||||
if (eventName !== undefined && !contains(entry.compilerPlugin.activationEvents, eventName)) continue;
|
||||
result.push(entry);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function executeUserCode<K extends Hook>(plugin: PluginEntry, hook: K, ...args: Parameters<HookFunction<K>>): ExecuteUserCodeResult<HookReturnType<K>> {
|
||||
const hookAction = plugin.compilerPlugin.plugin[hook];
|
||||
if (typeof hookAction === "function") {
|
||||
try {
|
||||
const result = hookFunction.apply(compilerPlugin.plugin, args);
|
||||
return { result, error: undefined };
|
||||
const result: HookReturnType<K> | undefined = hookAction.apply(plugin.compilerPlugin.plugin, args);
|
||||
return { error: undefined, result };
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof OperationCanceledException) {
|
||||
throw error;
|
||||
}
|
||||
return { result: undefined, error: createUserCodeDiagnostic(compilerPlugin, hook, error) };
|
||||
plugin.state = "failed";
|
||||
return { error: createUserCodeDiagnostic(plugin.compilerPlugin, hook, error), result: undefined };
|
||||
}
|
||||
}
|
||||
return { result: undefined, error: undefined };
|
||||
return { error: undefined, result: undefined };
|
||||
}
|
||||
|
||||
function createContext(compilerHost: CompilerHost, { options }: CompilerPlugin): CompilerPluginContext {
|
||||
return { ts, compilerHost, options };
|
||||
function createContext(compilerHost: CompilerHost, { compilerPlugin: { options } }: PluginEntry): CompilerPluginContext {
|
||||
return { ts, compilerHost, compilerOptions, options };
|
||||
}
|
||||
|
||||
function createUserCodeDiagnostic(compilerPlugin: CompilerPlugin, hook: Hook, error: { message?: string, stack?: string }) {
|
||||
return createCompilerDiagnostic(Diagnostics.Plugin_0_failed_while_executing_the_1_hook_Colon_2, compilerPlugin.name, hook, error.stack || error.message || error.toString());
|
||||
}
|
||||
|
||||
function activate(host: CompilerHost, activationEventName: string) {
|
||||
const activeCompilerPlugins: CompilerPlugin[] = [];
|
||||
function activate(host: CompilerHost, eventName: Hook): ReadonlyArray<Diagnostic> | undefined {
|
||||
let diagnostics: ReadonlyArray<Diagnostic> | undefined;
|
||||
for (const entry of entries) {
|
||||
if (!entry.active && contains(entry.compilerPlugin.activationEvents, activationEventName)) {
|
||||
const { error, result: activationResult } = executeUserCode(entry.compilerPlugin, "activate", createContext(host, entry.compilerPlugin));
|
||||
if (error) {
|
||||
diagnostics = concatenate(diagnostics, [error]);
|
||||
}
|
||||
else {
|
||||
if (activationResult) diagnostics = concatenate(diagnostics, activationResult.diagnostics);
|
||||
entry.active = true;
|
||||
}
|
||||
for (const plugin of selectPlugins({ eventName, state: "inactive" })) {
|
||||
const { error, result } = executeUserCode(plugin, "activate", createContext(host, plugin), { });
|
||||
if (error) {
|
||||
// TODO(rbuckton): Determine better mechanism to handle plugin activation failure.
|
||||
diagnostics = concatenate(diagnostics, [error]);
|
||||
}
|
||||
if (entry.active) {
|
||||
activeCompilerPlugins.push(entry.compilerPlugin);
|
||||
else {
|
||||
plugin.state = "active";
|
||||
if (result) diagnostics = concatenate(diagnostics, result.diagnostics);
|
||||
}
|
||||
}
|
||||
return { activeCompilerPlugins, diagnostics };
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
function preEmit(host: CompilerHost, program: Program, targetSourceFile?: SourceFile, cancellationToken?: CancellationToken): CompilerPluginPreEmitResult {
|
||||
debugger;
|
||||
const activationResult = activate(host, /*activationEventName*/ "preEmit");
|
||||
const activeCompilerPlugins = activationResult.activeCompilerPlugins;
|
||||
let diagnostics = activationResult.diagnostics;
|
||||
let customTransformers: CustomTransformers | undefined;
|
||||
for (const plugin of activeCompilerPlugins) {
|
||||
const { error, result: preEmitResult } = executeUserCode(plugin, "preEmit", createContext(host, plugin), program, targetSourceFile, cancellationToken);
|
||||
function preParse(host: CompilerHost, { rootNames, projectReferences }: CompilerPluginPreParseArgs): CompilerPluginPreParseResult {
|
||||
let diagnostics = activate(host, "preParse");
|
||||
for (const plugin of selectPlugins({ eventName: "preParse", state: "active" })) {
|
||||
const { error, result } = executeUserCode(plugin, "preParse", createContext(host, plugin), { rootNames, projectReferences });
|
||||
if (error) {
|
||||
diagnostics = concatenate(diagnostics, [error]);
|
||||
}
|
||||
else if (preEmitResult) {
|
||||
diagnostics = concatenate(diagnostics, preEmitResult.diagnostics);
|
||||
customTransformers = combineCustomTransformers(customTransformers, preEmitResult.customTransformers);
|
||||
else if (result) {
|
||||
diagnostics = concatenate(diagnostics, result.diagnostics);
|
||||
host = result.compilerHost || host;
|
||||
rootNames = result.rootNames || rootNames;
|
||||
projectReferences = result.projectReferences || projectReferences;
|
||||
}
|
||||
}
|
||||
return { compilerHost: host, rootNames, projectReferences };
|
||||
}
|
||||
|
||||
function preEmit(host: CompilerHost, { program, targetSourceFile, cancellationToken }: CompilerPluginPreEmitArgs): CompilerPluginPreEmitResult {
|
||||
program = getOrCreatePluginProgram(program);
|
||||
let diagnostics = activate(host, "preEmit");
|
||||
let customTransformers: CustomTransformers | undefined;
|
||||
for (const plugin of selectPlugins({ eventName: "preEmit", state: "active" })) {
|
||||
const { error, result } = executeUserCode(plugin, "preEmit", createContext(host, plugin), { program, targetSourceFile, cancellationToken });
|
||||
if (error) {
|
||||
diagnostics = concatenate(diagnostics, [error]);
|
||||
}
|
||||
else if (result) {
|
||||
diagnostics = concatenate(diagnostics, result.diagnostics);
|
||||
customTransformers = combineCustomTransformers(customTransformers, result.customTransformers);
|
||||
}
|
||||
}
|
||||
return { diagnostics, customTransformers };
|
||||
}
|
||||
|
||||
function deactivate(host: CompilerHost): CompilerPluginDeactivationResult {
|
||||
debugger;
|
||||
let diagnostics: Diagnostic[] | undefined;
|
||||
for (const entry of entries) {
|
||||
if (entry.active) {
|
||||
entry.active = false;
|
||||
const { error } = executeUserCode(entry.compilerPlugin, "deactivate", createContext(host, entry.compilerPlugin));
|
||||
if (error) {
|
||||
diagnostics = append(diagnostics, error);
|
||||
}
|
||||
let diagnostics: ReadonlyArray<Diagnostic> | undefined;
|
||||
for (const plugin of selectPlugins({ state: "active" })) {
|
||||
const { error } = executeUserCode(plugin, "deactivate", createContext(host, plugin));
|
||||
if (error) {
|
||||
diagnostics = concatenate(diagnostics, [error]);
|
||||
}
|
||||
else {
|
||||
plugin.state = "inactive";
|
||||
}
|
||||
}
|
||||
return { diagnostics };
|
||||
|
||||
+26
-9
@@ -711,8 +711,8 @@ namespace ts {
|
||||
export function createProgram(rootNames: ReadonlyArray<string>, options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program;
|
||||
export function createProgram(rootNamesOrOptions: ReadonlyArray<string> | CreateProgramOptions, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: ReadonlyArray<Diagnostic>): Program {
|
||||
const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217
|
||||
const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions;
|
||||
let { oldProgram } = createProgramOptions;
|
||||
const { options, configFileParsingDiagnostics } = createProgramOptions;
|
||||
let { rootNames, projectReferences, oldProgram } = createProgramOptions;
|
||||
|
||||
let program: Program;
|
||||
let processingDefaultLibFiles: SourceFile[] | undefined;
|
||||
@@ -725,7 +725,7 @@ namespace ts {
|
||||
const ambientModuleNameToUnmodifiedFileName = createMap<string>();
|
||||
// Todo:: Use this to report why file was included in --extendedDiagnostics
|
||||
let refFileMap: MultiMap<ts.RefFile> | undefined;
|
||||
const pluginHost = createProgramOptions.plugins && createPluginHost(createProgramOptions.plugins);
|
||||
const pluginHost = createProgramOptions.plugins && createPluginHost(createProgramOptions.plugins, options);
|
||||
|
||||
const cachedSemanticDiagnosticsForFile: DiagnosticCache<Diagnostic> = {};
|
||||
const cachedDeclarationDiagnosticsForFile: DiagnosticCache<DiagnosticWithLocation> = {};
|
||||
@@ -733,6 +733,21 @@ namespace ts {
|
||||
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective | undefined>();
|
||||
let fileProcessingDiagnostics = createDiagnosticCollection();
|
||||
|
||||
performance.mark("beforeProgram");
|
||||
|
||||
let host = createProgramOptions.host || createCompilerHost(options);
|
||||
const preParseResult = pluginHost && pluginHost.preParse(host, { rootNames, projectReferences });
|
||||
if (preParseResult) {
|
||||
if (preParseResult.diagnostics) {
|
||||
for (const diagnostic of preParseResult.diagnostics) {
|
||||
fileProcessingDiagnostics.add(diagnostic);
|
||||
}
|
||||
}
|
||||
if (preParseResult.compilerHost) host = preParseResult.compilerHost;
|
||||
if (preParseResult.rootNames) rootNames = preParseResult.rootNames;
|
||||
if (preParseResult.projectReferences) projectReferences = preParseResult.projectReferences;
|
||||
}
|
||||
|
||||
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
|
||||
// This works as imported modules are discovered recursively in a depth first manner, specifically:
|
||||
// - For each root file, findSourceFile is called.
|
||||
@@ -750,9 +765,6 @@ namespace ts {
|
||||
// Track source files that are source files found by searching under node_modules, as these shouldn't be compiled.
|
||||
const sourceFilesFoundSearchingNodeModules = createMap<boolean>();
|
||||
|
||||
performance.mark("beforeProgram");
|
||||
|
||||
const host = createProgramOptions.host || createCompilerHost(options);
|
||||
const configParsingHost = parseConfigHostFromCompilerHostLike(host);
|
||||
|
||||
let skipDefaultLib = options.noLib;
|
||||
@@ -975,6 +987,9 @@ namespace ts {
|
||||
if (pluginHost) {
|
||||
pluginHost.deactivate(host);
|
||||
}
|
||||
if (program.pluginProgram) {
|
||||
program.pluginProgram.pluginDispose();
|
||||
}
|
||||
}
|
||||
|
||||
function compareDefaultLibFiles(a: SourceFile, b: SourceFile) {
|
||||
@@ -1560,9 +1575,11 @@ namespace ts {
|
||||
|
||||
let pluginDiagnostics: ReadonlyArray<Diagnostic> | undefined;
|
||||
if (pluginHost) {
|
||||
const result = pluginHost.preEmit(host, program, sourceFile, cancellationToken);
|
||||
pluginDiagnostics = result.diagnostics;
|
||||
customTransformers = combineCustomTransformers(customTransformers, result.customTransformers);
|
||||
const result = pluginHost.preEmit(host, { program, targetSourceFile: sourceFile, cancellationToken });
|
||||
if (result) {
|
||||
pluginDiagnostics = result.diagnostics;
|
||||
customTransformers = combineCustomTransformers(customTransformers, result.customTransformers);
|
||||
}
|
||||
}
|
||||
|
||||
if (!emitOnlyDtsFiles) {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
|
||||
declare function setTimeout<A extends any[]>(handler: (...args: A) => void, timeout: number, ...args: A): any;
|
||||
declare function clearTimeout(handle: any): void;
|
||||
|
||||
namespace ts {
|
||||
|
||||
+105
-80
@@ -2947,27 +2947,6 @@ namespace ts {
|
||||
file: Path;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface CompilerPluginDeactivationResult {
|
||||
diagnostics?: ReadonlyArray<Diagnostic>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The CompilerPluginHost provides an interface for interacting with the compiler plugin model.
|
||||
*/
|
||||
/*@internal*/
|
||||
export interface CompilerPluginHost {
|
||||
/**
|
||||
* Trigger the `preEmit` hooks for plugins.
|
||||
*/
|
||||
preEmit(host: CompilerHost, program: Program, targetSourceFile?: SourceFile, cancellationToken?: CancellationToken): CompilerPluginPreEmitResult;
|
||||
|
||||
/**
|
||||
* Deactivate any active plugins.
|
||||
*/
|
||||
deactivate(host: CompilerHost): CompilerPluginDeactivationResult;
|
||||
}
|
||||
|
||||
// TODO: This should implement TypeCheckerHost but that's an internal type.
|
||||
export interface Program extends ScriptReferenceHost {
|
||||
|
||||
@@ -3063,6 +3042,14 @@ namespace ts {
|
||||
* Dispose of any resources held by the program and deactivate any active plugins.
|
||||
*/
|
||||
/*@internal*/ dispose(): void;
|
||||
|
||||
/** A view of the Program that is provided to plugins. */
|
||||
/*@internal*/ pluginProgram?: PluginProgram;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface PluginProgram extends Program {
|
||||
pluginDispose(): void;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -4927,65 +4914,6 @@ namespace ts {
|
||||
/* @internal */ spec: ConfigFileSpecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* A context object passed to a plugin during activation.
|
||||
*/
|
||||
export interface CompilerPluginContext {
|
||||
/**
|
||||
* The running instance of the TypeScript compiler.
|
||||
*/
|
||||
readonly ts: typeof ts;
|
||||
|
||||
/**
|
||||
* The current CompilerHost.
|
||||
*/
|
||||
readonly compilerHost: CompilerHost;
|
||||
|
||||
/**
|
||||
* Configuration options for the plugin.
|
||||
*/
|
||||
readonly options: MapLike<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional result that can be returned from the `CompilerPluginModule.activate` hook.
|
||||
*/
|
||||
export interface CompilerPluginActivationResult {
|
||||
diagnostics?: ReadonlyArray<Diagnostic>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional result that can be returned from the `CompilerPluginModule.preEmit` hook.
|
||||
*/
|
||||
export interface CompilerPluginPreEmitResult {
|
||||
diagnostics?: ReadonlyArray<Diagnostic>;
|
||||
customTransformers?: CustomTransformers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the supported shape of the main module for a compiler plugin.
|
||||
*/
|
||||
export interface CompilerPluginModule {
|
||||
/**
|
||||
* The `activate` hook is invoked when a plugin is activated for the first time within a `Program`.
|
||||
* @param context The current plugin context.
|
||||
*/
|
||||
activate?(context: CompilerPluginContext): CompilerPluginActivationResult | void;
|
||||
/**
|
||||
* The `preEmit` hook is invoked after type check has completed and immediately before emit.
|
||||
* @param context The current plugin context.
|
||||
* @param program The current `Program`.
|
||||
* @param targetSourceFile The `SourceFile` that is about to be emitted, or `undefined` when emitting all outputs.
|
||||
* @param cancellationToken A `CancellationToken` that can be used to abort an operation when running in the language service.
|
||||
*/
|
||||
preEmit?(context: CompilerPluginContext, program: Program, targetSourceFile?: SourceFile, cancellationToken?: CancellationToken): CompilerPluginPreEmitResult | void;
|
||||
/**
|
||||
* The `deactivate` hook is invoked when a plugin should be deactivated so that it can free up any shared resources.
|
||||
* @param context The current plugin context.
|
||||
*/
|
||||
deactivate?(context: CompilerPluginContext): void;
|
||||
}
|
||||
|
||||
export interface CompilerPlugin {
|
||||
/** The rsolved package name for the plugin. */
|
||||
name: string;
|
||||
@@ -5003,6 +4931,103 @@ namespace ts {
|
||||
plugin: CompilerPluginModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* A context object passed to a plugin during activation.
|
||||
*/
|
||||
export interface CompilerPluginContext {
|
||||
/** The running instance of the TypeScript compiler. */
|
||||
readonly ts: typeof ts;
|
||||
/** The current CompilerHost. */
|
||||
readonly compilerHost: CompilerHost;
|
||||
/** The current CompilerOptions. */
|
||||
readonly compilerOptions: CompilerOptions;
|
||||
/** Configuration options for the plugin. */
|
||||
readonly options: MapLike<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The CompilerPluginHost provides an interface for interacting with the compiler plugin model.
|
||||
*/
|
||||
/*@internal*/
|
||||
export interface CompilerPluginHost {
|
||||
preParse(host: CompilerHost, args: CompilerPluginPreParseArgs): CompilerPluginPreParseResult | void;
|
||||
preEmit(host: CompilerHost, args: CompilerPluginPreEmitArgs): CompilerPluginPreEmitResult | void;
|
||||
deactivate(host: CompilerHost): CompilerPluginDeactivationResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the supported shape of the main module for a compiler plugin.
|
||||
*/
|
||||
export interface CompilerPluginModule {
|
||||
/**
|
||||
* The `activate` hook is invoked when a plugin is activated for the first time within a `Program`.
|
||||
*/
|
||||
activate?(context: CompilerPluginContext, args: CompilerPluginActivationArgs): CompilerPluginActivationResult | void;
|
||||
/**
|
||||
* The `preParse` hook is invoked when a new `Program` is about to be created before any files are parsed.
|
||||
*/
|
||||
preParse?(context: CompilerPluginContext, args: CompilerPluginPreParseArgs): CompilerPluginPreParseResult | void;
|
||||
/**
|
||||
* The `preEmit` hook is invoked after type check has completed and immediately before emit.
|
||||
*/
|
||||
preEmit?(context: CompilerPluginContext, args: CompilerPluginPreEmitArgs): CompilerPluginPreEmitResult | void;
|
||||
/**
|
||||
* The `deactivate` hook is invoked when a plugin should be deactivated so that it can free up any shared resources.
|
||||
*/
|
||||
deactivate?(context: CompilerPluginContext): void;
|
||||
}
|
||||
|
||||
export interface CompilerPluginResult {
|
||||
diagnostics?: ReadonlyArray<Diagnostic>;
|
||||
}
|
||||
|
||||
export interface CompilerPluginActivationArgs {
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional result that can be returned from the `CompilerPluginModule.activate` hook.
|
||||
*/
|
||||
export interface CompilerPluginActivationResult extends CompilerPluginResult {
|
||||
}
|
||||
|
||||
export interface CompilerPluginPreParseArgs {
|
||||
readonly rootNames: ReadonlyArray<string>;
|
||||
readonly projectReferences: ReadonlyArray<ProjectReference> | undefined;
|
||||
}
|
||||
|
||||
export interface CompilerPluginPreParseResult extends CompilerPluginResult {
|
||||
compilerHost?: CompilerHost;
|
||||
rootNames?: ReadonlyArray<string>;
|
||||
projectReferences?: ReadonlyArray<ProjectReference>;
|
||||
}
|
||||
|
||||
export interface CompilerPluginPostCreateProgramArgs {
|
||||
readonly program: Program;
|
||||
}
|
||||
|
||||
export interface CompilerPluginPostCreateProgramResult extends CompilerPluginResult {
|
||||
}
|
||||
|
||||
export interface CompilerPluginPreEmitArgs {
|
||||
/** The current `Program`. */
|
||||
readonly program: Program;
|
||||
/** The `SourceFile` that is about to be emitted, or `undefined` when emitting all outputs. */
|
||||
readonly targetSourceFile: SourceFile | undefined;
|
||||
/** A `CancellationToken` that can be used to abort an operation when running in the language service. */
|
||||
readonly cancellationToken: CancellationToken | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optional result that can be returned from the `CompilerPluginModule.preEmit` hook.
|
||||
*/
|
||||
export interface CompilerPluginPreEmitResult extends CompilerPluginResult {
|
||||
customTransformers?: CustomTransformers;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface CompilerPluginDeactivationResult extends CompilerPluginResult {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface ModuleLoaderHost extends ModuleResolutionHost {
|
||||
require(initialDir: string, moduleName: string): RequireResult;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../tsconfig-library-base",
|
||||
"compilerOptions": {
|
||||
"removeComments": false,
|
||||
"emitDeclarationOnly": true,
|
||||
"outFile": "../../built/local/api.out.js"
|
||||
},
|
||||
"files": [
|
||||
"pluginApi.ts"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../compiler", "prepend": true }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user