Skip to content

feat(ivy): initial ngcc code dump#24897

Closed
petebacondarwin wants to merge 15 commits into
masterfrom
ngcc
Closed

feat(ivy): initial ngcc code dump#24897
petebacondarwin wants to merge 15 commits into
masterfrom
ngcc

Conversation

@petebacondarwin
Copy link
Copy Markdown
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

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

Does this PR introduce a breaking change?

[ ] Yes
[x] No

@petebacondarwin petebacondarwin added feature Label used to distinguish feature request from other issues area: build & ci Related the build and CI infrastructure of the project action: review The PR is still awaiting reviews from at least one requested reviewer hotlist: angular-core-team area: core Issues related to the framework runtime target: major This PR is targeted for the next major release labels Jul 16, 2018
@petebacondarwin petebacondarwin added this to the Ivy milestone Jul 16, 2018
@googlebot
Copy link
Copy Markdown

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 cla/google commit status will not change from this state. It's up to you to confirm consent of the commit author(s) and merge this pull request when appropriate.


getAllImports(contextPath: string, rewriteCoreImportsTo: ts.SourceFile|null):
{name: string, as: string}[] {
{ name: string, as: string }[] {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oops I guess I have a different curly brace formatting approach!

}
return `Error: ${message}`;
});
throw new Error(`Typescript diagnostics failed! ${errors.join(', ')}`);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not all source files are TypeScript :-P

@petebacondarwin petebacondarwin force-pushed the ngcc branch 3 times, most recently from ae04929 to ee37256 Compare July 16, 2018 13:19
@mary-poppins
Copy link
Copy Markdown

You can preview ee37256 at https://pr24897-ee37256.ngbuilds.io/.

Copy link
Copy Markdown
Member

@alxhub alxhub left a comment

Choose a reason for hiding this comment

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

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) ||
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Add ts.FunctionExpression to the type discriminator signature.


export function getFakeCore() {
return {
name: 'node_modules/@angular/core/index.ts',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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)?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, you can have e.g:

@HostListener('click')
onClick(): void {...}

@HostBinding('class.foo')
get isClassFoo(): boolean { ... }

Copy link
Copy Markdown
Contributor Author

@petebacondarwin petebacondarwin Jul 18, 2018

Choose a reason for hiding this comment

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

@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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Declare the return type.

* In ESM5 there is no "class" so the constructor that we want is actually the declaration
* function itself.
*/
protected getConstructorParameterDeclarations(classSymbol: ts.Symbol) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Declare return type, and throughout.

* ```
*/
protected getConstructorDecorators(classSymbol: ts.Symbol) {
if (classSymbol.exports && classSymbol.exports.has(CONSTRUCTOR_PARAMS)) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Consider inverting the logic here, with early returns if the preconditions aren't met, instead of nested if statements.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Explicit return


// 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?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think it'll matter. Top of the file should be fine.

@mary-poppins
Copy link
Copy Markdown

You can preview 493098b at https://pr24897-493098b.ngbuilds.io/.

@mary-poppins
Copy link
Copy Markdown

You can preview 51cc660 at https://pr24897-51cc660.ngbuilds.io/.

@petebacondarwin petebacondarwin force-pushed the ngcc branch 2 times, most recently from da93817 to 082c994 Compare July 18, 2018 13:44
@mary-poppins
Copy link
Copy Markdown

You can preview 082c994 at https://pr24897-082c994.ngbuilds.io/.

@googlebot
Copy link
Copy Markdown

CLAs look good, thanks!

IgorMinar pushed a commit that referenced this pull request Jul 28, 2018
This supports use cases needed by ngcc, where the compilation
needs to be configured for JavaScript differently to normal TypeScript.

PR Close #24897
IgorMinar pushed a commit that referenced this pull request Jul 28, 2018
IgorMinar pushed a commit that referenced this pull request Jul 28, 2018
IgorMinar pushed a commit that referenced this pull request Jul 28, 2018
IgorMinar pushed a commit that referenced this pull request Jul 28, 2018
@gkalpak
Copy link
Copy Markdown
Member

gkalpak commented Jul 28, 2018

AFAICT, this change was dropped from this PR (possibly due to a bad rebase?).
I will add it back in #25090.

@angular-automatic-lock-bot
Copy link
Copy Markdown

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 13, 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 area: build & ci Related the build and CI infrastructure of the project area: core Issues related to the framework runtime cla: yes feature Label used to distinguish feature request from other issues 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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants