refactor(ivy): implement NgccReflectionHost.findDecoratedFiles (#26082)

PR Close #26082
This commit is contained in:
Pete Bacon Darwin
2018-09-26 17:24:43 +01:00
committed by Miško Hevery
parent d17602f31d
commit 7f03528dbc
10 changed files with 280 additions and 6 deletions

View File

@ -6,12 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript';
import {Decorator} from '../../ngtsc/host';
import {DecoratorHandler} from '../../ngtsc/transform';
import {AnalyzedFile, Analyzer} from '../src/analyzer';
import {Fesm2015ReflectionHost} from '../src/host/fesm2015_host';
import {DecoratedClass} from '../src/host/decorated_class';
import {DecoratedFile} from '../src/host/decorated_file';
import {Fesm2015ReflectionHost} from '../src/host/fesm2015_host';
import {getDeclaration, makeProgram} from './helpers/utils';
const TEST_PROGRAM = {

View File

@ -50,6 +50,39 @@ const MARKER_FILE = {
`
};
const DECORATED_FILES = [
{
name: '/primary.js',
contents: `
import {Directive} from '@angular/core';
class A {}
A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] }
];
function x() {}
function y() {}
class B {}
B.decorators = [
{ type: Directive, args: [{ selector: '[b]' }] }
];
class C {}
export { A, x, C };
export { D } from '/secondary';
`
},
{
name: '/secondary.js',
contents: `
import {Directive} from '@angular/core';
class D {}
D.decorators = [
{ type: Directive, args: [{ selector: '[d]' }] }
];
export { D };
`
}
];
describe('Esm2015ReflectionHost', () => {
describe('getGenericArityOfClass()', () => {
it('should properly count type parameters', () => {
@ -84,4 +117,28 @@ describe('Esm2015ReflectionHost', () => {
]);
});
});
describe('findDecoratedFiles()', () => {
it('should return an array of objects for each file that has exported and decorated classes',
() => {
const program = makeProgram(...DECORATED_FILES);
const dtsMapper = new DtsMapper('/src', '/typings');
const host = new Esm2015ReflectionHost(false, program.getTypeChecker(), dtsMapper);
const decoratedFiles =
host.findDecoratedFiles(program.getSourceFile(DECORATED_FILES[0].name) !);
expect(decoratedFiles.length).toEqual(2);
const primary = decoratedFiles[0];
expect(primary.decoratedClasses.length).toEqual(1);
const classA = primary.decoratedClasses.find(c => c.name === 'A') !;
expect(classA.name).toEqual('A');
expect(ts.isClassDeclaration(classA.declaration)).toBeTruthy();
expect(classA.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
const secondary = decoratedFiles[1];
expect(secondary.decoratedClasses.length).toEqual(1);
const classD = secondary.decoratedClasses.find(c => c.name === 'D') !;
expect(classD.name).toEqual('D');
expect(ts.isClassDeclaration(classD.declaration)).toBeTruthy();
expect(classD.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
});
});
});

View File

@ -427,6 +427,51 @@ const FUNCTION_BODY_FILE = {
`
};
const DECORATED_FILES = [
{
name: '/primary.js',
contents: `
import {Directive} from '@angular/core';
var A = (function() {
function A() {}
A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] }
];
return A;
}());
var B = (function() {
function B() {}
B.decorators = [
{ type: Directive, args: [{ selector: '[b]' }] }
];
return B;
}());
function x() {}
function y() {}
var C = (function() {
function C() {}
return C;
});
export { A, x, C };
export { D } from '/secondary';
`
},
{
name: '/secondary.js',
contents: `
import {Directive} from '@angular/core';
var D = (function() {
function D() {}
D.decorators = [
{ type: Directive, args: [{ selector: '[d]' }] }
];
return D;
}());
export { D };
`
}
];
describe('Esm5ReflectionHost', () => {
describe('getDecoratorsOfDeclaration()', () => {
@ -1206,4 +1251,25 @@ describe('Esm5ReflectionHost', () => {
expect(getClassSymbolSpy).toHaveBeenCalledWith(mockNode);
});
});
describe('fileDecoratedFiles()', () => {
it('should return an array of objects for each file that has exported and decorated classes',
() => {
const program = makeProgram(...DECORATED_FILES);
const host = new Esm5ReflectionHost(false, program.getTypeChecker());
const decoratedFiles =
host.findDecoratedFiles(program.getSourceFile(DECORATED_FILES[0].name) !);
expect(decoratedFiles.length).toEqual(2);
const primary = decoratedFiles[0];
expect(primary.decoratedClasses.length).toEqual(1);
const classA = primary.decoratedClasses[0];
expect(classA.name).toEqual('A');
expect(classA.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
const secondary = decoratedFiles[1];
expect(secondary.decoratedClasses.length).toEqual(1);
const classD = secondary.decoratedClasses[0];
expect(classD.name).toEqual('D');
expect(classD.decorators.map(decorator => decorator.name)).toEqual(['Directive']);
});
});
});

View File

@ -392,6 +392,37 @@ const MARKER_FILE = {
`
};
const DECORATED_FILE = {
name: '/primary.js',
contents: `
import {Directive} from '@angular/core';
class A {}
A.decorators = [
{ type: Directive, args: [{ selector: '[a]' }] }
];
class B {}
B.decorators = [
{ type: Directive, args: [{ selector: '[b]' }] }
];
function x() {}
function y() {}
class C {}
let D = class D {}
D = tslib_1.__decorate([
Directive({ selector: '[d]' }),
OtherD()
], D);
export {D};
export { A, x, C };
`
};
describe('Fesm2015ReflectionHost', () => {
describe('getDecoratorsOfDeclaration()', () => {
@ -1152,4 +1183,29 @@ describe('Fesm2015ReflectionHost', () => {
]);
});
});
describe('findDecoratedFiles()', () => {
it('should return an array of objects for each file that has exported and decorated classes',
() => {
const program = makeProgram(DECORATED_FILE);
const host = new Fesm2015ReflectionHost(false, program.getTypeChecker());
const decoratedFiles =
host.findDecoratedFiles(program.getSourceFile(DECORATED_FILE.name) !);
expect(decoratedFiles.length).toEqual(1);
const decoratedClasses = decoratedFiles[0].decoratedClasses;
expect(decoratedClasses.length).toEqual(2);
const decoratedClassA = decoratedClasses.find(c => c.name === 'A') !;
expect(decoratedClassA.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]' }`]]);
});
});
});