fix(ivy): ngcc - identify all ESM5 decorated classes (#27848)
In ESM5 decorated classes can be indicated by calls to `__decorate()`. Previously the `ReflectionHost.findDecoratedClasses()` call would identify helper calls of the form: ``` SomeClass = tslib_1.__decorate(...); ``` But it was missing calls of the form: ``` SomeClass = SomeClass_1 = tslib_1.__decorate(...); ``` This form is common in `@NgModule()` decorations, where the class being decorated is referenced inside the decorator or another member. This commit now ensures that a chain of assignments, of any length, is now identified as a class decoration if it results in a call to `__decorate()`. Fixes #27841 PR Close #27848
This commit is contained in:
parent
d505468fb7
commit
e31afb7118
|
@ -12,7 +12,7 @@
|
|||
"master": {
|
||||
"uncompressed": {
|
||||
"runtime": 1440,
|
||||
"main": 507677,
|
||||
"main": 584077,
|
||||
"polyfills": 38390
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
|
||||
"@angular/animations@file:../../dist/packages-dist/animations":
|
||||
version "7.1.0"
|
||||
version "7.2.0-rc.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
|||
parse5 "^5.0.0"
|
||||
|
||||
"@angular/common@file:../../dist/packages-dist/common":
|
||||
version "7.1.0"
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/compiler-cli@file:../../dist/packages-dist/compiler-cli":
|
||||
version "7.1.0"
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
canonical-path "1.0.0"
|
||||
chokidar "^1.4.2"
|
||||
|
@ -37,22 +37,22 @@
|
|||
yargs "9.0.1"
|
||||
|
||||
"@angular/compiler@file:../../dist/packages-dist/compiler":
|
||||
version "7.1.0"
|
||||
version "7.2.0-rc.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/core@file:../../dist/packages-dist/core":
|
||||
version "7.1.0"
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/forms@file:../../dist/packages-dist/forms":
|
||||
version "7.1.0"
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/http@file:../../dist/packages-dist/http":
|
||||
version "7.1.0"
|
||||
version "7.2.0-rc.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
|
@ -66,17 +66,17 @@
|
|||
parse5 "^5.0.0"
|
||||
|
||||
"@angular/platform-browser-dynamic@file:../../dist/packages-dist/platform-browser-dynamic":
|
||||
version "7.1.0"
|
||||
version "7.2.0-rc.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/platform-browser@file:../../dist/packages-dist/platform-browser":
|
||||
version "7.1.0"
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
"@angular/router@file:../../dist/packages-dist/router":
|
||||
version "7.1.0"
|
||||
version "0.0.0"
|
||||
dependencies:
|
||||
tslib "^1.9.0"
|
||||
|
||||
|
@ -3278,7 +3278,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
|||
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
||||
|
||||
"typescript@file:../../node_modules/typescript":
|
||||
version "3.1.1"
|
||||
version "3.2.2"
|
||||
|
||||
ua-parser-js@0.7.17:
|
||||
version "0.7.17"
|
||||
|
|
|
@ -661,8 +661,10 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
|||
*/
|
||||
protected getHelperCall(statement: ts.Statement, helperName: string): ts.CallExpression|null {
|
||||
if (ts.isExpressionStatement(statement)) {
|
||||
const expression =
|
||||
isAssignmentStatement(statement) ? statement.expression.right : statement.expression;
|
||||
let expression = statement.expression;
|
||||
while (isAssignment(expression)) {
|
||||
expression = expression.right;
|
||||
}
|
||||
if (ts.isCallExpression(expression) && getCalleeName(expression) === helperName) {
|
||||
return expression;
|
||||
}
|
||||
|
|
|
@ -304,6 +304,27 @@ describe('Esm5ReflectionHost [import helper style]', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('findDecoratedClasses', () => {
|
||||
it('should return an array of all decorated classes in the given source file', () => {
|
||||
const program = makeTestProgram(...fileSystem.files);
|
||||
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
|
||||
|
||||
const ngModuleFile = program.getSourceFile('/ngmodule.js') !;
|
||||
const ngModuleClasses = host.findDecoratedClasses(ngModuleFile);
|
||||
expect(ngModuleClasses.length).toEqual(1);
|
||||
const ngModuleClass = ngModuleClasses.find(c => c.name === 'HttpClientXsrfModule') !;
|
||||
expect(ngModuleClass.decorators.map(decorator => decorator.name)).toEqual(['NgModule']);
|
||||
|
||||
const someDirectiveFile = program.getSourceFile('/some_directive.js') !;
|
||||
const someDirectiveClasses = host.findDecoratedClasses(someDirectiveFile);
|
||||
expect(someDirectiveClasses.length).toEqual(1);
|
||||
const someDirectiveClass = someDirectiveClasses.find(c => c.name === 'SomeDirective') !;
|
||||
expect(someDirectiveClass.decorators.map(decorator => decorator.name)).toEqual([
|
||||
'Directive'
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDeclarationOfIdentifier', () => {
|
||||
it('should return the declaration of a locally defined identifier', () => {
|
||||
const program = makeTestProgram(fileSystem.files[0]);
|
||||
|
|
Loading…
Reference in New Issue