feat(ivy): initial ngcc code dump#24897
Conversation
|
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the |
|
|
||
| getAllImports(contextPath: string, rewriteCoreImportsTo: ts.SourceFile|null): | ||
| {name: string, as: string}[] { | ||
| { name: string, as: string }[] { |
There was a problem hiding this comment.
Oops I guess I have a different curly brace formatting approach!
| } | ||
| return `Error: ${message}`; | ||
| }); | ||
| throw new Error(`Typescript diagnostics failed! ${errors.join(', ')}`); |
There was a problem hiding this comment.
This block of changes just makes the error output a bit clearer - and is in keeping with how the TS compiler outputs errors.
| return undefined; | ||
| } | ||
| return ts.createSourceFile(fileName, contents, languageVersion, undefined, ts.ScriptKind.TS); | ||
| return ts.createSourceFile(fileName, contents, languageVersion); |
There was a problem hiding this comment.
Not all source files are TypeScript :-P
ae04929 to
ee37256
Compare
|
You can preview ee37256 at https://pr24897-ee37256.ngbuilds.io/. |
alxhub
left a comment
There was a problem hiding this comment.
Initial round of comments. Looks great! Should be only minor stylistic updates.
| function isFunctionOrMethodDeclaration(node: ts.Node): node is ts.FunctionDeclaration| | ||
| ts.MethodDeclaration { | ||
| return ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node); | ||
| return ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || |
There was a problem hiding this comment.
Add ts.FunctionExpression to the type discriminator signature.
|
|
||
| export function getFakeCore() { | ||
| return { | ||
| name: 'node_modules/@angular/core/index.ts', |
There was a problem hiding this comment.
Can you add a TODO here to unify this with the actual fake core library - I'd love to not have this duplicated.
| import * as ts from 'typescript'; | ||
|
|
||
| import {ClassMember, ClassMemberKind, Decorator, Parameter} from '../../../ngtsc/host'; | ||
| import {TypeScriptReflectionHost, reflectObjectLiteral} from '../../../ngtsc/metadata/src/reflector'; |
There was a problem hiding this comment.
Import only from ../../../ngtsc/metadata - if the types you need aren't re-exported through the index.ts there, then add them.
| * `null` if either no decorators were present or if the declaration is not of a decoratable type. | ||
| */ | ||
| getDecoratorsOfDeclaration(declaration: ts.Declaration): Decorator[]|null { | ||
| // QUESTION: do we need to consider decoratored functions (i.e. not ES5 class constructors)? |
There was a problem hiding this comment.
Yes, you can have e.g:
@HostListener('click')
onClick(): void {...}
@HostBinding('class.foo')
get isClassFoo(): boolean { ... }
There was a problem hiding this comment.
@alxhub - actually in practice this method is only called with a non-class from within methods on TypeScriptReflectionHost as an implementation detail. For instance inside getConstructorParameters() and _reflectMember(). All of these calls are in methods that are not called in the ESM2015 and ESM5 reflection host classes.
Moreover in ES2015 and ES5 there are occasions where a decorated property does not even have a declaration, so this method would not be applicable anyway.
Therefore I don't believe that this should be a requirement of the ReflectionHost interface.
Instead, can we rename this interface method to getDecoratorsOfClass(declaration: ts.Declaration) and then refactor the TypeScriptReflectionHost to have a protected method getDecoratorsOfDeclaration that can find decorators on any declaration, which is what is used internally for getDecoratorsOfClass and those methods mentioned above.
There was a problem hiding this comment.
Ah, understood and agreed. getDecoratorsOfClass makes more sense.
| if (decoratorsIdentifier && decoratorsIdentifier.parent) { | ||
| // AST of the array of decorator values | ||
| const decoratorsArray = | ||
| (decoratorsIdentifier.parent as ts.AssignmentExpression<ts.EqualsToken>).right; |
There was a problem hiding this comment.
I generally prefer to use the type guards and throw if something doesn't match, rather than cast. It's more verbose, but it helps catch edge cases that we didn't consider, especially when the TypeScript version updates and semantics change slightly.
| * So we need to dig around inside to get hold of the "class" symbol. | ||
| * @param declaration the top level declaration that represents an exported class. | ||
| */ | ||
| getClassSymbol(declaration: ts.Declaration) { |
| * In ESM5 there is no "class" so the constructor that we want is actually the declaration | ||
| * function itself. | ||
| */ | ||
| protected getConstructorParameterDeclarations(classSymbol: ts.Symbol) { |
There was a problem hiding this comment.
Declare return type, and throughout.
| * ``` | ||
| */ | ||
| protected getConstructorDecorators(classSymbol: ts.Symbol) { | ||
| if (classSymbol.exports && classSymbol.exports.has(CONSTRUCTOR_PARAMS)) { |
There was a problem hiding this comment.
Consider inverting the logic here, with early returns if the preconditions aren't met, instead of nested if statements.
There was a problem hiding this comment.
Actually I am sorely tempted to implement tsquery for a lot of this logic. It would be cleaner to read and easier to maintain.
| const decorators = this.host.getDecoratorsOfDeclaration(declaration); | ||
| if (decorators) { | ||
| return new ParsedClass(declaration.name !.text, declaration, decorators); | ||
| } |
|
|
||
| // Add the imports at the top of the file | ||
| addImports(output: MagicString, imports: {name: string; as: string;}[]): void { | ||
| // QUESTION: Should we move the imports to after any initial comment in the file? |
There was a problem hiding this comment.
I don't think it'll matter. Top of the file should be fine.
|
You can preview 493098b at https://pr24897-493098b.ngbuilds.io/. |
|
You can preview 51cc660 at https://pr24897-51cc660.ngbuilds.io/. |
da93817 to
082c994
Compare
|
You can preview 082c994 at https://pr24897-082c994.ngbuilds.io/. |
|
CLAs look good, thanks! |
This supports use cases needed by ngcc, where the compilation needs to be configured for JavaScript differently to normal TypeScript. PR Close #24897
|
AFAICT, this change was dropped from this PR (possibly due to a bad rebase?). |
|
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. |
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
Does this PR introduce a breaking change?