fix(ivy): include "variable-declared" decorated classes in ngcc compilation (#26236)
Previously, classes that were declared via variable declarations, rather than class declarations, were being excluded from the parsed classes. PR Close #26236
This commit is contained in:

committed by
Jason Aden

parent
7d08722e80
commit
44c05c05af
@ -24,20 +24,24 @@ export class Esm2015FileParser implements FileParser {
|
|||||||
const moduleSymbol = this.checker.getSymbolAtLocation(file);
|
const moduleSymbol = this.checker.getSymbolAtLocation(file);
|
||||||
const map = new Map<ts.SourceFile, ParsedFile>();
|
const map = new Map<ts.SourceFile, ParsedFile>();
|
||||||
if (moduleSymbol) {
|
if (moduleSymbol) {
|
||||||
const exportClasses = this.checker.getExportsOfModule(moduleSymbol)
|
const exportedSymbols =
|
||||||
.map(getOriginalSymbol(this.checker))
|
this.checker.getExportsOfModule(moduleSymbol).map(getOriginalSymbol(this.checker));
|
||||||
.filter(exportSymbol => exportSymbol.flags & ts.SymbolFlags.Class);
|
const exportedDeclarations =
|
||||||
|
exportedSymbols.map(exportSymbol => exportSymbol.valueDeclaration).filter(isDefined);
|
||||||
const classDeclarations = exportClasses.map(exportSymbol => exportSymbol.valueDeclaration)
|
|
||||||
.filter(isDefined)
|
|
||||||
.filter(ts.isClassDeclaration);
|
|
||||||
|
|
||||||
const decoratedClasses =
|
const decoratedClasses =
|
||||||
classDeclarations
|
exportedDeclarations
|
||||||
.map(declaration => {
|
.map(declaration => {
|
||||||
const decorators = this.host.getDecoratorsOfDeclaration(declaration);
|
if (ts.isClassDeclaration(declaration) || ts.isVariableDeclaration(declaration)) {
|
||||||
return decorators && declaration.name &&
|
const name = declaration.name && ts.isIdentifier(declaration.name) ?
|
||||||
new ParsedClass(declaration.name.text, declaration, decorators);
|
declaration.name.text :
|
||||||
|
undefined;
|
||||||
|
const decorators = this.host.getDecoratorsOfDeclaration(declaration);
|
||||||
|
return decorators && isDefined(name) ?
|
||||||
|
new ParsedClass(name, declaration, decorators) :
|
||||||
|
undefined;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
})
|
})
|
||||||
.filter(isDefined);
|
.filter(isDefined);
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import {makeProgram} from '../helpers/utils';
|
|||||||
const BASIC_FILE = {
|
const BASIC_FILE = {
|
||||||
name: '/primary.js',
|
name: '/primary.js',
|
||||||
contents: `
|
contents: `
|
||||||
|
import {Directive} from '@angular/core';
|
||||||
class A {}
|
class A {}
|
||||||
A.decorators = [
|
A.decorators = [
|
||||||
{ type: Directive, args: [{ selector: '[a]' }] }
|
{ type: Directive, args: [{ selector: '[a]' }] }
|
||||||
@ -31,12 +32,19 @@ const BASIC_FILE = {
|
|||||||
|
|
||||||
class C {}
|
class C {}
|
||||||
|
|
||||||
|
let D = class D {}
|
||||||
|
D = tslib_1.__decorate([
|
||||||
|
Directive({ selector: '[d]' }),
|
||||||
|
OtherD()
|
||||||
|
], D);
|
||||||
|
export {D};
|
||||||
|
|
||||||
export { A, x, C };
|
export { A, x, C };
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Esm2015PackageParser', () => {
|
describe('Esm2015FileParser', () => {
|
||||||
describe('getDecoratedClasses()', () => {
|
describe('parseFile()', () => {
|
||||||
it('should return an array of object for each class that is exported and decorated', () => {
|
it('should return an array of object for each class that is exported and decorated', () => {
|
||||||
const program = makeProgram(BASIC_FILE);
|
const program = makeProgram(BASIC_FILE);
|
||||||
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
|
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
|
||||||
@ -46,11 +54,19 @@ describe('Esm2015PackageParser', () => {
|
|||||||
|
|
||||||
expect(parsedFiles.length).toEqual(1);
|
expect(parsedFiles.length).toEqual(1);
|
||||||
const decoratedClasses = parsedFiles[0].decoratedClasses;
|
const decoratedClasses = parsedFiles[0].decoratedClasses;
|
||||||
expect(decoratedClasses.length).toEqual(1);
|
expect(decoratedClasses.length).toEqual(2);
|
||||||
const decoratedClass = decoratedClasses[0];
|
|
||||||
expect(decoratedClass.name).toEqual('A');
|
const decoratedClassA = decoratedClasses.find(c => c.name === 'A') !;
|
||||||
expect(ts.isClassDeclaration(decoratedClass.declaration)).toBeTruthy();
|
expect(decoratedClassA.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
|
||||||
expect(decoratedClass.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
|
expect(decoratedClassA.decorators.map(
|
||||||
|
decorator => decorator.args && decorator.args.map(arg => arg.getText())))
|
||||||
|
.toEqual([[`{ selector: '[a]' }`]]);
|
||||||
|
|
||||||
|
const decoratedClassD = decoratedClasses.find(c => c.name === 'D') !;
|
||||||
|
expect(decoratedClassD.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
|
||||||
|
expect(decoratedClassD.decorators.map(
|
||||||
|
decorator => decorator.args && decorator.args.map(arg => arg.getText())))
|
||||||
|
.toEqual([[`{ selector: '[d]' }`]]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
Reference in New Issue
Block a user