-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Code generation extensibility point #9849
Comments
Thanks for getting this started, Wes. Which API call actually causes the code generator to run? Would
Yes, this is one of our requirements - the user's entry point TypeScript source should import from a generated file, so that the resulting module dependency graph can be completely understood by a tree-shaking tool like Rollup/WebPack2. We currently do this by creating a new program after codegen and before type-check/emit. Here: https://github.com/angular/angular/blob/db54a84d1418950a9c1ad07f2553179cbf231135/tools/%40angular/tsc-wrapped/src/main.ts#L36
We had this issue as well. The only thing we need from the program is In your design, I see that the codegen gets another chance to run after new files get generated. We don't need this, and also this introduces the need to continue until there are no newly generated files, which seems prone to causing cycles in naive implementations. This may go without saying (and not require any provision in the design): it will be useful to generate non-TS files, for example the |
@alexeagle After looking over your code, I believe I can see that you shouldn't need either. You use You should just be able to write: class CodegenProvider {
// Most of CodeGenerator's utility functions here
sourceFileFound(file: SourceFile) {
if (GENERATED_FILES.test(file.fileName)) return;
const metadata = this.readFileMetadata(file.fileName);
const generatedModules = this.compiler.compileSync(metadata.fileUrl, this.compiler.analyzeModule(metadata.appModules), metadata.components, metadata.appModules);
generatedModules.forEach(module => {
const fullText = PREAMBLE + module.source;
const newFile = ts.createSourceFile(module.moduleUrl, fullText, ScriptTarget.ES6, /*setParentNodes*/true, ScriptKind.ES6);
this.host.writeFile(this.calculateEmitPath(module.moduleUrl), fullText, /*writeBOM*/false, () => {}, [newFile]);
this.addSourceFile(newFile);
});
}
} Also, quite blatantly, there is no way I can make this API work for for you if you cannot do template compilation synchronously (note how I wrote |
That API looks sufficient to me. We can do some experimentation to verify when the extension point is prototyped. We could walk through those APIs sometime - the short version is that they're structured to allow the compiler to be run in a few different environments, to separate codegen from the tsc-wrapped (avoiding the cyclical dependency of angular build depending on angular) and also to borrow TS logic for module->filepath, how compilerOptions affect which files to write where and when, etc. re. async - I believe these are all consequences of having an online compilation mode, where eg. template files may need to be loaded from the server with an XHR. We have a synchronous XHR in https://github.com/angular/angular/blob/master/modules/@angular/compiler-cli/src/codegen.ts#L124 - @tbosch is the expert on most of the APIs inside the compiler, but is on vacation. I suspect the tsc-based compiler can be entirely synchronous. Worst case we could just count down as files are written and block the caller until the count reaches zero. |
This is should be covered by #13940 |
@alexeagle from @angular has asked for a code generation extensibility point as part of #9038.
A code generation extension should be able to:
Proposed API shape:
My immediate thought after taking a cursory glance as implementing this:
The text was updated successfully, but these errors were encountered: