Skip to content

feat(@ngtools/webpack): expose TS TypeChecker from ng compiler plugin #11786

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

Merged
merged 1 commit into from
Aug 14, 2018

Conversation

vakrilov
Copy link
Contributor

@vakrilov vakrilov commented Aug 6, 2018

Expose the TypeScript Program created by the plugin, so that it can be used in custom platform transformers.This will allow to define custom platformTransformers similar to replace_bootstrap. They will need some way to get access to the TS program created by the plugin to make transformations.

We discussed this with @filipesilva in slack and he suggested to open a proper PR exposing the TS program and continue any discussions here.

@filipesilva
Copy link
Contributor

@alexeagle @hansl @clydin I'm ok with this change, which is needed for the NativeScript team to get the TS type checker during their transforms. WDYT?

@filipesilva filipesilva added the needs: discussion On the agenda for team meeting to determine next steps label Aug 7, 2018
@clydin
Copy link
Member

clydin commented Aug 7, 2018

I'd prefer if the platformTransformers option had an additional type option. Either a platform transformers factory function or a TS transformer factory array with an expanded context object to allow for access to the type checker. An advantage is that additional information could be passed in the future if needed.

For example,

export interface PlatformTransformationContext extends ts.TransformationContext {
  getTypeChecker(): ts.TypeChecker;
}
export type PlatformTransformerFactory<T extends ts.Node = ts.SourceFile> = (context: PlatformTransformationContext) => ts.Transformer<T>;

And then the plugin options:

{
  ...
  platformTransformers: TransformerFactory<ts.SourceFile>[] | PlatformTransformerFactory[];
  ...
}

@vakrilov
Copy link
Contributor Author

vakrilov commented Aug 8, 2018

@clydin I like your suggestion, because it leaves the door open for further extensibility.

What is not clear to me is whether you have control over what context is passed to the transformers.
I can see in the code that all transformers are ultimately pushed into an array and passed to the program in emit. Isn't the TypeScript code that calls and executes the transformers?

@vakrilov
Copy link
Contributor Author

vakrilov commented Aug 8, 2018

Actually, in AOT case the AngularCompilerProgram is used, but at the end of the day it calls the emit method of the underlying ts.Program (or at least that is what I inferred form the code, might be wrong 😄). Still not sure if there is a way to pass an "extended" context to the transformers.

One other approach might be to pass in a platformTransfromersFactory (similar to the actual replaceBootstrap function) in the plugin options. It can accept a context similar to the one you proposed. Not sure if it worth to bloat the API with yet another such option though.

@clydin
Copy link
Member

clydin commented Aug 8, 2018

Replacing here with something similar to the following may work:

for (const platformTransformer of this._platformTransformers) {
  this._transformers.push(context => platformTransformer({ ...context, getTypeChecker }));
}

@vakrilov
Copy link
Contributor Author

vakrilov commented Aug 9, 2018

Hey @clydin I've tried this approach and as far the API goes - it works. We get the extended context.

However, this leaves us a little further form the the original goal of implementing replace_bootstrap for NativeScript projects while reusing as much code as possible 😄 . The reason fo this is that we cannot reuse the makeTransform and StandardTransforms as these actually create the TransformerFactory that gets the extended context.

In reality there are only small differences in the NativeScript bootstrap (the name of the platform and the module form where it is imported). That's why we are hopping to reuse most of the APIs so that there is less code to keep in sync.

@clydin
Copy link
Member

clydin commented Aug 9, 2018

The transformers are due for a general refactoring. As a result, I wouldn't be overly concerned about reuse. The current setup performs multiple full AST walks which has potential performance concerns. The need to pass getTypeChecker around is also a concern (ideally it should be part of the actual TypeScript interface). The bootstrap replacer also only performs a limited amount of AST analysis in regards to bootstrap discovery. There was a WIP PR that started some of this work for the bootstrap replacement but was unfortunately left unfinished here.

@@ -174,6 +174,10 @@ export class AngularCompilerPlugin {
return { path, className };
}

get typescriptProgram(): ts.Program {
return this._getTsProgram();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return just the typechecker here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can also be unavailable during certain points in the compilation lifecycle so should also return null in those cases.

@alexeagle
Copy link
Contributor

Let's keep the simple code you have, with one comment.

@vakrilov vakrilov changed the title feat(@ngtools/webpack): expose TS Program from ng compiler plugin feat(@ngtools/webpack): expose TS TypeChecker from ng compiler plugin Aug 10, 2018
@filipesilva filipesilva removed the needs: discussion On the agenda for team meeting to determine next steps label Aug 10, 2018
…ugin

Expose the TypeScript Program created by the plugin, so that it can be used in custom platform transformers.
@clydin clydin added the target: major This PR is targeted for the next major release label Aug 13, 2018
@alexeagle alexeagle requested review from alexeagle and removed request for alexeagle August 14, 2018 00:01
@alexeagle alexeagle merged commit 311723d into angular:master Aug 14, 2018
@vakrilov vakrilov deleted the expose-ts-program branch August 14, 2018 05:46
sis0k0 pushed a commit to NativeScript/nativescript-dev-webpack that referenced this pull request Aug 17, 2018
The bootstrap transformer will automatically replace the platform and bootstrap calls inside `main.ts` when building with AOT.
This will eliminate the need for `main.aot.ts` and `app.module.ngfactory.d.ts` files in templates.

This depends on angular/angular-cli#11786 going public
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants