fix(ivy): ngcc: only consider decorators from `@angular/core` (#26236)

PR Close #26236
This commit is contained in:
Pete Bacon Darwin 2018-09-27 21:21:43 +01:00 committed by Jason Aden
parent 50d1cba174
commit 6a24db2bc6
6 changed files with 154 additions and 168 deletions

View File

@ -336,7 +336,7 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
decoratorsIdentifier.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) { decoratorsIdentifier.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
// AST of the array of decorator values // AST of the array of decorator values
const decoratorsArray = decoratorsIdentifier.parent.right; const decoratorsArray = decoratorsIdentifier.parent.right;
return this.reflectDecorators(decoratorsArray); return this.reflectDecorators(decoratorsArray).filter(isImportedFromCore);
} }
} }
return null; return null;
@ -404,8 +404,12 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
const propDecoratorsMap = getPropertyValueFromSymbol(decoratorsProperty); const propDecoratorsMap = getPropertyValueFromSymbol(decoratorsProperty);
if (propDecoratorsMap && ts.isObjectLiteralExpression(propDecoratorsMap)) { if (propDecoratorsMap && ts.isObjectLiteralExpression(propDecoratorsMap)) {
const propertiesMap = reflectObjectLiteral(propDecoratorsMap); const propertiesMap = reflectObjectLiteral(propDecoratorsMap);
propertiesMap.forEach( propertiesMap.forEach((value, name) => {
(value, name) => { memberDecorators.set(name, this.reflectDecorators(value)); }); const decorators = this.reflectDecorators(value).filter(isImportedFromCore);
if (decorators.length) {
memberDecorators.set(name, decorators);
}
});
} }
return memberDecorators; return memberDecorators;
} }
@ -727,7 +731,8 @@ export class Fesm2015ReflectionHost extends TypeScriptReflectionHost implements
.map(paramInfo => { .map(paramInfo => {
const type = paramInfo && paramInfo.get('type') || null; const type = paramInfo && paramInfo.get('type') || null;
const decoratorInfo = paramInfo && paramInfo.get('decorators') || null; const decoratorInfo = paramInfo && paramInfo.get('decorators') || null;
const decorators = decoratorInfo && this.reflectDecorators(decoratorInfo); const decorators =
decoratorInfo && this.reflectDecorators(decoratorInfo).filter(isImportedFromCore);
return {type, decorators}; return {type, decorators};
}); });
} }

View File

