refactor(ivy): implement NgccReflectionHost.findDecoratedFiles
(#26082)
PR Close #26082
This commit is contained in:

committed by
Miško Hevery

parent
d17602f31d
commit
7f03528dbc
@ -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 = {
|
||||
|
@ -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']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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]' }`]]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user