|
// actually will be just the .d.ts from compiler, plus the following declarations: |
|
export interface CompilerPluginContext { |
|
readonly compilerHost: CompilerHost; |
|
readonly compilerOptions: CompilerOptions; |
|
readonly options: MapLike<any>; // plugin config options |
|
} |
|
|
|
export type CompilerPluginHookResult<T> = PromiseLike<T> | T; |
|
|
|
export interface CompilerPluginModule { |
|
activate?(context: CompilerPluginContext, args: CompilerPluginActivationArgs): |
|
CompilerPluginHookResult<CompilerPluginActivationResult | void>; |
|
|
|
preParse?(context: CompilerPluginContext, args: CompilerPluginPreParseArgs): |
|
CompilerPluginHookResult<CompilerPluginPreParseResult | void>; |
|
|
|
preEmit?(context: CompilerPluginContext, args: CompilerPluginPreEmitArgs): |
|
CompilerPluginHookResult<CompilerPluginPreEmitResult | void>; |
|
|
|
deactivate?(context: CompilerPluginContext): CompilerPluginHookResult<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: readonly string[]; |
|
readonly projectReferences: readonly ProjectReference[] | undefined; |
|
} |
|
|
|
export interface CompilerPluginPreParseResult extends CompilerPluginResult { |
|
rootNames?: readonly string[]; |
|
projectReferences?: readonly ProjectReference[]; |
|
preprocessors?: readonly TransformerFactory<SourceFile>[]; |
|
} |
|
|
|
export interface CompilerPluginPreEmitArgs { |
|
/** The current `Program`. */ |
|
readonly program: BaseProgram; |
|
/** 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; |
|
} |
|
|
|
export interface CompilerPluginDeactivationResult extends CompilerPluginResult { |
|
} |
|
|
|
// NOTE: All factory methods originally on `ts` have been moved to `NodeFactory`, which is accessible |
|
// from the `factory` property of a transformation context. Existing factory methods exist for |
|
// backwards compatibility when using the full TypeScript Language Service or TS Server API, but |
|
// will not be accessible for Compiler Plugins. |
|
export interface NodeFactory { |
|
createNodeArray<T extends Node>(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray<T>; |
|
createNumericLiteral(value: string | number, numericLiteralFlags?: TokenFlags): NumericLiteral; |
|
... |
|
} |
|
|
|
export interface TransformationContext { |
|
// The `NodeFactory` you should use to create nodes. |
|
// NOTE: Preprocessors (returned from the `preParse` hook) and Emit Transformers (returned |
|
// from the `preEmit` hook) will be provided *different* `NodeFactory` instances and should not be conflated. |
|
readonly factory: NodeFactory; |
|
... |
|
} |
|
|
|
export interface BaseProgram { |
|
// essentially the same as `Program`, except the `emit` method is not provided. |
|
... |
|
} |
For the new Angular compiler, it looks like this would mostly work except:
CompilerOptions
, which don't seem to be available in the proposed API. For example, we callresolveModuleName
which requires theCompilerOptions
and aCompilerHost
.I believe the
TransformationContext
of a transform gives access to theCompilerOptions
, but this is too late in the lifecycle for our compiler.Program
and checking when it changes, but an explicit lifecycle for this would be much cleaner.Currently we know whether a
SourceFile
has changed by checking referential equality between the same file in the old and newProgram
s. Will this method still work?module.ts
might require that we re-emitcomponent.ts
, even ifcomponent.ts
hasn't changed on disk itself, because the transform output will have changed. Would a plugin be able to do this by callingProgram.emit
? I could see issues if that causedpreEmit
to be reentrant, or if it skipped over the plugin chain entirely.