@ -79,46 +79,42 @@ const FOO_FUNCTION_FILE = {
const INVALID_DECORATORS_FILE = { const INVALID_DECORATORS_FILE = {
name: '/invalid_decorators.js', name: '/invalid_decorators.js',
contents: ` contents: `
var NotArrayLiteralDecorator = {}; import { Directive } from '@angular/core';
var NotArrayLiteral = (function() { var NotArrayLiteral = (function() {
function NotArrayLiteral() { function NotArrayLiteral() {
} }
NotArrayLiteral.decorators = () => [ NotArrayLiteral.decorators = () => [
{ type: NotArrayLiteralDecorator, args: [{ selector: '[ignored]' },] }, { type: Directive, args: [{ selector: '[ignored]' },] },
]; ];
return NotArrayLiteral; return NotArrayLiteral;
}()); }());
var NotObjectLiteralDecorator = {};
var NotObjectLiteral = (function() { var NotObjectLiteral = (function() {
function NotObjectLiteral() { function NotObjectLiteral() {
} }
NotObjectLiteral.decorators = [ NotObjectLiteral.decorators = [
"This is not an object literal", "This is not an object literal",
{ type: NotObjectLiteralDecorator }, { type: Directive },
]; ];
return NotObjectLiteral; return NotObjectLiteral;
}()); }());
var NoTypePropertyDecorator1 = {};
var NoTypePropertyDecorator2 = {};
var NoTypeProperty = (function() { var NoTypeProperty = (function() {
function NoTypeProperty() { function NoTypeProperty() {
} }
NoTypeProperty.decorators = [ NoTypeProperty.decorators = [
{ notType: NoTypePropertyDecorator1 }, { notType: Directive },
{ type: NoTypePropertyDecorator2 }, { type: Directive },
]; ];
return NoTypeProperty; return NoTypeProperty;
}()); }());
var NotIdentifierDecorator = {};
var NotIdentifier = (function() { var NotIdentifier = (function() {
function NotIdentifier() { function NotIdentifier() {
} }
NotIdentifier.decorators = [ NotIdentifier.decorators = [
{ type: 'StringsLiteralsAreNotIdentifiers' }, { type: 'StringsLiteralsAreNotIdentifiers' },
{ type: NotIdentifierDecorator }, { type: Directive },
]; ];
return NotIdentifier; return NotIdentifier;
}()); }());
@ -128,33 +124,31 @@ const INVALID_DECORATORS_FILE = {
const INVALID_DECORATOR_ARGS_FILE = { const INVALID_DECORATOR_ARGS_FILE = {
name: '/invalid_decorator_args.js', name: '/invalid_decorator_args.js',
contents: ` contents: `
var NoArgsPropertyDecorator = {}; import { Directive } from '@angular/core';
var NoArgsProperty = (function() { var NoArgsProperty = (function() {
function NoArgsProperty() { function NoArgsProperty() {
} }
NoArgsProperty.decorators = [ NoArgsProperty.decorators = [
{ type: NoArgsPropertyDecorator }, { type: Directive },
]; ];
return NoArgsProperty; return NoArgsProperty;
}()); }());
var NoPropertyAssignmentDecorator = {};
var args = [{ selector: '[ignored]' },]; var args = [{ selector: '[ignored]' },];
var NoPropertyAssignment = (function() { var NoPropertyAssignment = (function() {
function NoPropertyAssignment() { function NoPropertyAssignment() {
} }
NoPropertyAssignment.decorators = [ NoPropertyAssignment.decorators = [
{ type: NoPropertyAssignmentDecorator, args }, { type: Directive, args },
]; ];
return NoPropertyAssignment; return NoPropertyAssignment;
}()); }());
var NotArrayLiteralDecorator = {};
var NotArrayLiteral = (function() { var NotArrayLiteral = (function() {
function NotArrayLiteral() { function NotArrayLiteral() {
} }
NotArrayLiteral.decorators = [ NotArrayLiteral.decorators = [
{ type: NotArrayLiteralDecorator, args: () => [{ selector: '[ignored]' },] }, { type: Directive, args: () => [{ selector: '[ignored]' },] },
]; ];
return NotArrayLiteral; return NotArrayLiteral;
}()); }());
@ -164,51 +158,47 @@ const INVALID_DECORATOR_ARGS_FILE = {
const INVALID_PROP_DECORATORS_FILE = { const INVALID_PROP_DECORATORS_FILE = {
name: '/invalid_prop_decorators.js', name: '/invalid_prop_decorators.js',
contents: ` contents: `
var NotObjectLiteralDecorator = {}; import { Input } from '@angular/core';
var NotObjectLiteral = (function() { var NotObjectLiteral = (function() {
function NotObjectLiteral() { function NotObjectLiteral() {
} }
NotObjectLiteral.propDecorators = () => ({ NotObjectLiteral.propDecorators = () => ({
"prop": [{ type: NotObjectLiteralDecorator },] "prop": [{ type: Input },]
}); });
return NotObjectLiteral; return NotObjectLiteral;
}()); }());
var NotObjectLiteralPropDecorator = {};
var NotObjectLiteralProp = (function() { var NotObjectLiteralProp = (function() {
function NotObjectLiteralProp() { function NotObjectLiteralProp() {
} }
NotObjectLiteralProp.propDecorators = { NotObjectLiteralProp.propDecorators = {
"prop": [ "prop": [
"This is not an object literal", "This is not an object literal",
{ type: NotObjectLiteralPropDecorator }, { type: Input },
] ]
}; };
return NotObjectLiteralProp; return NotObjectLiteralProp;
}()); }());
var NoTypePropertyDecorator1 = {};
var NoTypePropertyDecorator2 = {};
var NoTypeProperty = (function() { var NoTypeProperty = (function() {
function NoTypeProperty() { function NoTypeProperty() {
} }
NoTypeProperty.propDecorators = { NoTypeProperty.propDecorators = {
"prop": [ "prop": [
{ notType: NoTypePropertyDecorator1 }, { notType: Input },
{ type: NoTypePropertyDecorator2 }, { type: Input },
] ]
}; };
return NoTypeProperty; return NoTypeProperty;
}()); }());
var NotIdentifierDecorator = {};
var NotIdentifier = (function() { var NotIdentifier = (function() {
function NotIdentifier() { function NotIdentifier() {
} }
NotIdentifier.propDecorators = { NotIdentifier.propDecorators = {
"prop": [ "prop": [
{ type: 'StringsLiteralsAreNotIdentifiers' }, { type: 'StringsLiteralsAreNotIdentifiers' },
{ type: NotIdentifierDecorator }, { type: Input },
] ]
}; };
return NotIdentifier; return NotIdentifier;
@ -219,33 +209,31 @@ const INVALID_PROP_DECORATORS_FILE = {
const INVALID_PROP_DECORATOR_ARGS_FILE = { const INVALID_PROP_DECORATOR_ARGS_FILE = {
name: '/invalid_prop_decorator_args.js', name: '/invalid_prop_decorator_args.js',
contents: ` contents: `
var NoArgsPropertyDecorator = {}; import { Input } from '@angular/core';
var NoArgsProperty = (function() { var NoArgsProperty = (function() {
function NoArgsProperty() { function NoArgsProperty() {
} }
NoArgsProperty.propDecorators = { NoArgsProperty.propDecorators = {
"prop": [{ type: NoArgsPropertyDecorator },] "prop": [{ type: Input },]
}; };
return NoArgsProperty; return NoArgsProperty;
}()); }());
var NoPropertyAssignmentDecorator = {};
var args = [{ selector: '[ignored]' },]; var args = [{ selector: '[ignored]' },];
var NoPropertyAssignment = (function() { var NoPropertyAssignment = (function() {
function NoPropertyAssignment() { function NoPropertyAssignment() {
} }
NoPropertyAssignment.propDecorators = { NoPropertyAssignment.propDecorators = {
"prop": [{ type: NoPropertyAssignmentDecorator, args },] "prop": [{ type: Input, args },]
}; };
return NoPropertyAssignment; return NoPropertyAssignment;
}()); }());
var NotArrayLiteralDecorator = {};
var NotArrayLiteral = (function() { var NotArrayLiteral = (function() {
function NotArrayLiteral() { function NotArrayLiteral() {
} }
NotArrayLiteral.propDecorators = { NotArrayLiteral.propDecorators = {
"prop": [{ type: NotArrayLiteralDecorator, args: () => [{ selector: '[ignored]' },] },], "prop": [{ type: Input, args: () => [{ selector: '[ignored]' },] },],
}; };
return NotArrayLiteral; return NotArrayLiteral;
}()); }());
@ -255,23 +243,22 @@ const INVALID_PROP_DECORATOR_ARGS_FILE = {
const INVALID_CTOR_DECORATORS_FILE = { const INVALID_CTOR_DECORATORS_FILE = {
name: '/invalid_ctor_decorators.js', name: '/invalid_ctor_decorators.js',
contents: ` contents: `
import { Inject } from '@angular/core';
var NoParametersDecorator = {}; var NoParametersDecorator = {};
var NoParameters = (function() { var NoParameters = (function() {
function NoParameters() {} function NoParameters() {}
return NoParameters; return NoParameters;
}()); }());
var ArrowFunctionDecorator = {};
var ArrowFunction = (function() { var ArrowFunction = (function() {
function ArrowFunction(arg1) { function ArrowFunction(arg1) {
} }
ArrowFunction.ctorParameters = () => [ ArrowFunction.ctorParameters = () => [
{ type: 'ParamType', decorators: [{ type: ArrowFunctionDecorator },] } { type: 'ParamType', decorators: [{ type: Inject },] }
]; ];
return ArrowFunction; return ArrowFunction;
}()); }());
var NotArrayLiteralDecorator = {};
var NotArrayLiteral = (function() { var NotArrayLiteral = (function() {
function NotArrayLiteral(arg1) { function NotArrayLiteral(arg1) {
} }
@ -279,19 +266,16 @@ const INVALID_CTOR_DECORATORS_FILE = {
return NotArrayLiteral; return NotArrayLiteral;
}()); }());
var NotObjectLiteralDecorator = {};
var NotObjectLiteral = (function() { var NotObjectLiteral = (function() {
function NotObjectLiteral(arg1, arg2) { function NotObjectLiteral(arg1, arg2) {
} }
NotObjectLiteral.ctorParameters = function() { return [ NotObjectLiteral.ctorParameters = function() { return [
"This is not an object literal", "This is not an object literal",
{ type: 'ParamType', decorators: [{ type: NotObjectLiteralDecorator },] }, { type: 'ParamType', decorators: [{ type: Inject },] },
]; }; ]; };
return NotObjectLiteral; return NotObjectLiteral;
}()); }());
var NoTypePropertyDecorator1 = {};
var NoTypePropertyDecorator2 = {};
var NoTypeProperty = (function() { var NoTypeProperty = (function() {
function NoTypeProperty(arg1, arg2) { function NoTypeProperty(arg1, arg2) {
} }
@ -299,15 +283,14 @@ const INVALID_CTOR_DECORATORS_FILE = {
{ {
type: 'ParamType', type: 'ParamType',
decorators: [ decorators: [
{ notType: NoTypePropertyDecorator1 }, { notType: Inject },
{ type: NoTypePropertyDecorator2 }, { type: Inject },
] ]
}, },
]; }; ]; };
return NoTypeProperty; return NoTypeProperty;
}()); }());
var NotIdentifierDecorator = {};
var NotIdentifier = (function() { var NotIdentifier = (function() {
function NotIdentifier(arg1, arg2) { function NotIdentifier(arg1, arg2) {
} }
@ -316,7 +299,7 @@ const INVALID_CTOR_DECORATORS_FILE = {
type: 'ParamType', type: 'ParamType',
decorators: [ decorators: [
{ type: 'StringsLiteralsAreNotIdentifiers' }, { type: 'StringsLiteralsAreNotIdentifiers' },
{ type: NotIdentifierDecorator }, { type: Inject },
] ]
}, },
]; }; ]; };
@ -328,33 +311,31 @@ const INVALID_CTOR_DECORATORS_FILE = {
const INVALID_CTOR_DECORATOR_ARGS_FILE = { const INVALID_CTOR_DECORATOR_ARGS_FILE = {
name: '/invalid_ctor_decorator_args.js', name: '/invalid_ctor_decorator_args.js',
contents: ` contents: `
var NoArgsPropertyDecorator = {}; import { Inject } from '@angular/core';
var NoArgsProperty = (function() { var NoArgsProperty = (function() {
function NoArgsProperty(arg1) { function NoArgsProperty(arg1) {
} }
NoArgsProperty.ctorParameters = function() { return [ NoArgsProperty.ctorParameters = function() { return [
{ type: 'ParamType', decorators: [{ type: NoArgsPropertyDecorator },] }, { type: 'ParamType', decorators: [{ type: Inject },] },
]; }; ]; };
return NoArgsProperty; return NoArgsProperty;
}()); }());
var NoPropertyAssignmentDecorator = {};
var args = [{ selector: '[ignored]' },]; var args = [{ selector: '[ignored]' },];
var NoPropertyAssignment = (function() { var NoPropertyAssignment = (function() {
function NoPropertyAssignment(arg1) { function NoPropertyAssignment(arg1) {
} }
NoPropertyAssignment.ctorParameters = function() { return [ NoPropertyAssignment.ctorParameters = function() { return [
{ type: 'ParamType', decorators: [{ type: NoPropertyAssignmentDecorator, args },] }, { type: 'ParamType', decorators: [{ type: Inject, args },] },
]; }; ]; };
return NoPropertyAssignment; return NoPropertyAssignment;
}()); }());
var NotArrayLiteralDecorator = {};
var NotArrayLiteral = (function() { var NotArrayLiteral = (function() {
function NotArrayLiteral(arg1) { function NotArrayLiteral(arg1) {
} }
NotArrayLiteral.ctorParameters = function() { return [ NotArrayLiteral.ctorParameters = function() { return [
{ type: 'ParamType', decorators: [{ type: NotArrayLiteralDecorator, args: () => [{ selector: '[ignored]' },] },] }, { type: 'ParamType', decorators: [{ type: Inject, args: () => [{ selector: '[ignored]' },] },] },
]; }; ]; };
return NotArrayLiteral; return NotArrayLiteral;
}()); }());
@ -502,7 +483,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotObjectLiteralDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
}); });
it('should ignore decorator elements that have no `type` property', () => { it('should ignore decorator elements that have no `type` property', () => {
@ -513,7 +494,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NoTypePropertyDecorator2'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
}); });
it('should ignore decorator elements whose `type` value is not an identifier', () => { it('should ignore decorator elements whose `type` value is not an identifier', () => {
@ -524,11 +505,11 @@ describe('Esm5ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotIdentifierDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
}); });
it('should use `getImportOfIdentifier()` to retrieve import info', () => { it('should use `getImportOfIdentifier()` to retrieve import info', () => {
const mockImportInfo = {} as Import; const mockImportInfo = { name: 'mock', from: '@angular/core' } as Import;
const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier') const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier')
.and.returnValue(mockImportInfo); .and.returnValue(mockImportInfo);
@ -554,7 +535,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoArgsPropertyDecorator'); expect(decorators[0].name).toBe('Directive');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -567,7 +548,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoPropertyAssignmentDecorator'); expect(decorators[0].name).toBe('Directive');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -579,7 +560,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NotArrayLiteralDecorator'); expect(decorators[0].name).toBe('Directive');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
}); });
@ -688,9 +669,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({ expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
name: 'NotObjectLiteralPropDecorator'
}));
}); });
it('should ignore prop decorator elements that have no `type` property', () => { it('should ignore prop decorator elements that have no `type` property', () => {
@ -703,7 +682,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NoTypePropertyDecorator2'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
}); });
it('should ignore prop decorator elements whose `type` value is not an identifier', () => { it('should ignore prop decorator elements whose `type` value is not an identifier', () => {
@ -716,14 +695,14 @@ describe('Esm5ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotIdentifierDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
}); });
it('should use `getImportOfIdentifier()` to retrieve import info', () => { it('should use `getImportOfIdentifier()` to retrieve import info', () => {
let callCount = 0; let callCount = 0;
const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier').and.callFake(() => { const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier').and.callFake(() => {
callCount++; callCount++;
return {name: `name${callCount}`, from: `from${callCount}`}; return {name: `name${callCount}`, from: `@angular/core`};
}); });
const program = makeProgram(SOME_DIRECTIVE_FILE); const program = makeProgram(SOME_DIRECTIVE_FILE);
@ -737,7 +716,7 @@ describe('Esm5ReflectionHost', () => {
const index = members.findIndex(member => member.name === 'input1'); const index = members.findIndex(member => member.name === 'input1');
expect(members[index].decorators !.length).toBe(1); expect(members[index].decorators !.length).toBe(1);
expect(members[index].decorators ![0].import).toEqual({name: 'name1', from: 'from1'}); expect(members[index].decorators ![0].import).toEqual({name: 'name1', from: '@angular/core'});
}); });
describe('(returned prop decorators `args`)', () => { describe('(returned prop decorators `args`)', () => {
@ -752,7 +731,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoArgsPropertyDecorator'); expect(decorators[0].name).toBe('Input');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -767,7 +746,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoPropertyAssignmentDecorator'); expect(decorators[0].name).toBe('Input');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -782,7 +761,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NotArrayLiteralDecorator'); expect(decorators[0].name).toBe('Input');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
}); });
@ -887,7 +866,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NoTypePropertyDecorator2'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'}));
}); });
it('should ignore param decorator elements whose `type` value is not an identifier', () => { it('should ignore param decorator elements whose `type` value is not an identifier', () => {
@ -899,11 +878,11 @@ describe('Esm5ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotIdentifierDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'}));
}); });
it('should use `getImportOfIdentifier()` to retrieve import info', () => { it('should use `getImportOfIdentifier()` to retrieve import info', () => {
const mockImportInfo = {} as Import; const mockImportInfo = { name: 'mock', from: '@angulare/core' } as Import;
const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier') const spy = spyOn(Esm5ReflectionHost.prototype, 'getImportOfIdentifier')
.and.returnValue(mockImportInfo); .and.returnValue(mockImportInfo);
@ -934,7 +913,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoArgsPropertyDecorator'); expect(decorators[0].name).toBe('Inject');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -948,7 +927,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoPropertyAssignmentDecorator'); expect(decorators[0].name).toBe('Inject');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -962,7 +941,7 @@ describe('Esm5ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NotArrayLiteralDecorator'); expect(decorators[0].name).toBe('Inject');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
}); });

View File

@ -76,36 +76,32 @@ const FOO_FUNCTION_FILE = {
const INVALID_DECORATORS_FILE = { const INVALID_DECORATORS_FILE = {
name: '/invalid_decorators.js', name: '/invalid_decorators.js',
contents: ` contents: `
const NotArrayLiteralDecorator = {}; import {Directive} from '@angular/core';
class NotArrayLiteral { class NotArrayLiteral {
} }
NotArrayLiteral.decorators = () => [ NotArrayLiteral.decorators = () => [
{ type: NotArrayLiteralDecorator, args: [{ selector: '[ignored]' },] }, { type: Directive, args: [{ selector: '[ignored]' },] },
]; ];
const NotObjectLiteralDecorator = {};
class NotObjectLiteral { class NotObjectLiteral {
} }
NotObjectLiteral.decorators = [ NotObjectLiteral.decorators = [
"This is not an object literal", "This is not an object literal",
{ type: NotObjectLiteralDecorator }, { type: Directive },
]; ];
const NoTypePropertyDecorator1 = {};
const NoTypePropertyDecorator2 = {};
class NoTypeProperty { class NoTypeProperty {
} }
NoTypeProperty.decorators = [ NoTypeProperty.decorators = [
{ notType: NoTypePropertyDecorator1 }, { notType: Directive },
{ type: NoTypePropertyDecorator2 }, { type: Directive },
]; ];
const NotIdentifierDecorator = {};
class NotIdentifier { class NotIdentifier {
} }
NotIdentifier.decorators = [ NotIdentifier.decorators = [
{ type: 'StringsLiteralsAreNotIdentifiers' }, { type: 'StringsLiteralsAreNotIdentifiers' },
{ type: NotIdentifierDecorator }, { type: Directive },
]; ];
`, `,
}; };
@ -113,26 +109,24 @@ const INVALID_DECORATORS_FILE = {
const INVALID_DECORATOR_ARGS_FILE = { const INVALID_DECORATOR_ARGS_FILE = {
name: '/invalid_decorator_args.js', name: '/invalid_decorator_args.js',
contents: ` contents: `
const NoArgsPropertyDecorator = {}; import {Directive} from '@angular/core';
class NoArgsProperty { class NoArgsProperty {
} }
NoArgsProperty.decorators = [ NoArgsProperty.decorators = [
{ type: NoArgsPropertyDecorator }, { type: Directive },
]; ];
const NoPropertyAssignmentDecorator = {};
const args = [{ selector: '[ignored]' },]; const args = [{ selector: '[ignored]' },];
class NoPropertyAssignment { class NoPropertyAssignment {
} }
NoPropertyAssignment.decorators = [ NoPropertyAssignment.decorators = [
{ type: NoPropertyAssignmentDecorator, args }, { type: Directive, args },
]; ];
const NotArrayLiteralDecorator = {};
class NotArrayLiteral { class NotArrayLiteral {
} }
NotArrayLiteral.decorators = [ NotArrayLiteral.decorators = [
{ type: NotArrayLiteralDecorator, args: () => [{ selector: '[ignored]' },] }, { type: Directive, args: () => [{ selector: '[ignored]' },] },
]; ];
`, `,
}; };
@ -140,41 +134,37 @@ const INVALID_DECORATOR_ARGS_FILE = {
const INVALID_PROP_DECORATORS_FILE = { const INVALID_PROP_DECORATORS_FILE = {
name: '/invalid_prop_decorators.js', name: '/invalid_prop_decorators.js',
contents: ` contents: `
const NotObjectLiteralDecorator = {}; import {Input} from '@angular/core';
class NotObjectLiteral { class NotObjectLiteral {
} }
NotObjectLiteral.propDecorators = () => ({ NotObjectLiteral.propDecorators = () => ({
"prop": [{ type: NotObjectLiteralDecorator },] "prop": [{ type: Input },]
}); });
const NotObjectLiteralPropDecorator = {};
class NotObjectLiteralProp { class NotObjectLiteralProp {
} }
NotObjectLiteralProp.propDecorators = { NotObjectLiteralProp.propDecorators = {
"prop": [ "prop": [
"This is not an object literal", "This is not an object literal",
{ type: NotObjectLiteralPropDecorator }, { type: Input },
] ]
}; };
const NoTypePropertyDecorator1 = {};
const NoTypePropertyDecorator2 = {};
class NoTypeProperty { class NoTypeProperty {
} }
NoTypeProperty.propDecorators = { NoTypeProperty.propDecorators = {
"prop": [ "prop": [
{ notType: NoTypePropertyDecorator1 }, { notType: Input },
{ type: NoTypePropertyDecorator2 }, { type: Input },
] ]
}; };
const NotIdentifierDecorator = {};
class NotIdentifier { class NotIdentifier {
} }
NotIdentifier.propDecorators = { NotIdentifier.propDecorators = {
"prop": [ "prop": [
{ type: 'StringsLiteralsAreNotIdentifiers' }, { type: 'StringsLiteralsAreNotIdentifiers' },
{ type: NotIdentifierDecorator }, { type: Input },
] ]
}; };
`, `,
@ -183,26 +173,24 @@ const INVALID_PROP_DECORATORS_FILE = {
const INVALID_PROP_DECORATOR_ARGS_FILE = { const INVALID_PROP_DECORATOR_ARGS_FILE = {
name: '/invalid_prop_decorator_args.js', name: '/invalid_prop_decorator_args.js',
contents: ` contents: `
const NoArgsPropertyDecorator = {}; import {Input} from '@angular/core';
class NoArgsProperty { class NoArgsProperty {
} }
NoArgsProperty.propDecorators = { NoArgsProperty.propDecorators = {
"prop": [{ type: NoArgsPropertyDecorator },] "prop": [{ type: Input },]
}; };
const NoPropertyAssignmentDecorator = {};
const args = [{ selector: '[ignored]' },]; const args = [{ selector: '[ignored]' },];
class NoPropertyAssignment { class NoPropertyAssignment {
} }
NoPropertyAssignment.propDecorators = { NoPropertyAssignment.propDecorators = {
"prop": [{ type: NoPropertyAssignmentDecorator, args },] "prop": [{ type: Input, args },]
}; };
const NotArrayLiteralDecorator = {};
class NotArrayLiteral { class NotArrayLiteral {
} }
NotArrayLiteral.propDecorators = { NotArrayLiteral.propDecorators = {
"prop": [{ type: NotArrayLiteralDecorator, args: () => [{ selector: '[ignored]' },] },], "prop": [{ type: Input, args: () => [{ selector: '[ignored]' },] },],
}; };
`, `,
}; };
@ -210,40 +198,44 @@ const INVALID_PROP_DECORATOR_ARGS_FILE = {
const INVALID_CTOR_DECORATORS_FILE = { const INVALID_CTOR_DECORATORS_FILE = {
name: '/invalid_ctor_decorators.js', name: '/invalid_ctor_decorators.js',
contents: ` contents: `
const NoParametersDecorator = {}; import {Inject} from '@angular/core';
class NoParameters { class NoParameters {
constructor() { constructor() {
} }
} }
const NotArrowFunctionDecorator = {}; const NotFromCoreDecorator = {};
class NotFromCore {
constructor(arg1) {
}
}
NotFromCore.ctorParameters = () => [
{ type: 'ParamType', decorators: [{ type: NotFromCoreDecorator },] },
]
class NotArrowFunction { class NotArrowFunction {
constructor(arg1) { constructor(arg1) {
} }
} }
NotArrowFunction.ctorParameters = function() { NotArrowFunction.ctorParameters = function() {
return { type: 'ParamType', decorators: [{ type: NotArrowFunctionDecorator },] }; return { type: 'ParamType', decorators: [{ type: Inject },] };
}; };
const NotArrayLiteralDecorator = {};
class NotArrayLiteral { class NotArrayLiteral {
constructor(arg1) { constructor(arg1) {
} }
} }
NotArrayLiteral.ctorParameters = () => 'StringsAreNotArrayLiterals'; NotArrayLiteral.ctorParameters = () => 'StringsAreNotArrayLiterals';
const NotObjectLiteralDecorator = {};
class NotObjectLiteral { class NotObjectLiteral {
constructor(arg1, arg2) { constructor(arg1, arg2) {
} }
} }
NotObjectLiteral.ctorParameters = () => [ NotObjectLiteral.ctorParameters = () => [
"This is not an object literal", "This is not an object literal",
{ type: 'ParamType', decorators: [{ type: NotObjectLiteralDecorator },] }, { type: 'ParamType', decorators: [{ type: Inject },] },
]; ];
const NoTypePropertyDecorator1 = {};
const NoTypePropertyDecorator2 = {};
class NoTypeProperty { class NoTypeProperty {
constructor(arg1, arg2) { constructor(arg1, arg2) {
} }
@ -252,13 +244,12 @@ const INVALID_CTOR_DECORATORS_FILE = {
{ {
type: 'ParamType', type: 'ParamType',
decorators: [ decorators: [
{ notType: NoTypePropertyDecorator1 }, { notType: Inject },
{ type: NoTypePropertyDecorator2 }, { type: Inject },
] ]
}, },
]; ];
const NotIdentifierDecorator = {};
class NotIdentifier { class NotIdentifier {
constructor(arg1, arg2) { constructor(arg1, arg2) {
} }
@ -268,7 +259,7 @@ const INVALID_CTOR_DECORATORS_FILE = {
type: 'ParamType', type: 'ParamType',
decorators: [ decorators: [
{ type: 'StringsLiteralsAreNotIdentifiers' }, { type: 'StringsLiteralsAreNotIdentifiers' },
{ type: NotIdentifierDecorator }, { type: Inject },
] ]
}, },
]; ];
@ -278,32 +269,30 @@ const INVALID_CTOR_DECORATORS_FILE = {
const INVALID_CTOR_DECORATOR_ARGS_FILE = { const INVALID_CTOR_DECORATOR_ARGS_FILE = {
name: '/invalid_ctor_decorator_args.js', name: '/invalid_ctor_decorator_args.js',
contents: ` contents: `
const NoArgsPropertyDecorator = {}; import {Inject} from '@angular/core';
class NoArgsProperty { class NoArgsProperty {
constructor(arg1) { constructor(arg1) {
} }
} }
NoArgsProperty.ctorParameters = () => [ NoArgsProperty.ctorParameters = () => [
{ type: 'ParamType', decorators: [{ type: NoArgsPropertyDecorator },] }, { type: 'ParamType', decorators: [{ type: Inject },] },
]; ];
const NoPropertyAssignmentDecorator = {};
const args = [{ selector: '[ignored]' },]; const args = [{ selector: '[ignored]' },];
class NoPropertyAssignment { class NoPropertyAssignment {
constructor(arg1) { constructor(arg1) {
} }
} }
NoPropertyAssignment.ctorParameters = () => [ NoPropertyAssignment.ctorParameters = () => [
{ type: 'ParamType', decorators: [{ type: NoPropertyAssignmentDecorator, args },] }, { type: 'ParamType', decorators: [{ type: Inject, args },] },
]; ];
const NotArrayLiteralDecorator = {};
class NotArrayLiteral { class NotArrayLiteral {
constructor(arg1) { constructor(arg1) {
} }
} }
NotArrayLiteral.ctorParameters = () => [ NotArrayLiteral.ctorParameters = () => [
{ type: 'ParamType', decorators: [{ type: NotArrayLiteralDecorator, args: () => [{ selector: '[ignored]' },] },] }, { type: 'ParamType', decorators: [{ type: Inject, args: () => [{ selector: '[ignored]' },] },] },
]; ];
`, `,
}; };
@ -459,7 +448,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotObjectLiteralDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
}); });
it('should ignore decorator elements that have no `type` property', () => { it('should ignore decorator elements that have no `type` property', () => {
@ -470,7 +459,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NoTypePropertyDecorator2'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
}); });
it('should ignore decorator elements whose `type` value is not an identifier', () => { it('should ignore decorator elements whose `type` value is not an identifier', () => {
@ -481,11 +470,11 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotIdentifierDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'}));
}); });
it('should use `getImportOfIdentifier()` to retrieve import info', () => { it('should use `getImportOfIdentifier()` to retrieve import info', () => {
const mockImportInfo = {} as Import; const mockImportInfo = { from: '@angular/core' } as Import;
const spy = spyOn(Fesm2015ReflectionHost.prototype, 'getImportOfIdentifier') const spy = spyOn(Fesm2015ReflectionHost.prototype, 'getImportOfIdentifier')
.and.returnValue(mockImportInfo); .and.returnValue(mockImportInfo);
@ -511,7 +500,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoArgsPropertyDecorator'); expect(decorators[0].name).toBe('Directive');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -524,7 +513,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoPropertyAssignmentDecorator'); expect(decorators[0].name).toBe('Directive');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -536,7 +525,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = host.getDecoratorsOfDeclaration(classNode) !; const decorators = host.getDecoratorsOfDeclaration(classNode) !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NotArrayLiteralDecorator'); expect(decorators[0].name).toBe('Directive');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
}); });
@ -644,9 +633,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({ expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
name: 'NotObjectLiteralPropDecorator'
}));
}); });
it('should ignore prop decorator elements that have no `type` property', () => { it('should ignore prop decorator elements that have no `type` property', () => {
@ -659,7 +646,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NoTypePropertyDecorator2'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
}); });
it('should ignore prop decorator elements whose `type` value is not an identifier', () => { it('should ignore prop decorator elements whose `type` value is not an identifier', () => {
@ -672,7 +659,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotIdentifierDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'}));
}); });
it('should use `getImportOfIdentifier()` to retrieve import info', () => { it('should use `getImportOfIdentifier()` to retrieve import info', () => {
@ -680,7 +667,7 @@ describe('Fesm2015ReflectionHost', () => {
const spy = const spy =
spyOn(Fesm2015ReflectionHost.prototype, 'getImportOfIdentifier').and.callFake(() => { spyOn(Fesm2015ReflectionHost.prototype, 'getImportOfIdentifier').and.callFake(() => {
callCount++; callCount++;
return {name: `name${callCount}`, from: `from${callCount}`}; return {name: `name${callCount}`, from: '@angular/core'};
}); });
const program = makeProgram(SOME_DIRECTIVE_FILE); const program = makeProgram(SOME_DIRECTIVE_FILE);
@ -698,9 +685,9 @@ describe('Fesm2015ReflectionHost', () => {
'HostListener', 'HostListener',
]); ]);
const index = members.findIndex(member => member.name === 'input1'); const member = members.find(member => member.name === 'input1') !;
expect(members[index].decorators !.length).toBe(1); expect(member.decorators !.length).toBe(1);
expect(members[index].decorators ![0].import).toEqual({name: 'name1', from: 'from1'}); expect(member.decorators ![0].import).toEqual({name: 'name1', from: '@angular/core'});
}); });
describe('(returned prop decorators `args`)', () => { describe('(returned prop decorators `args`)', () => {
@ -715,7 +702,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoArgsPropertyDecorator'); expect(decorators[0].name).toBe('Input');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -730,7 +717,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoPropertyAssignmentDecorator'); expect(decorators[0].name).toBe('Input');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -745,7 +732,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = prop.decorators !; const decorators = prop.decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NotArrayLiteralDecorator'); expect(decorators[0].name).toBe('Input');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
}); });
@ -757,13 +744,13 @@ describe('Fesm2015ReflectionHost', () => {
const host = new Fesm2015ReflectionHost(program.getTypeChecker()); const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const classNode = const classNode =
getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration); getDeclaration(program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode); const parameters = host.getConstructorParameters(classNode) !;
expect(parameters).toBeDefined(); expect(parameters).toBeDefined();
expect(parameters !.map(parameter => parameter.name)).toEqual([ expect(parameters.map(parameter => parameter.name)).toEqual([
'_viewContainer', '_template', 'injected' '_viewContainer', '_template', 'injected'
]); ]);
expect(parameters !.map(parameter => parameter.type !.getText())).toEqual([ expect(parameters.map(parameter => parameter.type !.getText())).toEqual([
'ViewContainerRef', 'TemplateRef', 'undefined' 'ViewContainerRef', 'TemplateRef', 'undefined'
]); ]);
}); });
@ -792,12 +779,12 @@ describe('Fesm2015ReflectionHost', () => {
const host = new Fesm2015ReflectionHost(program.getTypeChecker()); const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const classNode = getDeclaration( const classNode = getDeclaration(
program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', ts.isClassDeclaration); program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode); const parameters = host.getConstructorParameters(classNode) !;
expect(parameters).toEqual(jasmine.any(Array)); expect(parameters).toEqual(jasmine.any(Array));
expect(parameters !.length).toEqual(1); expect(parameters.length).toEqual(1);
expect(parameters ![0].name).toEqual('foo'); expect(parameters[0].name).toEqual('foo');
expect(parameters ![0].decorators).toBe(null); expect(parameters[0].decorators).toBe(null);
}); });
it('should return an empty array if there are no constructor parameters', () => { it('should return an empty array if there are no constructor parameters', () => {
@ -810,15 +797,29 @@ describe('Fesm2015ReflectionHost', () => {
expect(parameters).toEqual([]); expect(parameters).toEqual([]);
}); });
it('should ignore decorators that are not imported from core', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotFromCore', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode) !;
expect(parameters.length).toBe(1);
expect(parameters[0]).toEqual(jasmine.objectContaining({
name: 'arg1',
decorators: [],
}));
});
it('should ignore `ctorParameters` if it is not an arrow function', () => { it('should ignore `ctorParameters` if it is not an arrow function', () => {
const program = makeProgram(INVALID_CTOR_DECORATORS_FILE); const program = makeProgram(INVALID_CTOR_DECORATORS_FILE);
const host = new Fesm2015ReflectionHost(program.getTypeChecker()); const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const classNode = getDeclaration( const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrowFunction', ts.isClassDeclaration); program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrowFunction', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode); const parameters = host.getConstructorParameters(classNode) !;
expect(parameters !.length).toBe(1); expect(parameters.length).toBe(1);
expect(parameters ![0]).toEqual(jasmine.objectContaining({ expect(parameters[0]).toEqual(jasmine.objectContaining({
name: 'arg1', name: 'arg1',
decorators: null, decorators: null,
})); }));
@ -829,10 +830,10 @@ describe('Fesm2015ReflectionHost', () => {
const host = new Fesm2015ReflectionHost(program.getTypeChecker()); const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const classNode = getDeclaration( const classNode = getDeclaration(
program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', ts.isClassDeclaration); program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode); const parameters = host.getConstructorParameters(classNode) !;
expect(parameters !.length).toBe(1); expect(parameters.length).toBe(1);
expect(parameters ![0]).toEqual(jasmine.objectContaining({ expect(parameters[0]).toEqual(jasmine.objectContaining({
name: 'arg1', name: 'arg1',
decorators: null, decorators: null,
})); }));
@ -866,7 +867,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NoTypePropertyDecorator2'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'}));
}); });
it('should ignore param decorator elements whose `type` value is not an identifier', () => { it('should ignore param decorator elements whose `type` value is not an identifier', () => {
@ -878,11 +879,11 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'NotIdentifierDecorator'})); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'}));
}); });
it('should use `getImportOfIdentifier()` to retrieve import info', () => { it('should use `getImportOfIdentifier()` to retrieve import info', () => {
const mockImportInfo = {} as Import; const mockImportInfo: Import = {name: 'mock', from: '@angular/core'};
const spy = spyOn(Fesm2015ReflectionHost.prototype, 'getImportOfIdentifier') const spy = spyOn(Fesm2015ReflectionHost.prototype, 'getImportOfIdentifier')
.and.returnValue(mockImportInfo); .and.returnValue(mockImportInfo);
@ -890,8 +891,8 @@ describe('Fesm2015ReflectionHost', () => {
const host = new Fesm2015ReflectionHost(program.getTypeChecker()); const host = new Fesm2015ReflectionHost(program.getTypeChecker());
const classNode = getDeclaration( const classNode = getDeclaration(
program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration); program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', ts.isClassDeclaration);
const parameters = host.getConstructorParameters(classNode); const parameters = host.getConstructorParameters(classNode) !;
const decorators = parameters ![2].decorators !; const decorators = parameters[2].decorators !;
expect(decorators.length).toEqual(1); expect(decorators.length).toEqual(1);
expect(decorators[0].import).toBe(mockImportInfo); expect(decorators[0].import).toBe(mockImportInfo);
@ -913,7 +914,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoArgsPropertyDecorator'); expect(decorators[0].name).toBe('Inject');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -927,7 +928,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NoPropertyAssignmentDecorator'); expect(decorators[0].name).toBe('Inject');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
@ -941,7 +942,7 @@ describe('Fesm2015ReflectionHost', () => {
const decorators = parameters ![0].decorators !; const decorators = parameters ![0].decorators !;
expect(decorators.length).toBe(1); expect(decorators.length).toBe(1);
expect(decorators[0].name).toBe('NotArrayLiteralDecorator'); expect(decorators[0].name).toBe('Inject');
expect(decorators[0].args).toEqual([]); expect(decorators[0].args).toEqual([]);
}); });
}); });

View File

@ -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';
var A = (function() { var A = (function() {
function A() {} function A() {}
A.decorators = [ A.decorators = [

View File

@ -200,7 +200,7 @@ A.decorators = [
const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !);
const output = new MagicString(PROGRAM.contents); const output = new MagicString(PROGRAM.contents);
const analyzedClass = analyzedFile.analyzedClasses[1]; const analyzedClass = analyzedFile.analyzedClasses[1];
const decorator = analyzedClass.decorators[1]; const decorator = analyzedClass.decorators[0];
const decoratorsToRemove = new Map<ts.Node, ts.Node[]>(); const decoratorsToRemove = new Map<ts.Node, ts.Node[]>();
decoratorsToRemove.set(decorator.node.parent !, [decorator.node]); decoratorsToRemove.set(decorator.node.parent !, [decorator.node]);
renderer.removeDecorators(output, decoratorsToRemove); renderer.removeDecorators(output, decoratorsToRemove);

View File

@ -223,7 +223,7 @@ SOME DEFINITION TEXT
const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !); const analyzedFile = analyze(parser, analyzer, program.getSourceFile(PROGRAM.name) !);
const output = new MagicString(PROGRAM.contents); const output = new MagicString(PROGRAM.contents);
const analyzedClass = analyzedFile.analyzedClasses[1]; const analyzedClass = analyzedFile.analyzedClasses[1];
const decorator = analyzedClass.decorators[1]; const decorator = analyzedClass.decorators[0];
const decoratorsToRemove = new Map<ts.Node, ts.Node[]>(); const decoratorsToRemove = new Map<ts.Node, ts.Node[]>();
decoratorsToRemove.set(decorator.node.parent !, [decorator.node]); decoratorsToRemove.set(decorator.node.parent !, [decorator.node]);
renderer.removeDecorators(output, decoratorsToRemove); renderer.removeDecorators(output, decoratorsToRemove);