Skip to content

refactor(ivy): correctly type class declarations#29209

Closed
gkalpak wants to merge 11 commits intoangular:masterfrom
gkalpak:fix-ivy-ngcc-es5-class
Closed

refactor(ivy): correctly type class declarations#29209
gkalpak wants to merge 11 commits intoangular:masterfrom
gkalpak:fix-ivy-ngcc-es5-class

Conversation

@gkalpak
Copy link
Member

@gkalpak gkalpak commented Mar 10, 2019

Previously, several ngtsc and ngcc APIs dealing with class declaration nodes used inconsistent types. For example, some methods of the DecoratorHandler interface expected a ts.Declaration argument, but actual DecoratorHandler implementations specified a stricter ts.ClassDeclaration type.

As a result, the stricter methods would operate under the incorrect assumption that their arguments were of type ts.ClassDeclaration, while the actual arguments might be of different types (e.g. ngcc would call them with ts.FunctionDeclaration or ts.VariableDeclaration arguments, when compiling ES5 code).

Additionally, since we need those class declarations to be referenced in other parts of the program, ngtsc/ngcc had to either repeatedly check for ts.isIdentifier(node.name) or assume there was a name identifier and use node.name!. While this assumption happens to be true in the current implementation, working around type-checking is error-prone (e.g. the assumption might stop being true in the future).

This commit fixes this by introducing a new type to be used for such class declarations (ts.Declaration & {name: ts.Identifier}) and using it consistently throughput the code.

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Jira issue: FW-1151

Copy link
Contributor

Choose a reason for hiding this comment

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

=== undefined?

Copy link
Member Author

Choose a reason for hiding this comment

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

😁 (It's a draft 😇)

@gkalpak gkalpak force-pushed the fix-ivy-ngcc-es5-class branch 3 times, most recently from 0d88d10 to dc19808 Compare March 11, 2019 07:34
@kara kara added the comp: ivy label Mar 12, 2019
@ngbot ngbot bot added this to the needsTriage milestone Mar 12, 2019
Copy link
Contributor

@petebacondarwin petebacondarwin left a comment

Choose a reason for hiding this comment

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

I know this is still draft but as it might solve my problem I started to look at it.
I like the idea of a new ClassDeclaration type. This kind of abstraction fits well with our general approach to hiding the internals of the TS AST. I believe we should go a bit further and use it wherever we can to hide the use of ts.ClassDeclaration.
I also think that the code would be easier to decipher if we added new alias types for InnerClassDeclaration and OuterClassDeclaration (or perhaps just let the latter be ClassDeclaration).

Copy link
Contributor

Choose a reason for hiding this comment

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

We ought to be able to move all such typings from clazz: ts.Declaration to the new ClassDeclaration type, I believe.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I was thinking about that, but (a) wasn't sure if these methods are only called with ClassDeclaration (and didn't bother finding out 😁) and (b) I didn't want to make unnecessary changes (i.e. I only fixed the necessary signatures and then made necessary changes for typechecking to be happy).

Happy to go "all in" 😁

Copy link
Contributor

Choose a reason for hiding this comment

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

Making functions like these into protected methods on the host would have two benefits:

  1. we can avoid having to pass the typechecker as a parameter since it is a member of the host.
  2. we can override it in a future UmdReflectionHost that might need slightly different behaviour.

Copy link
Member Author

Choose a reason for hiding this comment

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

It didn't use the TypeChecker in an earlier implementation, but totally makes sense now.
(Personally, I would turn all standalone functions into methods (or move them to a utils file if they are generic and re-usable).)

@gkalpak gkalpak force-pushed the fix-ivy-ngcc-es5-class branch from dc19808 to 5fba061 Compare March 12, 2019 09:19
@gkalpak gkalpak force-pushed the fix-ivy-ngcc-es5-class branch 6 times, most recently from a4721f6 to 9db9df5 Compare March 13, 2019 15:49
@gkalpak
Copy link
Member Author

gkalpak commented Mar 13, 2019

I also think that the code would be easier to decipher if we added new alias types for InnerClassDeclaration and OuterClassDeclaration (or perhaps just let the latter be ClassDeclaration).

I briefly looked into it, but I didn't where how it would be useful. If it's an ES5 thing only, we can't use it outside of Esm5ReflectionHost, and many (most?) methods can receive either one, so 🤷‍♂️

@gkalpak gkalpak added type: bug/fix action: review The PR is still awaiting reviews from at least one requested reviewer target: major This PR is targeted for the next major release labels Mar 13, 2019
@gkalpak gkalpak marked this pull request as ready for review March 13, 2019 16:19
@gkalpak gkalpak requested review from a team March 13, 2019 16:19
@gkalpak
Copy link
Member Author

gkalpak commented Mar 13, 2019

BTW, one optimization that can be done is memoizing [outer variable declaration <--> inner function declaration] pairs, so that we don't have to walk the AST in order to get from one to the other. I was going to do that, but maybe not worth it if this code is going to be refactored as part of #29119 anyway.

@gkalpak gkalpak force-pushed the fix-ivy-ngcc-es5-class branch from 9db9df5 to cf9abf9 Compare March 14, 2019 10:31
@gkalpak gkalpak mentioned this pull request Mar 14, 2019
16 tasks
@gkalpak gkalpak added merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Mar 20, 2019
@ngbot
Copy link

ngbot bot commented Mar 20, 2019

I see that you just added the PR action: merge label, but the following checks are still failing:
    failure status "ci/circleci: material-unit-tests" is failing
    pending status "google3" is pending
    pending 1 pending code review

If you want your PR to be merged, it has to pass all the CI checks.

If you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help.

@gkalpak
Copy link
Member Author

gkalpak commented Mar 20, 2019

merge-assistance: The material-unit-tests failures are unrelated to this PR (and will be fixed by #29416).

gkalpak added 11 commits March 21, 2019 19:47
Previously, several `ngtsc` and `ngcc` APIs dealing with class
declaration nodes used inconsistent types. For example, some methods of
the `DecoratorHandler` interface expected a `ts.Declaration` argument,
but actual `DecoratorHandler` implementations specified a stricter
`ts.ClassDeclaration` type.

As a result, the stricter methods would operate under the incorrect
assumption that their arguments were of type `ts.ClassDeclaration`,
while the actual arguments might be of different types (e.g. `ngcc`
would call them with `ts.FunctionDeclaration` or
`ts.VariableDeclaration` arguments, when compiling ES5 code).

Additionally, since we need those class declarations to be referenced in
other parts of the program, `ngtsc`/`ngcc` had to either repeatedly
check for `ts.isIdentifier(node.name)` or assume there was a `name`
identifier and use `node.name!`. While this assumption happens to be
true in the current implementation, working around type-checking is
error-prone (e.g. the assumption might stop being true in the future).

This commit fixes this by introducing a new type to be used for such
class declarations (`ts.Declaration & {name: ts.Identifier}`) and using
it consistently throughput the code.
@gkalpak gkalpak force-pushed the fix-ivy-ngcc-es5-class branch from 322e6aa to 7ba59e1 Compare March 21, 2019 17:56
@mary-poppins
Copy link

You can preview 7ba59e1 at https://pr29209-7ba59e1.ngbuilds.io/.

@mhevery mhevery closed this in 70fffba Mar 21, 2019
mhevery pushed a commit that referenced this pull request Mar 21, 2019
mhevery pushed a commit that referenced this pull request Mar 21, 2019
…29209)

Previously, several `ngtsc` and `ngcc` APIs dealing with class
declaration nodes used inconsistent types. For example, some methods of
the `DecoratorHandler` interface expected a `ts.Declaration` argument,
but actual `DecoratorHandler` implementations specified a stricter
`ts.ClassDeclaration` type.

As a result, the stricter methods would operate under the incorrect
assumption that their arguments were of type `ts.ClassDeclaration`,
while the actual arguments might be of different types (e.g. `ngcc`
would call them with `ts.FunctionDeclaration` or
`ts.VariableDeclaration` arguments, when compiling ES5 code).

Additionally, since we need those class declarations to be referenced in
other parts of the program, `ngtsc`/`ngcc` had to either repeatedly
check for `ts.isIdentifier(node.name)` or assume there was a `name`
identifier and use `node.name!`. While this assumption happens to be
true in the current implementation, working around type-checking is
error-prone (e.g. the assumption might stop being true in the future).

This commit fixes this by introducing a new type to be used for such
class declarations (`ts.Declaration & {name: ts.Identifier}`) and using
it consistently throughput the code.

PR Close #29209
@gkalpak gkalpak deleted the fix-ivy-ngcc-es5-class branch March 22, 2019 14:08
wKoza pushed a commit to wKoza/angular that referenced this pull request Apr 17, 2019
wKoza pushed a commit to wKoza/angular that referenced this pull request Apr 17, 2019
wKoza pushed a commit to wKoza/angular that referenced this pull request Apr 17, 2019
…ngular#29209)

Previously, several `ngtsc` and `ngcc` APIs dealing with class
declaration nodes used inconsistent types. For example, some methods of
the `DecoratorHandler` interface expected a `ts.Declaration` argument,
but actual `DecoratorHandler` implementations specified a stricter
`ts.ClassDeclaration` type.

As a result, the stricter methods would operate under the incorrect
assumption that their arguments were of type `ts.ClassDeclaration`,
while the actual arguments might be of different types (e.g. `ngcc`
would call them with `ts.FunctionDeclaration` or
`ts.VariableDeclaration` arguments, when compiling ES5 code).

Additionally, since we need those class declarations to be referenced in
other parts of the program, `ngtsc`/`ngcc` had to either repeatedly
check for `ts.isIdentifier(node.name)` or assume there was a `name`
identifier and use `node.name!`. While this assumption happens to be
true in the current implementation, working around type-checking is
error-prone (e.g. the assumption might stop being true in the future).

This commit fixes this by introducing a new type to be used for such
class declarations (`ts.Declaration & {name: ts.Identifier}`) and using
it consistently throughput the code.

PR Close angular#29209
wKoza pushed a commit to wKoza/angular that referenced this pull request Apr 17, 2019
wKoza pushed a commit to wKoza/angular that referenced this pull request Apr 17, 2019
@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 14, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: merge The PR is ready for merge by the caretaker cla: yes merge: caretaker note Alert the caretaker performing the merge to check the PR for an out of normal action needed or note target: major This PR is targeted for the next major release type: bug/fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants