Skip to content

Code generation extensibility point #9849

Closed
@weswigham

Description

@weswigham

@alexeagle from @angular has asked for a code generation extensibility point as part of #9038.

A code generation extension should be able to:

  • Access the program after (or during) parsing, but before typechecking
  • Inject new (already parsed) source files (not necessarily backed by files in the host) into the compilation

Proposed API shape:

interface CodegenProviderStatic {
  readonly ["extension-kind"]: "codegen";
  new (context: {
    ts: typeof ts,
    args: any,
    getCommonSourceDirectory: () => string,
    getCurrentDirectory: () => string,
    getCompilerOptions: () => CompilerOptions, // NOTE: These are unverified at this stage
    /**
     * addSourceFile causes processRootFile to be called on the provided SourceFile
     * and the file to be added to the filesByName map inside the Program
     */
    addSourceFile: (file: SourceFile) => void
  }): CodegenProvider
}

interface CodegenProvider {
  /**
   * Called each time a file is added to the filesByName set in a program
   *  - should trigger when a generated file is added, this way your
   *    generated code can cause code to generate
   */
  sourceFileFound?(file: SourceFile): void;
  /**
   * Called when all processing is complete and the program is about to be returned,
   * giving you the opportunity to finalize your emitted set of generated files
   */
  processingComplete?(program: Program): void; 
}

My immediate thought after taking a cursory glance as implementing this:

  • Do injected files need to affect module resolution? (Are they actually discoverable by other files' imports, or are they just compiled as part of the project? Discoverability could be difficult as module resolution hosts aren't expected to layer on pre-resolved paths or virtual filesystems - maybe this is best dealt with by coordination with a provided host?)
  • A program cannot be provided in the constructor, as it has to be constructed before we start traversing files - so before a program is available. I've tried to make the things from the program you'd be likely to want available, so hopefully that's good enough.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions