Conversation
petebacondarwin
left a comment
There was a problem hiding this comment.
From first commit message:
The template type checker is capable of recreating generic type bounds
in a different, ...
It looks like this phrase was not completed?
when the type
parameter emitting logic was introduces
typo
There was a problem hiding this comment.
Is this to help when running on Windows?
There was a problem hiding this comment.
Indeed. I haven't seen them fail but remembered from earlier that Windows would have used \r\n by default, causing assertions using \n to fail.
petebacondarwin
left a comment
There was a problem hiding this comment.
From the second commit message:
Type parameters with a default clause would incorrectly be emitted into
the typecheck file using the original `ts.TypeNode` for the default
clause, such that `ts.TypeReferenceNode`s within the default clause
would be invalid.
I didn't quite understand this sentence. Are you saying that it is not valid to have a ts.TypeNode inside a ts.TypeReferenceNode?
petebacondarwin
left a comment
There was a problem hiding this comment.
Nice work @JoostK.
If this PR means that the fallback is no longer necessary, should it be removed too?
There was a problem hiding this comment.
| * or null to indicate the no reference could be resolved, or that the reference can not be emitted. | |
| * or null to indicate that no reference could be resolved, or that the reference can not be emitted. |
Or even better start a new sentence?
| * or null to indicate the no reference could be resolved, or that the reference can not be emitted. | |
| * or null. | |
| * A value of null indicates that no reference could be resolved or that the reference can not be emitted. |
There was a problem hiding this comment.
| // If the type is a reference, consider the type not to be eligible for emitting. | |
| // If the type is a reference, consider the type to be eligible for emitting. |
???
There was a problem hiding this comment.
So would this test pass if Local was exported?
If so, should we add a test to demonstrate that?
There was a problem hiding this comment.
If Local were exported, then the type emitter would indeed have succeeded.
There's a test here: https://github.com/angular/angular/pull/42492/files#diff-66249b018abab813af0a8497c3308ede071069a30ebb22dbb4c860559ef1b406R119-R127
There was a problem hiding this comment.
Where does this test namespace come from and how would that look in practice?
There was a problem hiding this comment.
The test namespace comes from the test setup that creates a fake type reference node:
In the actual code, the rewritten type reference is created by ngtsc's ReferenceEmitter from the type-check's environment:
angular/packages/compiler-cli/src/ngtsc/typecheck/src/environment.ts
Lines 134 to 141 in 5161084
a4cee78 to
1b610d0
Compare
I added a note to clarify that an untranslated
The fallback continues to be necessary, as non-exported declarations cannot be translated by the type-emitter. |
|
Since this is still awaiting @alxhub review, I will go ahead and remove it from the merge queue for now. Please re-add |
There was a problem hiding this comment.
This is getting a bit too clever... it seems we're relying on the fact that this returns undefined for all other kinds of type nodes, correct? At the very least, we should have a comment here explaining:
- what kinds of nodes we want to return
INELIGIBLEfor, and why. - the mechanism by which eligible nodes end up getting selected.
There was a problem hiding this comment.
typeof INELIGIBLE here is {}, the empty interface type. Lots of things are assignable to it, including false.
If we want to make a singleton value, it'd be better to use a branded type instead:
type INELIGIBLE = {__brand: 'ineligible'};
const INELIGIBLE: INELIGIBLE = {} as INELIGIBLE;This ensures we don't accidentally create other values of this type besides the constant.
The template type checker is capable of recreating generic type bounds in a different context, rewriting type references along the way (if possible). This was previously done using a visitor that only supported a limited set of types, resulting in the inability to emit all sorts of types (even if they don't contain type references at all). The inability to emit generic type bounds was not critical when the type parameter emitting logic was introduced, as the compiler also has a fallback strategy of creating inline type constructors. However, this fallback is not available to the language service, resulting in inaccurate types when components/directives use a complex generic type. To mitigate this problem, the specialized visitor has been replaced with a generalized TypeScript transform, where only type references get special treatment. This allows for more complex types to be emitted, such as union and intersection types, object literal types and tuple types.
…r default When a component/directive has a generic type parameter, the template type checker attempts to translate the type parameter such that the type parameters can be replicated in the type constructor that is emitted into the typecheck file. Type parameters with a default clause would incorrectly be emitted into the typecheck file using the original `ts.TypeNode` for the default clause, such that `ts.TypeReferenceNode`s within the default clause would likely be invalid (i.e. referencing a type for which no import is present in the typecheck file). This did not result in user-facing type-check errors as errors reported in type constructors are not translated into template positions Regardless, this commit ensures that `ts.TypeReferenceNode`s within defaults are properly translated into the typecheck file.
… emitter Previously, the template type checker would only opt-in to inline type constructors if it could import all type references from absolute module specifiers. This limitation was put into place in an abundance of caution as there was a safe, but less performant, fallback available. The language service is not capable of using this fallback, which now means that the limitation of absolute module specifiers limits the language service's ability to use accurate types for component/directive classes that have generic type parameters. This commit loosens the restriction such that type references are now eligible for emit as long as they are exported.
1b610d0 to
1b961a6
Compare
…ers (#42492) The template type checker is capable of recreating generic type bounds in a different context, rewriting type references along the way (if possible). This was previously done using a visitor that only supported a limited set of types, resulting in the inability to emit all sorts of types (even if they don't contain type references at all). The inability to emit generic type bounds was not critical when the type parameter emitting logic was introduced, as the compiler also has a fallback strategy of creating inline type constructors. However, this fallback is not available to the language service, resulting in inaccurate types when components/directives use a complex generic type. To mitigate this problem, the specialized visitor has been replaced with a generalized TypeScript transform, where only type references get special treatment. This allows for more complex types to be emitted, such as union and intersection types, object literal types and tuple types. PR Close #42492
…r default (#42492) When a component/directive has a generic type parameter, the template type checker attempts to translate the type parameter such that the type parameters can be replicated in the type constructor that is emitted into the typecheck file. Type parameters with a default clause would incorrectly be emitted into the typecheck file using the original `ts.TypeNode` for the default clause, such that `ts.TypeReferenceNode`s within the default clause would likely be invalid (i.e. referencing a type for which no import is present in the typecheck file). This did not result in user-facing type-check errors as errors reported in type constructors are not translated into template positions Regardless, this commit ensures that `ts.TypeReferenceNode`s within defaults are properly translated into the typecheck file. PR Close #42492
… emitter (#42492) Previously, the template type checker would only opt-in to inline type constructors if it could import all type references from absolute module specifiers. This limitation was put into place in an abundance of caution as there was a safe, but less performant, fallback available. The language service is not capable of using this fallback, which now means that the limitation of absolute module specifiers limits the language service's ability to use accurate types for component/directive classes that have generic type parameters. This commit loosens the restriction such that type references are now eligible for emit as long as they are exported. PR Close #42492
…r default (#42492) When a component/directive has a generic type parameter, the template type checker attempts to translate the type parameter such that the type parameters can be replicated in the type constructor that is emitted into the typecheck file. Type parameters with a default clause would incorrectly be emitted into the typecheck file using the original `ts.TypeNode` for the default clause, such that `ts.TypeReferenceNode`s within the default clause would likely be invalid (i.e. referencing a type for which no import is present in the typecheck file). This did not result in user-facing type-check errors as errors reported in type constructors are not translated into template positions Regardless, this commit ensures that `ts.TypeReferenceNode`s within defaults are properly translated into the typecheck file. PR Close #42492
… emitter (#42492) Previously, the template type checker would only opt-in to inline type constructors if it could import all type references from absolute module specifiers. This limitation was put into place in an abundance of caution as there was a safe, but less performant, fallback available. The language service is not capable of using this fallback, which now means that the limitation of absolute module specifiers limits the language service's ability to use accurate types for component/directive classes that have generic type parameters. This commit loosens the restriction such that type references are now eligible for emit as long as they are exported. PR Close #42492
…arameters in a different file In angular#42492 the template type checker became capable of replicating a wider range of generic type parameters for use in template type-check files. Any literal types within a type parameter would however emit invalid code, as TypeScript was emitting the literals using the text as extracted from the template type-check file instead of the original source file where the type node was taken from. This commit works around the issue by cloning any literal types and marking them as synthetic, signalling to TypeScript that the literal text has to be extracted from the node itself instead from the source file. This commit also excludes `import()` type nodes from being supported, as their module specifier may potentially need to be rewritten. Fixes angular#42667
…arameters in a different file (#42761) In #42492 the template type checker became capable of replicating a wider range of generic type parameters for use in template type-check files. Any literal types within a type parameter would however emit invalid code, as TypeScript was emitting the literals using the text as extracted from the template type-check file instead of the original source file where the type node was taken from. This commit works around the issue by cloning any literal types and marking them as synthetic, signalling to TypeScript that the literal text has to be extracted from the node itself instead from the source file. This commit also excludes `import()` type nodes from being supported, as their module specifier may potentially need to be rewritten. Fixes #42667 PR Close #42761
…arameters in a different file (#42761) In #42492 the template type checker became capable of replicating a wider range of generic type parameters for use in template type-check files. Any literal types within a type parameter would however emit invalid code, as TypeScript was emitting the literals using the text as extracted from the template type-check file instead of the original source file where the type node was taken from. This commit works around the issue by cloning any literal types and marking them as synthetic, signalling to TypeScript that the literal text has to be extracted from the node itself instead from the source file. This commit also excludes `import()` type nodes from being supported, as their module specifier may potentially need to be rewritten. Fixes #42667 PR Close #42761
|
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
See individual commits