diff --git a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts index 3ebd4f1fd5..421bab1b0d 100644 --- a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts @@ -8,12 +8,15 @@ import * as ts from 'typescript'; import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; -import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; -import {ClassMemberKind, CtorParameter, InlineDeclaration, KnownDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; +import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; +import {ClassMemberKind, CtorParameter, InlineDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; import {CommonJsReflectionHost} from '../../src/host/commonjs_host'; +import {DelegatingReflectionHost} from '../../src/host/delegating_host'; import {getIifeBody} from '../../src/host/esm5_host'; +import {NgccReflectionHost} from '../../src/host/ngcc_host'; +import {BundleProgram} from '../../src/packages/bundle_program'; import {MockLogger} from '../helpers/mock_logger'; import {getRootFiles, makeTestBundleProgram, makeTestDtsBundleProgram} from '../helpers/utils'; @@ -21,7 +24,6 @@ import {expectTypeValueReferencesForParameters} from './util'; runInEachFileSystem(() => { describe('CommonJsReflectionHost', () => { - let _: typeof absoluteFrom; let SOME_DIRECTIVE_FILE: TestFile; @@ -45,6 +47,12 @@ runInEachFileSystem(() => { let TYPINGS_DTS_FILES: TestFile[]; let MODULE_WITH_PROVIDERS_PROGRAM: TestFile[]; + // Helpers + const createHost = (bundle: BundleProgram, ngccHost: CommonJsReflectionHost) => { + const tsHost = new TypeScriptReflectionHost(bundle.program.getTypeChecker()); + return new DelegatingReflectionHost(tsHost, ngccHost); + }; + beforeEach(() => { _ = absoluteFrom; @@ -916,16 +924,16 @@ exports.ExternalModule = ExternalModule; }); describe('CommonJsReflectionHost', () => { - describe('getDecoratorsOfDeclaration()', () => { it('should find the decorators on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -933,7 +941,7 @@ exports.ExternalModule = ExternalModule; const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -941,11 +949,12 @@ exports.ExternalModule = ExternalModule; it('should find the decorators on a class at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -953,7 +962,7 @@ exports.ExternalModule = ExternalModule; const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -961,7 +970,8 @@ exports.ExternalModule = ExternalModule; it('should return null if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const decorators = host.getDecoratorsOfDeclaration(functionNode); @@ -971,7 +981,8 @@ exports.ExternalModule = ExternalModule; it('should return null if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const decorators = host.getDecoratorsOfDeclaration(classNode); @@ -981,7 +992,8 @@ exports.ExternalModule = ExternalModule; it('should ignore `decorators` if it is not an array literal', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); @@ -992,11 +1004,12 @@ exports.ExternalModule = ExternalModule; it('should ignore decorator elements that are not object literals', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1005,11 +1018,12 @@ exports.ExternalModule = ExternalModule; it('should ignore decorator elements that have no `type` property', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1018,11 +1032,12 @@ exports.ExternalModule = ExternalModule; it('should ignore decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1032,11 +1047,12 @@ exports.ExternalModule = ExternalModule; it('should be an empty array if decorator has no `args` property', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1046,11 +1062,12 @@ exports.ExternalModule = ExternalModule; it('should be an empty array if decorator\'s `args` has no property assignment', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1060,11 +1077,12 @@ exports.ExternalModule = ExternalModule; it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1077,94 +1095,100 @@ exports.ExternalModule = ExternalModule; it('should find decorated members on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const input1 = members.find(member => member.name === 'input1') !; + const input1 = members.find(member => member.name === 'input1')!; expect(input1.kind).toEqual(ClassMemberKind.Property); expect(input1.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); - const input2 = members.find(member => member.name === 'input2') !; + const input2 = members.find(member => member.name === 'input2')!; expect(input2.kind).toEqual(ClassMemberKind.Property); expect(input2.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); }); it('should find decorated members on a class at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const input1 = members.find(member => member.name === 'input1') !; + const input1 = members.find(member => member.name === 'input1')!; expect(input1.kind).toEqual(ClassMemberKind.Property); expect(input1.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); - const input2 = members.find(member => member.name === 'input2') !; + const input2 = members.find(member => member.name === 'input2')!; expect(input2.kind).toEqual(ClassMemberKind.Property); expect(input2.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); }); it('should find non decorated properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const instanceProperty = members.find(member => member.name === 'instanceProperty') !; + const instanceProperty = members.find(member => member.name === 'instanceProperty')!; expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); expect(instanceProperty.isStatic).toEqual(false); - expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true); - expect(instanceProperty.value !.getText()).toEqual(`'instance'`); + expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true); + expect(instanceProperty.value!.getText()).toEqual(`'instance'`); }); it('should find static methods on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const staticMethod = members.find(member => member.name === 'staticMethod') !; + const staticMethod = members.find(member => member.name === 'staticMethod')!; expect(staticMethod.kind).toEqual(ClassMemberKind.Method); expect(staticMethod.isStatic).toEqual(true); - expect(ts.isFunctionExpression(staticMethod.implementation !)).toEqual(true); + expect(ts.isFunctionExpression(staticMethod.implementation!)).toEqual(true); }); it('should find static properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const staticProperty = members.find(member => member.name === 'staticProperty') !; + const staticProperty = members.find(member => member.name === 'staticProperty')!; expect(staticProperty.kind).toEqual(ClassMemberKind.Property); expect(staticProperty.isStatic).toEqual(true); - expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true); - expect(staticProperty.value !.getText()).toEqual(`'static'`); + expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true); + expect(staticProperty.value!.getText()).toEqual(`'static'`); }); it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(() => { @@ -1175,7 +1199,8 @@ exports.ExternalModule = ExternalModule; it('should return an empty array if there are no prop decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); @@ -1187,7 +1212,8 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); @@ -1199,13 +1225,14 @@ exports.ExternalModule = ExternalModule; it('should ignore prop decorator elements that are not object literals', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteralProp', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1214,13 +1241,14 @@ exports.ExternalModule = ExternalModule; it('should ignore prop decorator elements that have no `type` property', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1229,13 +1257,14 @@ exports.ExternalModule = ExternalModule; it('should ignore prop decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1244,12 +1273,13 @@ exports.ExternalModule = ExternalModule; it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'}); @@ -1259,13 +1289,14 @@ exports.ExternalModule = ExternalModule; it('should be an empty array if prop decorator has no `args` property', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1276,13 +1307,14 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1292,13 +1324,14 @@ exports.ExternalModule = ExternalModule; it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1311,17 +1344,18 @@ exports.ExternalModule = ExternalModule; it('should find the decorated constructor parameters', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toBeDefined(); - expect(parameters !.map(parameter => parameter.name)).toEqual([ + expect(parameters!.map(parameter => parameter.name)).toEqual([ '_viewContainer', '_template', 'injected' ]); - expectTypeValueReferencesForParameters(parameters !, [ + expectTypeValueReferencesForParameters(parameters!, [ 'ViewContainerRef', 'TemplateRef', null, @@ -1331,17 +1365,18 @@ exports.ExternalModule = ExternalModule; it('should find the decorated constructor parameters at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toBeDefined(); - expect(parameters !.map(parameter => parameter.name)).toEqual([ + expect(parameters!.map(parameter => parameter.name)).toEqual([ '_viewContainer', '_template', 'injected' ]); - expectTypeValueReferencesForParameters(parameters !, [ + expectTypeValueReferencesForParameters(parameters!, [ 'ViewContainerRef', 'TemplateRef', null, @@ -1351,11 +1386,12 @@ exports.ExternalModule = ExternalModule; it('should accept `ctorParameters` as an array', () => { loadTestFiles([CTOR_DECORATORS_ARRAY_FILE]); const bundle = makeTestBundleProgram(CTOR_DECORATORS_ARRAY_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, CTOR_DECORATORS_ARRAY_FILE.name, 'CtorDecoratedAsArray', isNamedVariableDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters).toBeDefined(); expect(parameters.map(parameter => parameter.name)).toEqual(['arg1']); @@ -1365,10 +1401,13 @@ exports.ExternalModule = ExternalModule; it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); - expect(() => { host.getConstructorParameters(functionNode); }) + expect(() => { + host.getConstructorParameters(functionNode); + }) .toThrowError( 'Attempted to get constructor parameters of a non-class: "function foo() {}"'); }); @@ -1379,22 +1418,24 @@ exports.ExternalModule = ExternalModule; it('should return an array even if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toEqual(jasmine.any(Array)); - expect(parameters !.length).toEqual(1); - expect(parameters ![0].name).toEqual('foo'); - expect(parameters ![0].decorators).toBe(null); + expect(parameters!.length).toEqual(1); + expect(parameters![0].name).toEqual('foo'); + expect(parameters![0].decorators).toBe(null); }); it('should return an empty array if there are no constructor parameters', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoParameters', isNamedVariableDeclaration); @@ -1409,14 +1450,15 @@ exports.ExternalModule = ExternalModule; it('should ignore `ctorParameters` if it does not return an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(1); - expect(parameters ![0]).toEqual(jasmine.objectContaining({ + expect(parameters!.length).toBe(1); + expect(parameters![0]).toEqual(jasmine.objectContaining({ name: 'arg1', decorators: null, })); @@ -1426,18 +1468,19 @@ exports.ExternalModule = ExternalModule; it('should ignore param decorator elements that are not object literals', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(2); - expect(parameters ![0]).toEqual(jasmine.objectContaining({ + expect(parameters!.length).toBe(2); + expect(parameters![0]).toEqual(jasmine.objectContaining({ name: 'arg1', decorators: null, })); - expect(parameters ![1]).toEqual(jasmine.objectContaining({ + expect(parameters![1]).toEqual(jasmine.objectContaining({ name: 'arg2', decorators: jasmine.any(Array) as any })); @@ -1446,12 +1489,13 @@ exports.ExternalModule = ExternalModule; it('should ignore param decorator elements that have no `type` property', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1461,12 +1505,13 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1475,13 +1520,14 @@ exports.ExternalModule = ExternalModule; it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![2].decorators !; + const decorators = parameters![2].decorators!; expect(decorators.length).toEqual(1); expect(decorators[0].name).toBe('Inject'); @@ -1493,13 +1539,14 @@ exports.ExternalModule = ExternalModule; it('should be an empty array if param decorator has no `args` property', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(1); - const decorators = parameters ![0].decorators !; + expect(parameters!.length).toBe(1); + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1510,12 +1557,13 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1525,12 +1573,13 @@ exports.ExternalModule = ExternalModule; it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1544,45 +1593,46 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([FUNCTION_BODY_FILE]); const bundle = makeTestBundleProgram(FUNCTION_BODY_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const fooNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration) !; - const fooDef = host.getDefinitionOfFunction(fooNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration)!; + const fooDef = host.getDefinitionOfFunction(fooNode)!; expect(fooDef.node).toBe(fooNode); - expect(fooDef.body !.length).toEqual(1); - expect(fooDef.body ![0].getText()).toEqual(`return x;`); + expect(fooDef.body!.length).toEqual(1); + expect(fooDef.body![0].getText()).toEqual(`return x;`); expect(fooDef.parameters.length).toEqual(1); expect(fooDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); const barNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration) !; - const barDef = host.getDefinitionOfFunction(barNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration)!; + const barDef = host.getDefinitionOfFunction(barNode)!; expect(barDef.node).toBe(barNode); - expect(barDef.body !.length).toEqual(1); - expect(ts.isReturnStatement(barDef.body ![0])).toBeTruthy(); - expect(barDef.body ![0].getText()).toEqual(`return x + y;`); + expect(barDef.body!.length).toEqual(1); + expect(ts.isReturnStatement(barDef.body![0])).toBeTruthy(); + expect(barDef.body![0].getText()).toEqual(`return x + y;`); expect(barDef.parameters.length).toEqual(2); expect(barDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); expect(barDef.parameters[1].name).toEqual('y'); - expect(barDef.parameters[1].initializer !.getText()).toEqual('42'); + expect(barDef.parameters[1].initializer!.getText()).toEqual('42'); const bazNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration) !; - const bazDef = host.getDefinitionOfFunction(bazNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration)!; + const bazDef = host.getDefinitionOfFunction(bazNode)!; expect(bazDef.node).toBe(bazNode); - expect(bazDef.body !.length).toEqual(3); + expect(bazDef.body!.length).toEqual(3); expect(bazDef.parameters.length).toEqual(1); expect(bazDef.parameters[0].name).toEqual('x'); expect(bazDef.parameters[0].initializer).toBe(null); const quxNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration) !; - const quxDef = host.getDefinitionOfFunction(quxNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration)!; + const quxDef = host.getDefinitionOfFunction(quxNode)!; expect(quxDef.node).toBe(quxNode); - expect(quxDef.body !.length).toEqual(2); + expect(quxDef.body!.length).toEqual(2); expect(quxDef.parameters.length).toEqual(1); expect(quxDef.parameters[0].name).toEqual('x'); expect(quxDef.parameters[0].initializer).toBe(null); @@ -1593,7 +1643,8 @@ exports.ExternalModule = ExternalModule; it('should find the import of an identifier', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/file_b.js'), 'b', isNamedVariableDeclaration); const identifier = (variableNode.initializer && @@ -1603,14 +1654,15 @@ exports.ExternalModule = ExternalModule; null; expect(identifier).not.toBe(null); - const importOfIdent = host.getImportOfIdentifier(identifier !); + const importOfIdent = host.getImportOfIdentifier(identifier!); expect(importOfIdent).toEqual({name: 'a', from: './file_a'}); }); it('should return null if the identifier was not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/file_b.js'), 'd', isNamedVariableDeclaration); const importOfIdent = @@ -1622,7 +1674,8 @@ exports.ExternalModule = ExternalModule; it('should handle factory functions not wrapped in parentheses', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/file_c.js'), 'c', isNamedVariableDeclaration); const identifier = (variableNode.initializer && @@ -1632,7 +1685,7 @@ exports.ExternalModule = ExternalModule; null; expect(identifier).not.toBe(null); - const importOfIdent = host.getImportOfIdentifier(identifier !); + const importOfIdent = host.getImportOfIdentifier(identifier!); expect(importOfIdent).toEqual({name: 'a', from: './file_a'}); }); }); @@ -1640,10 +1693,10 @@ exports.ExternalModule = ExternalModule; describe('getDeclarationOfIdentifier', () => { // Helpers const createTestForTsHelper = - (program: ts.Program, host: CommonJsReflectionHost, srcFile: TestFile, + (program: ts.Program, host: NgccReflectionHost, srcFile: TestFile, getHelperDeclaration: (name: string) => ts.Declaration) => (varName: string, helperName: string, knownAs: KnownDeclaration, - viaModule: string | null = null) => { + viaModule: string|null = null) => { const node = getDeclaration(program, srcFile.name, varName, ts.isVariableDeclaration); const helperIdentifier = getIdentifierFromCallExpression(node); @@ -1651,7 +1704,8 @@ exports.ExternalModule = ExternalModule; expect(helperDeclaration).toEqual({ known: knownAs, - node: getHelperDeclaration(helperName), viaModule, + node: getHelperDeclaration(helperName), + viaModule, }); }; @@ -1667,12 +1721,13 @@ exports.ExternalModule = ExternalModule; it('should return the declaration of a locally defined identifier', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const ctrDecorators = host.getConstructorParameters(classNode) !; - const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference !as{ + const ctrDecorators = host.getConstructorParameters(classNode)!; + const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference! as { local: true, expression: ts.Identifier, defaultImportStatement: null, @@ -1683,8 +1738,8 @@ exports.ExternalModule = ExternalModule; isNamedVariableDeclaration); const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe(null); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe(null); }); it('should return the correct declaration for an outer alias identifier', () => { @@ -1702,7 +1757,8 @@ exports.ExternalModule = ExternalModule; loadTestFiles([PROGRAM_FILE]); const bundle = makeTestBundleProgram(PROGRAM_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const expectedDeclaration = getDeclaration( bundle.program, PROGRAM_FILE.name, 'AliasedClass', isNamedVariableDeclaration); @@ -1713,29 +1769,31 @@ exports.ExternalModule = ExternalModule; expect(aliasIdentifier.getText()).toBe('AliasedClass_1'); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclaration); + expect(actualDeclaration!.node).toBe(expectedDeclaration); }); it('should return the source-file of an import namespace', () => { loadFakeCore(getFileSystem()); loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; - const identifierOfDirective = (((classDecorators[0].node as ts.ObjectLiteralExpression) - .properties[0] as ts.PropertyAssignment) - .initializer as ts.PropertyAccessExpression) - .expression as ts.Identifier; + const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; + const identifierOfDirective = + (((classDecorators[0].node as ts.ObjectLiteralExpression).properties[0] as + ts.PropertyAssignment) + .initializer as ts.PropertyAccessExpression) + .expression as ts.Identifier; const expectedDeclarationNode = getSourceFileOrError(bundle.program, _('/node_modules/@angular/core/index.d.ts')); const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe('@angular/core'); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe('@angular/core'); }); it('should return viaModule: null for relative imports', () => { @@ -1756,12 +1814,13 @@ exports.ExternalModule = ExternalModule; ]); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/index.js'), 'b', isNamedVariableDeclaration); const identifier = variableNode.name as ts.Identifier; - const importOfIdent = host.getDeclarationOfIdentifier(identifier !) !; + const importOfIdent = host.getDeclarationOfIdentifier(identifier!)!; expect(importOfIdent.node).not.toBeNull(); expect(importOfIdent.viaModule).toBeNull(); }); @@ -1782,13 +1841,14 @@ exports.ExternalModule = ExternalModule; ]); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/index.js'), 'b', isNamedVariableDeclaration); const identifier = - (variableNode.initializer !as ts.PropertyAccessExpression).name as ts.Identifier; + (variableNode.initializer! as ts.PropertyAccessExpression).name as ts.Identifier; - const importOfIdent = host.getDeclarationOfIdentifier(identifier !) !; + const importOfIdent = host.getDeclarationOfIdentifier(identifier!)!; expect(importOfIdent.viaModule).toBe('lib'); }); @@ -1807,7 +1867,8 @@ exports.ExternalModule = ExternalModule; }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -1834,7 +1895,8 @@ exports.ExternalModule = ExternalModule; }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -1861,7 +1923,8 @@ exports.ExternalModule = ExternalModule; }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -1888,7 +1951,8 @@ exports.ExternalModule = ExternalModule; }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -1925,7 +1989,8 @@ exports.ExternalModule = ExternalModule; const [testFile, tslibFile] = files; const bundle = makeTestBundleProgram(testFile.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const tslibSourceFile = getSourceFileOrError(bundle.program, tslibFile.name); const testForHelper = @@ -1942,12 +2007,13 @@ exports.ExternalModule = ExternalModule; loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/b_module.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, '@angular/core'], ['a', `a = 'a'`, null], @@ -1968,13 +2034,14 @@ exports.ExternalModule = ExternalModule; loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/wildcard_reexports_emitted_helpers.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, _('/b_module')], ['a', `a = 'a'`, _('/b_module')], @@ -1997,13 +2064,14 @@ exports.ExternalModule = ExternalModule; loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/wildcard_reexports_imported_helpers.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, _('/b_module')], ['a', `a = 'a'`, _('/b_module')], @@ -2025,11 +2093,12 @@ exports.ExternalModule = ExternalModule; it('should handle inline exports', () => { loadTestFiles([INLINE_EXPORT_FILE]); const bundle = makeTestBundleProgram(_('/inline_export.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/inline_export.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBeNull(); - const decl = exportDeclarations !.get('directives') as InlineDeclaration; + const decl = exportDeclarations!.get('directives') as InlineDeclaration; expect(decl).not.toBeUndefined(); expect(decl.node).toBeNull(); expect(decl.expression).toBeDefined(); @@ -2047,9 +2116,10 @@ exports.ExternalModule = ExternalModule; }; loadTestFiles([tslib]); const bundle = makeTestBundleProgram(tslib.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const sf = getSourceFileOrError(bundle.program, tslib.name); - const exportDeclarations = host.getExportsOfModule(sf) !; + const exportDeclarations = host.getExportsOfModule(sf)!; expect([...exportDeclarations].map(([exportName, {known}]) => [exportName, known])) .toEqual([ @@ -2065,56 +2135,59 @@ exports.ExternalModule = ExternalModule; it('should return the class symbol for an ES2015 class', () => { loadTestFiles([SIMPLE_ES2015_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_ES2015_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_ES2015_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); const classSymbol = host.getClassSymbol(node); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(node); - expect(classSymbol !.implementation.valueDeclaration).toBe(node); + expect(classSymbol!.declaration.valueDeclaration).toBe(node); + expect(classSymbol!.implementation.valueDeclaration).toBe(node); }); it('should return the class symbol for an ES5 class (outer variable declaration)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the class symbol for an ES5 class (inner function declaration)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(innerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the same class symbol (of the outer declaration) for outer and inner declarations', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = - getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; - const innerSymbol = host.getClassSymbol(innerNode) !; - const outerSymbol = host.getClassSymbol(outerNode) !; + const innerSymbol = host.getClassSymbol(innerNode)!; + const outerSymbol = host.getClassSymbol(outerNode)!; expect(innerSymbol.declaration).toBe(outerSymbol.declaration); expect(innerSymbol.implementation).toBe(outerSymbol.implementation); }); @@ -2123,40 +2196,41 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'NoParensClass', isNamedVariableDeclaration); - const innerNode = - getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the class symbol for an ES5 class whose IIFE is not wrapped with inner parens', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'InnerParensClass', isNamedVariableDeclaration); - const innerNode = - getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return undefined if node is not an ES5 class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const classSymbol = host.getClassSymbol(node); @@ -2172,7 +2246,8 @@ exports.ExternalModule = ExternalModule; }; loadTestFiles([testFile]); const bundle = makeTestBundleProgram(testFile.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, testFile.name, 'MyClass', isNamedVariableDeclaration); const classSymbol = host.getClassSymbol(node); @@ -2185,7 +2260,8 @@ exports.ExternalModule = ExternalModule; it('should return true if a given node is a TS class declaration', () => { loadTestFiles([SIMPLE_ES2015_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_ES2015_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_ES2015_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); expect(host.isClass(node)).toBe(true); @@ -2195,7 +2271,8 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration); expect(host.isClass(node)).toBe(true); @@ -2205,18 +2282,19 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration); - const innerNode = - getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; expect(host.isClass(innerNode)).toBe(true); }); it('should return false if a given node is a function declaration', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(host.isClass(node)).toBe(false); @@ -2232,7 +2310,8 @@ exports.ExternalModule = ExternalModule; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); return host.hasBaseClass(classNode); @@ -2279,7 +2358,8 @@ exports.ExternalModule = ExternalModule; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); const expression = host.getBaseClassExpression(classNode); @@ -2301,7 +2381,7 @@ exports.ExternalModule = ExternalModule; function TestClass() {} return TestClass; }(BaseClass));`); - expect(identifier !.text).toBe('BaseClass'); + expect(identifier!.text).toBe('BaseClass'); }); it('should find the base class of an IIFE with a unique name generated for the _super parameter', @@ -2316,7 +2396,7 @@ exports.ExternalModule = ExternalModule; function TestClass() {} return TestClass; }(BaseClass));`); - expect(identifier !.text).toBe('BaseClass'); + expect(identifier!.text).toBe('BaseClass'); }); it('should not find a base class for an IIFE without parameter', () => { @@ -2351,10 +2431,11 @@ exports.ExternalModule = ExternalModule; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); - const expression = host.getBaseClassExpression(classNode) !; + const expression = host.getBaseClassExpression(classNode)!; expect(expression.getText()).toBe('foo()'); }); }); @@ -2363,7 +2444,8 @@ exports.ExternalModule = ExternalModule; it('should return an array of all classes in the given source file', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(getRootFiles(DECORATED_FILES)[0]); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); @@ -2381,7 +2463,8 @@ exports.ExternalModule = ExternalModule; it('should return decorators of class symbol', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(getRootFiles(DECORATED_FILES)[0]); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); @@ -2389,14 +2472,14 @@ exports.ExternalModule = ExternalModule; const classDecoratorsPrimary = classSymbolsPrimary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsPrimary.length).toEqual(2); - expect(classDecoratorsPrimary[0] !.map(d => d.name)).toEqual(['Directive']); - expect(classDecoratorsPrimary[1] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[0]!.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[1]!.map(d => d.name)).toEqual(['Directive']); const classSymbolsSecondary = host.findClassSymbols(secondaryFile); const classDecoratorsSecondary = classSymbolsSecondary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsSecondary.length).toEqual(1); - expect(classDecoratorsSecondary[0] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsSecondary[0]!.map(d => d.name)).toEqual(['Directive']); }); }); @@ -2409,11 +2492,11 @@ exports.ExternalModule = ExternalModule; const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/class1.js'), 'Class1', ts.isVariableDeclaration); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = createHost( + bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName) - .toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find the dts declaration for exported functions', () => { @@ -2423,9 +2506,10 @@ exports.ExternalModule = ExternalModule; const dts = makeTestDtsBundleProgram(_('/ep/typings/func1.d.ts'), _('/')); const mooFn = getDeclaration( bundle.program, _('/ep/src/func1.js'), 'mooFn', ts.isFunctionDeclaration); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(mooFn); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); }); it('should return null if there is no matching class in the matching dts file', () => { @@ -2435,7 +2519,8 @@ exports.ExternalModule = ExternalModule; const dts = makeTestDtsBundleProgram(_('/ep/typings/index.d.ts'), _('/')); const missingClass = getDeclaration( bundle.program, _('/ep/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2448,7 +2533,8 @@ exports.ExternalModule = ExternalModule; const missingClass = getDeclaration( bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2', ts.isVariableDeclaration); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2461,11 +2547,11 @@ exports.ExternalModule = ExternalModule; const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = createHost( + bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName) - .toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find aliased exports', () => { @@ -2475,7 +2561,8 @@ exports.ExternalModule = ExternalModule; const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const sourceClass = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', ts.isVariableDeclaration); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(sourceClass); if (dtsDeclaration === null) { @@ -2498,10 +2585,11 @@ exports.ExternalModule = ExternalModule; const internalClass = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'InternalClass', ts.isVariableDeclaration); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = createHost( + bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(internalClass); - expect(dtsDeclaration !.getSourceFile().fileName) + expect(dtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/internal.d.ts')); }); @@ -2511,18 +2599,19 @@ exports.ExternalModule = ExternalModule; loadTestFiles(TYPINGS_DTS_FILES); const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]); const dts = makeTestDtsBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0], _('/ep')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts); + const host = createHost( + bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle, dts)); const class2 = getDeclaration( bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedVariableDeclaration); const class2DtsDeclaration = host.getDtsDeclaration(class2); - expect(class2DtsDeclaration !.getSourceFile().fileName) + expect(class2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/class2.d.ts')); const internalClass2 = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedVariableDeclaration); const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2); - expect(internalClass2DtsDeclaration !.getSourceFile().fileName) + expect(internalClass2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/internal.d.ts')); }); }); @@ -2531,7 +2620,8 @@ exports.ExternalModule = ExternalModule; it('should return the name of the inner class declaration', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const emptyClass = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); @@ -2555,7 +2645,8 @@ exports.ExternalModule = ExternalModule; it('should return the name of the inner class declaration', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const emptyClass = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); @@ -2580,10 +2671,11 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/functions.js')); const fns = host.getModuleWithProvidersFunctions(file); - expect(fns.map(fn => [fn.declaration.name !.getText(), fn.ngModule.node.name.text])) + expect(fns.map(fn => [fn.declaration.name!.getText(), fn.ngModule.node.name.text])) .toEqual([ ['ngModuleIdentifier', 'InternalModule'], ['ngModuleWithEmptyProviders', 'InternalModule'], @@ -2596,7 +2688,8 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/methods.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ @@ -2623,7 +2716,8 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/outer_aliased_class.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ @@ -2636,7 +2730,8 @@ exports.ExternalModule = ExternalModule; () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new CommonJsReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new CommonJsReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/inner_aliased_class.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ diff --git a/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts b/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts index 6f086011db..f0b5956d1b 100644 --- a/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts @@ -9,11 +9,13 @@ import * as ts from 'typescript'; import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; -import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; -import {ClassMemberKind, CtorParameter, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; +import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; +import {ClassMemberKind, CtorParameter, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; +import {DelegatingReflectionHost} from '../../src/host/delegating_host'; import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; +import {BundleProgram} from '../../src/packages/bundle_program'; import {MockLogger} from '../helpers/mock_logger'; import {getRootFiles, makeTestBundleProgram, makeTestDtsBundleProgram} from '../helpers/utils'; @@ -21,7 +23,6 @@ import {expectTypeValueReferencesForParameters} from './util'; runInEachFileSystem(() => { describe('Esm2015ReflectionHost', () => { - let _: typeof absoluteFrom; let SOME_DIRECTIVE_FILE: TestFile; @@ -48,6 +49,12 @@ runInEachFileSystem(() => { let NAMESPACED_IMPORT_FILE: TestFile; let INDEX_SIGNATURE_PROP_FILE: TestFile; + // Helpers + const createHost = (bundle: BundleProgram, ngccHost: Esm2015ReflectionHost) => { + const tsHost = new TypeScriptReflectionHost(bundle.program.getTypeChecker()); + return new DelegatingReflectionHost(tsHost, ngccHost); + }; + beforeEach(() => { _ = absoluteFrom; @@ -720,10 +727,10 @@ runInEachFileSystem(() => { it('should find the decorators on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -731,7 +738,7 @@ runInEachFileSystem(() => { const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -739,10 +746,10 @@ runInEachFileSystem(() => { it('should find the decorators on an aliased class', () => { loadTestFiles([CLASS_EXPRESSION_FILE]); const bundle = makeTestBundleProgram(CLASS_EXPRESSION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, CLASS_EXPRESSION_FILE.name, 'AliasedClass', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -750,7 +757,7 @@ runInEachFileSystem(() => { const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -758,7 +765,7 @@ runInEachFileSystem(() => { it('should return null if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const decorators = host.getDecoratorsOfDeclaration(functionNode); @@ -768,7 +775,7 @@ runInEachFileSystem(() => { it('should return null if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); const decorators = host.getDecoratorsOfDeclaration(classNode); @@ -778,7 +785,7 @@ runInEachFileSystem(() => { it('should ignore `decorators` if it is not an array literal', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedClassDeclaration); @@ -789,11 +796,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements that are not object literals', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -802,11 +809,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements that have no `type` property', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NoTypeProperty', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -815,10 +822,10 @@ runInEachFileSystem(() => { it('should ignore decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotIdentifier', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -827,10 +834,10 @@ runInEachFileSystem(() => { it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'}); @@ -840,11 +847,12 @@ runInEachFileSystem(() => { it('should be an empty array if decorator has no `args` property', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -854,11 +862,12 @@ runInEachFileSystem(() => { it('should be an empty array if decorator\'s `args` has no property assignment', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -868,11 +877,12 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedClassDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -885,43 +895,43 @@ runInEachFileSystem(() => { it('should find decorated properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const input1 = members.find(member => member.name === 'input1') !; + const input1 = members.find(member => member.name === 'input1')!; expect(input1.kind).toEqual(ClassMemberKind.Property); expect(input1.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); - expect(input1.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'}); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators![0].import).toEqual({name: 'Input', from: '@angular/core'}); - const input2 = members.find(member => member.name === 'input2') !; + const input2 = members.find(member => member.name === 'input2')!; expect(input2.kind).toEqual(ClassMemberKind.Property); expect(input2.isStatic).toEqual(false); - expect(input2.decorators !.map(d => d.name)).toEqual(['Input']); - expect(input2.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'}); + expect(input2.decorators!.map(d => d.name)).toEqual(['Input']); + expect(input2.decorators![0].import).toEqual({name: 'Input', from: '@angular/core'}); }); it('should find non decorated properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const instanceProperty = members.find(member => member.name === 'instanceProperty') !; + const instanceProperty = members.find(member => member.name === 'instanceProperty')!; expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); expect(instanceProperty.isStatic).toEqual(false); - expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true); - expect(instanceProperty.value !.getText()).toEqual(`'instance'`); + expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true); + expect(instanceProperty.value!.getText()).toEqual(`'instance'`); }); it('should handle equally named getter/setter pairs correctly', () => { loadTestFiles([ACCESSORS_FILE]); const bundle = makeTestBundleProgram(ACCESSORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, ACCESSORS_FILE.name, 'SomeDirective', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); @@ -930,50 +940,50 @@ runInEachFileSystem(() => { members.filter(member => member.name === 'setterAndGetter'); expect(combinedSetter.kind).toEqual(ClassMemberKind.Setter); expect(combinedSetter.isStatic).toEqual(false); - expect(ts.isSetAccessor(combinedSetter.implementation !)).toEqual(true); + expect(ts.isSetAccessor(combinedSetter.implementation!)).toEqual(true); expect(combinedSetter.value).toBeNull(); - expect(combinedSetter.decorators !.map(d => d.name)).toEqual(['Input']); + expect(combinedSetter.decorators!.map(d => d.name)).toEqual(['Input']); expect(combinedGetter.kind).toEqual(ClassMemberKind.Getter); expect(combinedGetter.isStatic).toEqual(false); - expect(ts.isGetAccessor(combinedGetter.implementation !)).toEqual(true); + expect(ts.isGetAccessor(combinedGetter.implementation!)).toEqual(true); expect(combinedGetter.value).toBeNull(); - expect(combinedGetter.decorators !.map(d => d.name)).toEqual([]); + expect(combinedGetter.decorators!.map(d => d.name)).toEqual([]); }); it('should find static methods on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const staticMethod = members.find(member => member.name === 'staticMethod') !; + const staticMethod = members.find(member => member.name === 'staticMethod')!; expect(staticMethod.kind).toEqual(ClassMemberKind.Method); expect(staticMethod.isStatic).toEqual(true); - expect(ts.isMethodDeclaration(staticMethod.implementation !)).toEqual(true); + expect(ts.isMethodDeclaration(staticMethod.implementation!)).toEqual(true); }); it('should find static properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const staticProperty = members.find(member => member.name === 'staticProperty') !; + const staticProperty = members.find(member => member.name === 'staticProperty')!; expect(staticProperty.kind).toEqual(ClassMemberKind.Property); expect(staticProperty.isStatic).toEqual(true); - expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true); - expect(staticProperty.value !.getText()).toEqual(`'static'`); + expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true); + expect(staticProperty.value!.getText()).toEqual(`'static'`); }); it('should ignore index signature properties', () => { loadTestFiles([INDEX_SIGNATURE_PROP_FILE]); const logger = new MockLogger(); const bundle = makeTestBundleProgram(INDEX_SIGNATURE_PROP_FILE.name); - const host = new Esm2015ReflectionHost(logger, false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(logger, false, bundle)); const classNode = getDeclaration( bundle.program, INDEX_SIGNATURE_PROP_FILE.name, 'IndexSignatureClass', isNamedClassDeclaration); @@ -986,7 +996,7 @@ runInEachFileSystem(() => { it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(() => { @@ -997,7 +1007,7 @@ runInEachFileSystem(() => { it('should return an empty array if there are no prop decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); @@ -1009,7 +1019,8 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedClassDeclaration); @@ -1021,13 +1032,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements that are not object literals', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteralProp', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'})); @@ -1036,13 +1047,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements that have no `type` property', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NoTypeProperty', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'})); @@ -1051,13 +1062,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotIdentifier', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'})); @@ -1067,13 +1078,14 @@ runInEachFileSystem(() => { it('should be an empty array if prop decorator has no `args` property', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1084,13 +1096,14 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1100,13 +1113,14 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedClassDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1120,10 +1134,10 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters).toBeDefined(); expect(parameters.map(parameter => parameter.name)).toEqual([ @@ -1136,11 +1150,11 @@ runInEachFileSystem(() => { it('should accept `ctorParameters` as an array', () => { loadTestFiles([CTOR_DECORATORS_ARRAY_FILE]); const bundle = makeTestBundleProgram(CTOR_DECORATORS_ARRAY_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, CTOR_DECORATORS_ARRAY_FILE.name, 'CtorDecoratedAsArray', isNamedClassDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters).toBeDefined(); expect(parameters.map(parameter => parameter.name)).toEqual(['arg1']); @@ -1150,10 +1164,12 @@ runInEachFileSystem(() => { it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); - expect(() => { host.getConstructorParameters(functionNode); }) + expect(() => { + host.getConstructorParameters(functionNode); + }) .toThrowError( 'Attempted to get constructor parameters of a non-class: "function foo() {}"'); }); @@ -1161,7 +1177,7 @@ runInEachFileSystem(() => { it('should return `null` if there is no constructor', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); const parameters = host.getConstructorParameters(classNode); @@ -1171,11 +1187,11 @@ runInEachFileSystem(() => { it('should return an array even if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', isNamedClassDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters).toEqual(jasmine.any(Array)); expect(parameters.length).toEqual(1); @@ -1186,7 +1202,7 @@ runInEachFileSystem(() => { it('should return an empty array if there are no constructor parameters', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoParameters', isNamedClassDeclaration); @@ -1198,11 +1214,11 @@ runInEachFileSystem(() => { it('should ignore decorators that are not imported from core', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotFromCore', isNamedClassDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters.length).toBe(1); expect(parameters[0]).toEqual(jasmine.objectContaining({ @@ -1214,11 +1230,11 @@ runInEachFileSystem(() => { it('should ignore `ctorParameters` if it is not an arrow function', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrowFunction', isNamedClassDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters.length).toBe(1); expect(parameters[0]).toEqual(jasmine.objectContaining({ @@ -1230,11 +1246,11 @@ runInEachFileSystem(() => { it('should ignore `ctorParameters` if it does not return an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedClassDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters.length).toBe(1); expect(parameters[0]).toEqual(jasmine.objectContaining({ @@ -1257,7 +1273,8 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedClassDeclaration); return host.getConstructorParameters(classNode); @@ -1279,7 +1296,7 @@ runInEachFileSystem(() => { super(arguments); }`); - expect(parameters !.length).toBe(0); + expect(parameters!.length).toBe(0); }); it('does not consider constructors with parameters as synthesized', () => { @@ -1288,7 +1305,7 @@ runInEachFileSystem(() => { super(...arguments); }`); - expect(parameters !.length).toBe(1); + expect(parameters!.length).toBe(1); }); it('does not consider manual super calls as synthesized', () => { @@ -1297,7 +1314,7 @@ runInEachFileSystem(() => { super(); }`); - expect(parameters !.length).toBe(0); + expect(parameters!.length).toBe(0); }); it('does not consider empty constructors as synthesized', () => { @@ -1305,7 +1322,7 @@ runInEachFileSystem(() => { constructor() { }`); - expect(parameters !.length).toBe(0); + expect(parameters!.length).toBe(0); }); }); @@ -1313,18 +1330,19 @@ runInEachFileSystem(() => { it('should ignore param decorator elements that are not object literals', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedClassDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(2); - expect(parameters ![0]).toEqual(jasmine.objectContaining({ + expect(parameters!.length).toBe(2); + expect(parameters![0]).toEqual(jasmine.objectContaining({ name: 'arg1', decorators: null, })); - expect(parameters ![1]).toEqual(jasmine.objectContaining({ + expect(parameters![1]).toEqual(jasmine.objectContaining({ name: 'arg2', decorators: jasmine.any(Array) as any })); @@ -1333,12 +1351,13 @@ runInEachFileSystem(() => { it('should ignore param decorator elements that have no `type` property', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoTypeProperty', isNamedClassDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1347,12 +1366,13 @@ runInEachFileSystem(() => { it('should ignore param decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotIdentifier', isNamedClassDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1361,11 +1381,12 @@ runInEachFileSystem(() => { it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); - const parameters = host.getConstructorParameters(classNode) !; - const decorators = parameters[2].decorators !; + const parameters = host.getConstructorParameters(classNode)!; + const decorators = parameters[2].decorators!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'}); @@ -1376,13 +1397,14 @@ runInEachFileSystem(() => { it('should be an empty array if param decorator has no `args` property', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedClassDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(1); - const decorators = parameters ![0].decorators !; + expect(parameters!.length).toBe(1); + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1393,12 +1415,13 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedClassDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1408,12 +1431,13 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedClassDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1427,61 +1451,62 @@ runInEachFileSystem(() => { () => { loadTestFiles([FUNCTION_BODY_FILE]); const bundle = makeTestBundleProgram(FUNCTION_BODY_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const fooNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration) !; - const fooDef = host.getDefinitionOfFunction(fooNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration)!; + const fooDef = host.getDefinitionOfFunction(fooNode)!; expect(fooDef.node).toBe(fooNode); - expect(fooDef.body !.length).toEqual(1); - expect(fooDef.body ![0].getText()).toEqual(`return x;`); + expect(fooDef.body!.length).toEqual(1); + expect(fooDef.body![0].getText()).toEqual(`return x;`); expect(fooDef.parameters.length).toEqual(1); expect(fooDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); const barNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration) !; - const barDef = host.getDefinitionOfFunction(barNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration)!; + const barDef = host.getDefinitionOfFunction(barNode)!; expect(barDef.node).toBe(barNode); - expect(barDef.body !.length).toEqual(1); - expect(ts.isReturnStatement(barDef.body ![0])).toBeTruthy(); - expect(barDef.body ![0].getText()).toEqual(`return x + y;`); + expect(barDef.body!.length).toEqual(1); + expect(ts.isReturnStatement(barDef.body![0])).toBeTruthy(); + expect(barDef.body![0].getText()).toEqual(`return x + y;`); expect(barDef.parameters.length).toEqual(2); expect(barDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); expect(barDef.parameters[1].name).toEqual('y'); - expect(barDef.parameters[1].initializer !.getText()).toEqual('42'); + expect(barDef.parameters[1].initializer!.getText()).toEqual('42'); const bazNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration) !; - const bazDef = host.getDefinitionOfFunction(bazNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration)!; + const bazDef = host.getDefinitionOfFunction(bazNode)!; expect(bazDef.node).toBe(bazNode); - expect(bazDef.body !.length).toEqual(3); + expect(bazDef.body!.length).toEqual(3); expect(bazDef.parameters.length).toEqual(1); expect(bazDef.parameters[0].name).toEqual('x'); expect(bazDef.parameters[0].initializer).toBe(null); const quxNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration) !; - const quxDef = host.getDefinitionOfFunction(quxNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration)!; + const quxDef = host.getDefinitionOfFunction(quxNode)!; expect(quxDef.node).toBe(quxNode); - expect(quxDef.body !.length).toEqual(2); + expect(quxDef.body!.length).toEqual(2); expect(quxDef.parameters.length).toEqual(1); expect(quxDef.parameters[0].name).toEqual('x'); expect(quxDef.parameters[0].initializer).toBe(null); const mooNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'moo', isNamedFunctionDeclaration) !; - const mooDef = host.getDefinitionOfFunction(mooNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'moo', isNamedFunctionDeclaration)!; + const mooDef = host.getDefinitionOfFunction(mooNode)!; expect(mooDef.node).toBe(mooNode); - expect(mooDef.body !.length).toEqual(3); + expect(mooDef.body!.length).toEqual(3); expect(mooDef.parameters).toEqual([]); const juuNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'juu', isNamedFunctionDeclaration) !; - const juuDef = host.getDefinitionOfFunction(juuNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'juu', isNamedFunctionDeclaration)!; + const juuDef = host.getDefinitionOfFunction(juuNode)!; expect(juuDef.node).toBe(juuNode); - expect(juuDef.body !.length).toEqual(2); + expect(juuDef.body!.length).toEqual(2); expect(juuDef.parameters).toEqual([]); }); }); @@ -1490,7 +1515,7 @@ runInEachFileSystem(() => { it('should find the import of an identifier', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/b.js'), 'b', isNamedVariableDeclaration); const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier); @@ -1501,7 +1526,7 @@ runInEachFileSystem(() => { it('should find the name by which the identifier was exported, not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/b.js'), 'c', isNamedVariableDeclaration); const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier); @@ -1512,7 +1537,7 @@ runInEachFileSystem(() => { it('should return null if the identifier was not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/b.js'), 'd', isNamedVariableDeclaration); const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier); @@ -1526,61 +1551,63 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); const actualDeclaration = host.getDeclarationOfIdentifier(classNode.name); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(classNode); - expect(actualDeclaration !.viaModule).toBe(null); + expect(actualDeclaration!.node).toBe(classNode); + expect(actualDeclaration!.viaModule).toBe(null); }); it('should return the declaration of an externally defined identifier', () => { loadFakeCore(getFileSystem()); loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedClassDeclaration); - const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; - const identifierOfDirective = ((classDecorators[0].node as ts.ObjectLiteralExpression) - .properties[0] as ts.PropertyAssignment) - .initializer as ts.Identifier; + const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; + const identifierOfDirective = + ((classDecorators[0].node as ts.ObjectLiteralExpression).properties[0] as + ts.PropertyAssignment) + .initializer as ts.Identifier; const expectedDeclarationNode = getDeclaration( bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive', isNamedVariableDeclaration); const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe('@angular/core'); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe('@angular/core'); }); it('should return the source-file of an import namespace', () => { loadFakeCore(getFileSystem()); loadTestFiles([NAMESPACED_IMPORT_FILE]); const bundle = makeTestBundleProgram(NAMESPACED_IMPORT_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, NAMESPACED_IMPORT_FILE.name, 'SomeDirective', ts.isClassDeclaration); - const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; - const identifier = (((classDecorators[0].node as ts.ObjectLiteralExpression) - .properties[0] as ts.PropertyAssignment) - .initializer as ts.PropertyAccessExpression) - .expression as ts.Identifier; + const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; + const identifier = + (((classDecorators[0].node as ts.ObjectLiteralExpression).properties[0] as + ts.PropertyAssignment) + .initializer as ts.PropertyAccessExpression) + .expression as ts.Identifier; const expectedDeclarationNode = getSourceFileOrError(bundle.program, _('/node_modules/@angular/core/index.d.ts')); const actualDeclaration = host.getDeclarationOfIdentifier(identifier); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe('@angular/core'); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe('@angular/core'); }); it('should return the original declaration of an aliased class', () => { loadTestFiles([CLASS_EXPRESSION_FILE]); const bundle = makeTestBundleProgram(CLASS_EXPRESSION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classDeclaration = getDeclaration( bundle.program, CLASS_EXPRESSION_FILE.name, 'AliasedClass', ts.isVariableDeclaration); const usageOfAliasedClass = getDeclaration( @@ -1588,7 +1615,7 @@ runInEachFileSystem(() => { ts.isVariableDeclaration); const aliasedClassIdentifier = usageOfAliasedClass.initializer as ts.Identifier; expect(aliasedClassIdentifier.text).toBe('AliasedClass_1'); - expect(host.getDeclarationOfIdentifier(aliasedClassIdentifier) !.node) + expect(host.getDeclarationOfIdentifier(aliasedClassIdentifier)!.node) .toBe(classDeclaration); }); }); @@ -1598,11 +1625,11 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/b.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.keys())).toEqual([ + expect(Array.from(exportDeclarations!.keys())).toEqual([ 'Directive', 'a', 'b', @@ -1614,8 +1641,8 @@ runInEachFileSystem(() => { ]); const values = - Array.from(exportDeclarations !.values()) - .map(declaration => [declaration.node !.getText(), declaration.viaModule]); + Array.from(exportDeclarations!.values()) + .map(declaration => [declaration.node!.getText(), declaration.viaModule]); expect(values).toEqual([ [`Directive: FnWithArg<(clazz: any) => any>`, null], [`a = 'a'`, null], @@ -1633,21 +1660,22 @@ runInEachFileSystem(() => { it('should return the class symbol for an ES2015 class', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); const classSymbol = host.getClassSymbol(node); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(node); - expect(classSymbol !.implementation.valueDeclaration).toBe(node); + expect(classSymbol!.declaration.valueDeclaration).toBe(node); + expect(classSymbol!.implementation.valueDeclaration).toBe(node); }); it('should return the class symbol for a class expression (outer variable declaration)', () => { loadTestFiles([CLASS_EXPRESSION_FILE]); const bundle = makeTestBundleProgram(CLASS_EXPRESSION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, CLASS_EXPRESSION_FILE.name, 'EmptyClass', isNamedVariableDeclaration); @@ -1655,36 +1683,37 @@ runInEachFileSystem(() => { const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the class symbol for a class expression (inner class expression)', () => { loadTestFiles([CLASS_EXPRESSION_FILE]); const bundle = makeTestBundleProgram(CLASS_EXPRESSION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, CLASS_EXPRESSION_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const innerNode = (outerNode.initializer as ts.ClassExpression); const classSymbol = host.getClassSymbol(innerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the same class symbol (of the outer declaration) for outer and inner declarations', () => { loadTestFiles([CLASS_EXPRESSION_FILE]); const bundle = makeTestBundleProgram(CLASS_EXPRESSION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, CLASS_EXPRESSION_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const innerNode = (outerNode.initializer as ts.ClassExpression); - const innerSymbol = host.getClassSymbol(innerNode) !; - const outerSymbol = host.getClassSymbol(outerNode) !; + const innerSymbol = host.getClassSymbol(innerNode)!; + const outerSymbol = host.getClassSymbol(outerNode)!; expect(innerSymbol.declaration).toBe(outerSymbol.declaration); expect(innerSymbol.implementation).toBe(outerSymbol.implementation); }); @@ -1692,7 +1721,7 @@ runInEachFileSystem(() => { it('should return undefined if node is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const classSymbol = host.getClassSymbol(node); @@ -1708,7 +1737,8 @@ runInEachFileSystem(() => { }; loadTestFiles([testFile]); const bundle = makeTestBundleProgram(testFile.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration(bundle.program, testFile.name, 'MyClass', isNamedVariableDeclaration); const classSymbol = host.getClassSymbol(node); @@ -1721,7 +1751,7 @@ runInEachFileSystem(() => { it('should return true if a given node is a TS class declaration', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); expect(host.isClass(node)).toBe(true); @@ -1731,7 +1761,8 @@ runInEachFileSystem(() => { () => { loadTestFiles([CLASS_EXPRESSION_FILE]); const bundle = makeTestBundleProgram(CLASS_EXPRESSION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, CLASS_EXPRESSION_FILE.name, 'EmptyClass', ts.isVariableDeclaration); expect(host.isClass(node)).toBe(true); @@ -1741,7 +1772,8 @@ runInEachFileSystem(() => { () => { loadTestFiles([CLASS_EXPRESSION_FILE]); const bundle = makeTestBundleProgram(CLASS_EXPRESSION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, CLASS_EXPRESSION_FILE.name, 'AliasedClass', ts.isVariableDeclaration); @@ -1751,7 +1783,7 @@ runInEachFileSystem(() => { it('should return false if a given node is a TS function declaration', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(host.isClass(node)).toBe(false); @@ -1766,7 +1798,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedClassDeclaration); expect(host.hasBaseClass(classNode)).toBe(false); @@ -1781,7 +1813,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedClassDeclaration); expect(host.hasBaseClass(classNode)).toBe(true); @@ -1797,7 +1829,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); expect(host.hasBaseClass(classNode)).toBe(true); @@ -1812,7 +1844,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedClassDeclaration); expect(host.getBaseClassExpression(classNode)).toBe(null); @@ -1827,10 +1859,10 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedClassDeclaration); - const baseIdentifier = host.getBaseClassExpression(classNode) !; + const baseIdentifier = host.getBaseClassExpression(classNode)!; if (!ts.isIdentifier(baseIdentifier)) { throw new Error(`Expected ${baseIdentifier.getText()} to be an identifier.`); } @@ -1847,10 +1879,10 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); - const baseIdentifier = host.getBaseClassExpression(classNode) !; + const baseIdentifier = host.getBaseClassExpression(classNode)!; if (!ts.isIdentifier(baseIdentifier)) { throw new Error(`Expected ${baseIdentifier.getText()} to be an identifier.`); } @@ -1868,10 +1900,11 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedClassDeclaration); - const baseExpression = host.getBaseClassExpression(classNode) !; + const baseExpression = host.getBaseClassExpression(classNode)!; expect(baseExpression.getText()).toEqual('foo()'); }); }); @@ -1881,7 +1914,8 @@ runInEachFileSystem(() => { loadTestFiles(ARITY_CLASSES); const bundle = makeTestBundleProgram(ARITY_CLASSES[0].name); const dts = makeTestBundleProgram(ARITY_CLASSES[1].name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); const noTypeParamClass = getDeclaration( bundle.program, _('/src/class.js'), 'NoTypeParam', isNamedClassDeclaration); expect(host.getGenericArityOfClass(noTypeParamClass)).toBe(0); @@ -1899,10 +1933,11 @@ runInEachFileSystem(() => { () => { loadTestFiles([MARKER_FILE]); const bundle = makeTestBundleProgram(MARKER_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, MARKER_FILE.name); const declarations = host.getSwitchableDeclarations(file); - expect(declarations.map(d => [d.name.getText(), d.initializer !.getText()])).toEqual([ + expect(declarations.map(d => [d.name.getText(), d.initializer!.getText()])).toEqual([ ['compileNgModuleFactory', 'compileNgModuleFactory__PRE_R3__'] ]); }); @@ -1912,7 +1947,7 @@ runInEachFileSystem(() => { it('should return an array of all classes in the given source file', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(getRootFiles(DECORATED_FILES)[0]); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); @@ -1930,31 +1965,31 @@ runInEachFileSystem(() => { it('should return decorators of class symbol', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(getRootFiles(DECORATED_FILES)[0]); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); const classSymbolsPrimary = host.findClassSymbols(primaryFile); const classDecoratorsPrimary = classSymbolsPrimary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsPrimary.length).toEqual(3); - expect(classDecoratorsPrimary[0] !.map(d => d.name)).toEqual(['Directive']); - expect(classDecoratorsPrimary[1] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[0]!.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[1]!.map(d => d.name)).toEqual(['Directive']); expect(classDecoratorsPrimary[2]).toBe(null); const classSymbolsSecondary = host.findClassSymbols(secondaryFile); const classDecoratorsSecondary = classSymbolsSecondary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsSecondary.length).toEqual(1); - expect(classDecoratorsSecondary[0] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsSecondary[0]!.map(d => d.name)).toEqual(['Directive']); }); it('should return a cloned array on each invocation', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(getRootFiles(DECORATED_FILES)[0]); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const classDecl = - getDeclaration(bundle.program, DECORATED_FILES[0].name, 'A', ts.isClassDeclaration) !; - const classSymbol = host.getClassSymbol(classDecl) !; + getDeclaration(bundle.program, DECORATED_FILES[0].name, 'A', ts.isClassDeclaration)!; + const classSymbol = host.getClassSymbol(classDecl)!; const firstResult = host.getDecoratorsOfSymbol(classSymbol); const secondResult = host.getDecoratorsOfSymbol(classSymbol); @@ -1972,10 +2007,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/class1.js'), 'Class1', isNamedClassDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find the dts declaration for exported functions', () => { @@ -1985,10 +2021,11 @@ runInEachFileSystem(() => { const dts = makeTestDtsBundleProgram(_('/ep/typings/func1.d.ts'), _('/')); const mooFn = getDeclaration( bundle.program, _('/ep/src/func1.js'), 'mooFn', isNamedFunctionDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(mooFn); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); }); it('should return null if there is no matching class in the matching dts file', () => { @@ -1999,7 +2036,8 @@ runInEachFileSystem(() => { const missingClass = getDeclaration( bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2', isNamedClassDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2012,7 +2050,8 @@ runInEachFileSystem(() => { const missingClass = getDeclaration( bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2', isNamedClassDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2026,9 +2065,10 @@ runInEachFileSystem(() => { getRootFiles(TYPINGS_DTS_FILES)[0], false, [_('/ep/typings/shadow-class.d.ts')]); const shadowClass = getDeclaration( bundle.program, _('/ep/src/shadow-class.js'), 'ShadowClass', isNamedClassDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); - const dtsDecl = host.getDtsDeclaration(shadowClass) !; + const dtsDecl = host.getDtsDeclaration(shadowClass)!; expect(dtsDecl).not.toBeNull(); expect(dtsDecl.getSourceFile().fileName).toEqual(_('/ep/typings/shadow-class.d.ts')); }); @@ -2054,7 +2094,8 @@ runInEachFileSystem(() => { const missingClass = getDeclaration( bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2', isNamedClassDeclaration); - const host = new TestEsm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new TestEsm2015ReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBeNull(); }); @@ -2067,10 +2108,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'Class1', isNamedClassDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find aliased exports', () => { @@ -2080,7 +2122,8 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const sourceClass = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', isNamedClassDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(sourceClass); if (dtsDeclaration === null) { @@ -2102,11 +2145,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const internalClass = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'InternalClass', isNamedClassDeclaration); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(internalClass); - expect(dtsDeclaration !.getSourceFile().fileName) - .toEqual(_('/ep/typings/internal.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/internal.d.ts')); }); it('should match publicly and internal exported classes correctly, even if they have the same name', @@ -2115,18 +2158,19 @@ runInEachFileSystem(() => { loadTestFiles(TYPINGS_DTS_FILES); const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]); const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts)); const class2 = getDeclaration( bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedClassDeclaration); const class2DtsDeclaration = host.getDtsDeclaration(class2); - expect(class2DtsDeclaration !.getSourceFile().fileName) + expect(class2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/class2.d.ts')); const internalClass2 = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedClassDeclaration); const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2); - expect(internalClass2DtsDeclaration !.getSourceFile().fileName) + expect(internalClass2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/internal.d.ts')); }); }); @@ -2135,7 +2179,7 @@ runInEachFileSystem(() => { it('should return the name of the class (there is no separate inner class in ES2015)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); expect(host.getInternalNameOfClass(node).text).toEqual('EmptyClass'); @@ -2146,7 +2190,7 @@ runInEachFileSystem(() => { it('should return the name of the class (there is no separate inner class in ES2015)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); expect(host.getAdjacentNameOfClass(node).text).toEqual('EmptyClass'); @@ -2158,10 +2202,11 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(getRootFiles(MODULE_WITH_PROVIDERS_PROGRAM)[0]); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/functions.js')); const fns = host.getModuleWithProvidersFunctions(file); - expect(fns.map(fn => [fn.declaration.name !.getText(), fn.ngModule.node.name.text])) + expect(fns.map(fn => [fn.declaration.name!.getText(), fn.ngModule.node.name.text])) .toEqual([ ['ngModuleIdentifier', 'InternalModule'], ['ngModuleWithEmptyProviders', 'InternalModule'], @@ -2175,10 +2220,11 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(getRootFiles(MODULE_WITH_PROVIDERS_PROGRAM)[0]); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/methods.js')); const fn = host.getModuleWithProvidersFunctions(file); - expect(fn.map(fn => [fn.declaration.name !.getText(), fn.ngModule.node.name.text])) + expect(fn.map(fn => [fn.declaration.name!.getText(), fn.ngModule.node.name.text])) .toEqual([ ['ngModuleIdentifier', 'InternalModule'], ['ngModuleWithEmptyProviders', 'InternalModule'], @@ -2192,13 +2238,12 @@ runInEachFileSystem(() => { it('should resolve aliased module references to their original declaration', () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(getRootFiles(MODULE_WITH_PROVIDERS_PROGRAM)[0]); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/aliased_class.js')); const fn = host.getModuleWithProvidersFunctions(file); - expect(fn.map(fn => [fn.declaration.name !.getText(), fn.ngModule.node.name.text])) - .toEqual([ - ['forRoot', 'AliasedModule'], - ]); + expect(fn.map(fn => [fn.declaration.name!.getText(), fn.ngModule.node.name.text])).toEqual([ + ['forRoot', 'AliasedModule'], + ]); }); }); @@ -2224,8 +2269,8 @@ runInEachFileSystem(() => { }; loadTestFiles([testFile]); const bundle = makeTestBundleProgram(testFile.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); - const classSymbol = host.findClassSymbols(bundle.program.getSourceFile(testFile.name) !)[0]; + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); + const classSymbol = host.findClassSymbols(bundle.program.getSourceFile(testFile.name)!)[0]; const endOfClass = host.getEndOfClass(classSymbol); expect(endOfClass.getText()) .toEqual( @@ -2247,8 +2292,8 @@ runInEachFileSystem(() => { }; loadTestFiles([testFile]); const bundle = makeTestBundleProgram(testFile.name); - const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle); - const classSymbol = host.findClassSymbols(bundle.program.getSourceFile(testFile.name) !)[0]; + const host = createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); + const classSymbol = host.findClassSymbols(bundle.program.getSourceFile(testFile.name)!)[0]; const endOfClass = host.getEndOfClass(classSymbol); expect(endOfClass.getText()) .toEqual( diff --git a/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts b/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts index be3b064a67..8182a8807d 100644 --- a/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts @@ -9,12 +9,15 @@ import * as ts from 'typescript'; import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; -import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; -import {ClassMemberKind, CtorParameter, Decorator, KnownDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; +import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; +import {ClassMemberKind, CtorParameter, Decorator, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; +import {DelegatingReflectionHost} from '../../src/host/delegating_host'; import {Esm2015ReflectionHost} from '../../src/host/esm2015_host'; import {Esm5ReflectionHost, getIifeBody} from '../../src/host/esm5_host'; +import {NgccReflectionHost} from '../../src/host/ngcc_host'; +import {BundleProgram} from '../../src/packages/bundle_program'; import {MockLogger} from '../helpers/mock_logger'; import {getRootFiles, makeTestBundleProgram, makeTestDtsBundleProgram} from '../helpers/utils'; @@ -22,7 +25,6 @@ import {expectTypeValueReferencesForParameters} from './util'; runInEachFileSystem(() => { describe('Esm5ReflectionHost', () => { - let _: typeof absoluteFrom; let SOME_DIRECTIVE_FILE: TestFile; @@ -48,6 +50,12 @@ runInEachFileSystem(() => { let MODULE_WITH_PROVIDERS_PROGRAM: TestFile[]; let NAMESPACED_IMPORT_FILE: TestFile; + // Helpers + const createHost = (bundle: BundleProgram, ngccHost: Esm5ReflectionHost) => { + const tsHost = new TypeScriptReflectionHost(bundle.program.getTypeChecker()); + return new DelegatingReflectionHost(tsHost, ngccHost); + }; + beforeEach(() => { _ = absoluteFrom; SOME_DIRECTIVE_FILE = { @@ -891,10 +899,10 @@ runInEachFileSystem(() => { it('should find the decorators on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -902,7 +910,7 @@ runInEachFileSystem(() => { const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -910,11 +918,11 @@ runInEachFileSystem(() => { it('should find the decorators on a class at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -922,7 +930,7 @@ runInEachFileSystem(() => { const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -930,7 +938,7 @@ runInEachFileSystem(() => { it('should return null if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const decorators = host.getDecoratorsOfDeclaration(functionNode); @@ -940,7 +948,7 @@ runInEachFileSystem(() => { it('should return null if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const decorators = host.getDecoratorsOfDeclaration(classNode); @@ -950,7 +958,7 @@ runInEachFileSystem(() => { it('should ignore `decorators` if it is not an array literal', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); @@ -961,11 +969,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements that are not object literals', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -974,11 +982,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements that have no `type` property', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -987,11 +995,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1000,10 +1008,10 @@ runInEachFileSystem(() => { it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'}); @@ -1013,11 +1021,11 @@ runInEachFileSystem(() => { it('should be an empty array if decorator has no `args` property', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1027,11 +1035,11 @@ runInEachFileSystem(() => { it('should be an empty array if decorator\'s `args` has no property assignment', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1041,11 +1049,11 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1058,67 +1066,67 @@ runInEachFileSystem(() => { it('should find decorated members on a class at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const input1 = members.find(member => member.name === 'input1') !; + const input1 = members.find(member => member.name === 'input1')!; expect(input1.kind).toEqual(ClassMemberKind.Property); expect(input1.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); - expect(input1.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'}); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators![0].import).toEqual({name: 'Input', from: '@angular/core'}); - const input2 = members.find(member => member.name === 'input2') !; + const input2 = members.find(member => member.name === 'input2')!; expect(input2.kind).toEqual(ClassMemberKind.Property); expect(input2.isStatic).toEqual(false); - expect(input2.decorators !.map(d => d.name)).toEqual(['Input']); - expect(input2.decorators ![0].import).toEqual({name: 'Input', from: '@angular/core'}); + expect(input2.decorators!.map(d => d.name)).toEqual(['Input']); + expect(input2.decorators![0].import).toEqual({name: 'Input', from: '@angular/core'}); }); it('should find decorated members on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const input1 = members.find(member => member.name === 'input1') !; + const input1 = members.find(member => member.name === 'input1')!; expect(input1.kind).toEqual(ClassMemberKind.Property); expect(input1.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); - const input2 = members.find(member => member.name === 'input2') !; + const input2 = members.find(member => member.name === 'input2')!; expect(input2.kind).toEqual(ClassMemberKind.Property); expect(input2.isStatic).toEqual(false); - expect(input2.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input2.decorators!.map(d => d.name)).toEqual(['Input']); }); it('should find Object.defineProperty members on a class', () => { loadTestFiles([ACCESSORS_FILE]); const bundle = makeTestBundleProgram(ACCESSORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, ACCESSORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const setter = members.find(member => member.name === 'setter') !; + const setter = members.find(member => member.name === 'setter')!; expect(setter.kind).toEqual(ClassMemberKind.Setter); expect(setter.isStatic).toEqual(false); expect(setter.value).toBeNull(); - expect(setter.decorators !.map(d => d.name)).toEqual(['Input']); - expect(ts.isFunctionExpression(setter.implementation !)).toEqual(true); + expect(setter.decorators!.map(d => d.name)).toEqual(['Input']); + expect(ts.isFunctionExpression(setter.implementation!)).toEqual(true); expect((setter.implementation as ts.FunctionExpression).body.statements[0].getText()) .toEqual('this.value = value;'); - const getter = members.find(member => member.name === 'getter') !; + const getter = members.find(member => member.name === 'getter')!; expect(getter.kind).toEqual(ClassMemberKind.Getter); expect(getter.isStatic).toEqual(false); expect(getter.value).toBeNull(); - expect(getter.decorators !.map(d => d.name)).toEqual(['Output']); - expect(ts.isFunctionExpression(getter.implementation !)).toEqual(true); + expect(getter.decorators!.map(d => d.name)).toEqual(['Output']); + expect(ts.isFunctionExpression(getter.implementation!)).toEqual(true); expect((getter.implementation as ts.FunctionExpression).body.statements[0].getText()) .toEqual('return null;'); @@ -1126,16 +1134,16 @@ runInEachFileSystem(() => { members.filter(member => member.name === 'setterAndGetter'); expect(combinedSetter.kind).toEqual(ClassMemberKind.Setter); expect(combinedSetter.isStatic).toEqual(false); - expect(combinedSetter.decorators !.map(d => d.name)).toEqual(['Input']); + expect(combinedSetter.decorators!.map(d => d.name)).toEqual(['Input']); expect(combinedGetter.kind).toEqual(ClassMemberKind.Getter); expect(combinedGetter.isStatic).toEqual(false); - expect(combinedGetter.decorators !.map(d => d.name)).toEqual([]); + expect(combinedGetter.decorators!.map(d => d.name)).toEqual([]); - const staticSetter = members.find(member => member.name === 'staticSetter') !; + const staticSetter = members.find(member => member.name === 'staticSetter')!; expect(staticSetter.kind).toEqual(ClassMemberKind.Setter); expect(staticSetter.isStatic).toEqual(true); expect(staticSetter.value).toBeNull(); - expect(staticSetter.decorators !.map(d => d.name)).toEqual([]); + expect(staticSetter.decorators!.map(d => d.name)).toEqual([]); const none = members.find(member => member.name === 'none'); expect(none).toBeUndefined(); @@ -1147,56 +1155,56 @@ runInEachFileSystem(() => { it('should find non decorated properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const instanceProperty = members.find(member => member.name === 'instanceProperty') !; + const instanceProperty = members.find(member => member.name === 'instanceProperty')!; expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); expect(instanceProperty.isStatic).toEqual(false); - expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true); - expect(instanceProperty.value !.getText()).toEqual(`'instance'`); + expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true); + expect(instanceProperty.value!.getText()).toEqual(`'instance'`); }); it('should find static methods on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const staticMethod = members.find(member => member.name === 'staticMethod') !; + const staticMethod = members.find(member => member.name === 'staticMethod')!; expect(staticMethod.kind).toEqual(ClassMemberKind.Method); expect(staticMethod.isStatic).toEqual(true); expect(staticMethod.value).toBeNull(); - expect(ts.isFunctionExpression(staticMethod.implementation !)).toEqual(true); + expect(ts.isFunctionExpression(staticMethod.implementation!)).toEqual(true); }); it('should find static properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const staticProperty = members.find(member => member.name === 'staticProperty') !; + const staticProperty = members.find(member => member.name === 'staticProperty')!; expect(staticProperty.kind).toEqual(ClassMemberKind.Property); expect(staticProperty.isStatic).toEqual(true); - expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true); - expect(staticProperty.value !.getText()).toEqual(`'static'`); + expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true); + expect(staticProperty.value!.getText()).toEqual(`'static'`); }); it('should accept `ctorParameters` as an array', () => { loadTestFiles([CTOR_DECORATORS_ARRAY_FILE]); const bundle = makeTestBundleProgram(CTOR_DECORATORS_ARRAY_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, CTOR_DECORATORS_ARRAY_FILE.name, 'CtorDecoratedAsArray', isNamedVariableDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters).toBeDefined(); expect(parameters.map(parameter => parameter.name)).toEqual(['arg1']); @@ -1206,7 +1214,7 @@ runInEachFileSystem(() => { it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(() => { @@ -1217,7 +1225,7 @@ runInEachFileSystem(() => { it('should return an empty array if there are no prop decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); @@ -1229,7 +1237,7 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); @@ -1241,13 +1249,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements that are not object literals', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteralProp', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'})); @@ -1256,13 +1264,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements that have no `type` property', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'})); @@ -1271,13 +1279,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Input'})); @@ -1287,13 +1295,13 @@ runInEachFileSystem(() => { it('should be an empty array if prop decorator has no `args` property', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1304,13 +1312,14 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1320,13 +1329,13 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1338,7 +1347,7 @@ runInEachFileSystem(() => { () => { loadTestFiles([UNWANTED_PROTOTYPE_EXPORT_FILE]); const bundle = makeTestBundleProgram(UNWANTED_PROTOTYPE_EXPORT_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, UNWANTED_PROTOTYPE_EXPORT_FILE.name, 'SomeParam', isNamedClassDeclaration); @@ -1351,16 +1360,16 @@ runInEachFileSystem(() => { it('should find the decorated constructor parameters', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toBeDefined(); - expect(parameters !.map(parameter => parameter.name)).toEqual([ + expect(parameters!.map(parameter => parameter.name)).toEqual([ '_viewContainer', '_template', 'injected' ]); - expectTypeValueReferencesForParameters(parameters !, [ + expectTypeValueReferencesForParameters(parameters!, [ 'ViewContainerRef', 'TemplateRef', null, @@ -1370,17 +1379,17 @@ runInEachFileSystem(() => { it('should find the decorated constructor parameters at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toBeDefined(); - expect(parameters !.map(parameter => parameter.name)).toEqual([ + expect(parameters!.map(parameter => parameter.name)).toEqual([ '_viewContainer', '_template', 'injected' ]); - expectTypeValueReferencesForParameters(parameters !, [ + expectTypeValueReferencesForParameters(parameters!, [ 'ViewContainerRef', 'TemplateRef', null, @@ -1390,10 +1399,12 @@ runInEachFileSystem(() => { it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); - expect(() => { host.getConstructorParameters(functionNode); }) + expect(() => { + host.getConstructorParameters(functionNode); + }) .toThrowError( 'Attempted to get constructor parameters of a non-class: "function foo() {}"'); }); @@ -1404,22 +1415,22 @@ runInEachFileSystem(() => { it('should return an array even if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toEqual(jasmine.any(Array)); - expect(parameters !.length).toEqual(1); - expect(parameters ![0].name).toEqual('foo'); - expect(parameters ![0].decorators).toBe(null); + expect(parameters!.length).toEqual(1); + expect(parameters![0].name).toEqual('foo'); + expect(parameters![0].decorators).toBe(null); }); it('should return an empty array if there are no constructor parameters', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoParameters', isNamedVariableDeclaration); @@ -1434,14 +1445,14 @@ runInEachFileSystem(() => { it('should ignore `ctorParameters` if it does not return an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(1); - expect(parameters ![0]).toEqual(jasmine.objectContaining({ + expect(parameters!.length).toBe(1); + expect(parameters![0]).toEqual(jasmine.objectContaining({ name: 'arg1', decorators: null, })); @@ -1451,18 +1462,18 @@ runInEachFileSystem(() => { it('should ignore param decorator elements that are not object literals', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(2); - expect(parameters ![0]).toEqual(jasmine.objectContaining({ + expect(parameters!.length).toBe(2); + expect(parameters![0]).toEqual(jasmine.objectContaining({ name: 'arg1', decorators: null, })); - expect(parameters ![1]).toEqual(jasmine.objectContaining({ + expect(parameters![1]).toEqual(jasmine.objectContaining({ name: 'arg2', decorators: jasmine.any(Array) as any })); @@ -1471,12 +1482,12 @@ runInEachFileSystem(() => { it('should ignore param decorator elements that have no `type` property', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1485,12 +1496,12 @@ runInEachFileSystem(() => { it('should ignore param decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1499,12 +1510,12 @@ runInEachFileSystem(() => { it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![2].decorators !; + const decorators = parameters![2].decorators!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'}); @@ -1526,7 +1537,7 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); return host.getConstructorParameters(classNode); @@ -1570,7 +1581,7 @@ runInEachFileSystem(() => { return _super !== null && _super.apply(this, arguments) || this; }`); - expect(parameters !.length).toBe(1); + expect(parameters!.length).toBe(1); }); it('does not consider manual super calls as synthesized', () => { @@ -1579,7 +1590,7 @@ runInEachFileSystem(() => { return _super.call(this) || this; }`); - expect(parameters !.length).toBe(0); + expect(parameters!.length).toBe(0); }); it('does not consider empty constructors as synthesized', () => { @@ -1587,7 +1598,7 @@ runInEachFileSystem(() => { function TestClass() { }`); - expect(parameters !.length).toBe(0); + expect(parameters!.length).toBe(0); }); }); @@ -1595,13 +1606,13 @@ runInEachFileSystem(() => { it('should be an empty array if param decorator has no `args` property', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(1); - const decorators = parameters ![0].decorators !; + expect(parameters!.length).toBe(1); + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1612,12 +1623,13 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1627,12 +1639,12 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1646,45 +1658,45 @@ runInEachFileSystem(() => { () => { loadTestFiles([FUNCTION_BODY_FILE]); const bundle = makeTestBundleProgram(FUNCTION_BODY_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const fooNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration) !; - const fooDef = host.getDefinitionOfFunction(fooNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration)!; + const fooDef = host.getDefinitionOfFunction(fooNode)!; expect(fooDef.node).toBe(fooNode); - expect(fooDef.body !.length).toEqual(1); - expect(fooDef.body ![0].getText()).toEqual(`return x;`); + expect(fooDef.body!.length).toEqual(1); + expect(fooDef.body![0].getText()).toEqual(`return x;`); expect(fooDef.parameters.length).toEqual(1); expect(fooDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); const barNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration) !; - const barDef = host.getDefinitionOfFunction(barNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration)!; + const barDef = host.getDefinitionOfFunction(barNode)!; expect(barDef.node).toBe(barNode); - expect(barDef.body !.length).toEqual(1); - expect(ts.isReturnStatement(barDef.body ![0])).toBeTruthy(); - expect(barDef.body ![0].getText()).toEqual(`return x + y;`); + expect(barDef.body!.length).toEqual(1); + expect(ts.isReturnStatement(barDef.body![0])).toBeTruthy(); + expect(barDef.body![0].getText()).toEqual(`return x + y;`); expect(barDef.parameters.length).toEqual(2); expect(barDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); expect(barDef.parameters[1].name).toEqual('y'); - expect(barDef.parameters[1].initializer !.getText()).toEqual('42'); + expect(barDef.parameters[1].initializer!.getText()).toEqual('42'); const bazNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration) !; - const bazDef = host.getDefinitionOfFunction(bazNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration)!; + const bazDef = host.getDefinitionOfFunction(bazNode)!; expect(bazDef.node).toBe(bazNode); - expect(bazDef.body !.length).toEqual(3); + expect(bazDef.body!.length).toEqual(3); expect(bazDef.parameters.length).toEqual(1); expect(bazDef.parameters[0].name).toEqual('x'); expect(bazDef.parameters[0].initializer).toBe(null); const quxNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration) !; - const quxDef = host.getDefinitionOfFunction(quxNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration)!; + const quxDef = host.getDefinitionOfFunction(quxNode)!; expect(quxDef.node).toBe(quxNode); - expect(quxDef.body !.length).toEqual(2); + expect(quxDef.body!.length).toEqual(2); expect(quxDef.parameters.length).toEqual(1); expect(quxDef.parameters[0].name).toEqual('x'); expect(quxDef.parameters[0].initializer).toBe(null); @@ -1695,7 +1707,7 @@ runInEachFileSystem(() => { it('should find the import of an identifier', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/b.js'), 'b', isNamedVariableDeclaration); const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier); @@ -1706,7 +1718,7 @@ runInEachFileSystem(() => { it('should find the name by which the identifier was exported, not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/b.js'), 'c', isNamedVariableDeclaration); const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier); @@ -1717,7 +1729,7 @@ runInEachFileSystem(() => { it('should return null if the identifier was not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/b.js'), 'd', isNamedVariableDeclaration); const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier); @@ -1729,10 +1741,10 @@ runInEachFileSystem(() => { describe('getDeclarationOfIdentifier()', () => { // Helpers const createTestForTsHelper = - (program: ts.Program, host: Esm5ReflectionHost, srcFile: TestFile, + (program: ts.Program, host: NgccReflectionHost, srcFile: TestFile, getHelperDeclaration: (name: string) => ts.Declaration) => (varName: string, helperName: string, knownAs: KnownDeclaration, - viaModule: string | null = null) => { + viaModule: string|null = null) => { const node = getDeclaration(program, srcFile.name, varName, ts.isVariableDeclaration); const helperIdentifier = getIdentifierFromCallExpression(node); @@ -1740,7 +1752,8 @@ runInEachFileSystem(() => { expect(helperDeclaration).toEqual({ known: knownAs, - node: getHelperDeclaration(helperName), viaModule, + node: getHelperDeclaration(helperName), + viaModule, }); }; @@ -1756,11 +1769,11 @@ runInEachFileSystem(() => { it('should return the declaration of a locally defined identifier', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const ctrDecorators = host.getConstructorParameters(classNode) !; - const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference !as{ + const ctrDecorators = host.getConstructorParameters(classNode)!; + const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference! as { local: true, expression: ts.Identifier, defaultImportStatement: null, @@ -1771,51 +1784,53 @@ runInEachFileSystem(() => { isNamedVariableDeclaration); const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe(null); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe(null); }); it('should return the declaration of an externally defined identifier', () => { loadFakeCore(getFileSystem()); loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; - const identifierOfDirective = ((classDecorators[0].node as ts.ObjectLiteralExpression) - .properties[0] as ts.PropertyAssignment) - .initializer as ts.Identifier; + const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; + const identifierOfDirective = + ((classDecorators[0].node as ts.ObjectLiteralExpression).properties[0] as + ts.PropertyAssignment) + .initializer as ts.Identifier; const expectedDeclarationNode = getDeclaration( bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive', isNamedVariableDeclaration); const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe('@angular/core'); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe('@angular/core'); }); it('should return the source-file of an import namespace', () => { loadFakeCore(getFileSystem()); loadTestFiles([NAMESPACED_IMPORT_FILE]); const bundle = makeTestBundleProgram(NAMESPACED_IMPORT_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, NAMESPACED_IMPORT_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; - const identifier = (((classDecorators[0].node as ts.ObjectLiteralExpression) - .properties[0] as ts.PropertyAssignment) - .initializer as ts.PropertyAccessExpression) - .expression as ts.Identifier; + const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; + const identifier = + (((classDecorators[0].node as ts.ObjectLiteralExpression).properties[0] as + ts.PropertyAssignment) + .initializer as ts.PropertyAccessExpression) + .expression as ts.Identifier; const expectedDeclarationNode = getSourceFileOrError(bundle.program, _('/node_modules/@angular/core/index.d.ts')); const actualDeclaration = host.getDeclarationOfIdentifier(identifier); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe('@angular/core'); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe('@angular/core'); }); it('should return the correct declaration for an inner function identifier inside an ES5 IIFE', @@ -1825,25 +1840,26 @@ runInEachFileSystem(() => { .and.callThrough(); loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const outerDeclaration = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerDeclaration = (((outerDeclaration.initializer as ts.ParenthesizedExpression) - .expression as ts.CallExpression) - .expression as ts.FunctionExpression) - .body.statements[0] as ts.FunctionDeclaration; + const innerDeclaration = + (((outerDeclaration.initializer as ts.ParenthesizedExpression).expression as + ts.CallExpression) + .expression as ts.FunctionExpression) + .body.statements[0] as ts.FunctionDeclaration; const outerIdentifier = outerDeclaration.name as ts.Identifier; const innerIdentifier = innerDeclaration.name as ts.Identifier; - expect(host.getDeclarationOfIdentifier(outerIdentifier) !.node).toBe(outerDeclaration); + expect(host.getDeclarationOfIdentifier(outerIdentifier)!.node).toBe(outerDeclaration); expect(superGetDeclarationOfIdentifierSpy).toHaveBeenCalledWith(outerIdentifier); expect(superGetDeclarationOfIdentifierSpy).toHaveBeenCalledTimes(1); superGetDeclarationOfIdentifierSpy.calls.reset(); - expect(host.getDeclarationOfIdentifier(innerIdentifier) !.node).toBe(outerDeclaration); + expect(host.getDeclarationOfIdentifier(innerIdentifier)!.node).toBe(outerDeclaration); expect(superGetDeclarationOfIdentifierSpy).toHaveBeenCalledWith(innerIdentifier); expect(superGetDeclarationOfIdentifierSpy).toHaveBeenCalledWith(outerIdentifier); expect(superGetDeclarationOfIdentifierSpy).toHaveBeenCalledTimes(2); @@ -1864,17 +1880,17 @@ runInEachFileSystem(() => { loadTestFiles([PROGRAM_FILE]); const bundle = makeTestBundleProgram(PROGRAM_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const expectedDeclaration = getDeclaration( bundle.program, PROGRAM_FILE.name, 'AliasedClass', isNamedVariableDeclaration); // Grab the `AliasedClass_1` identifier (which is an alias for `AliasedClass`). const aliasIdentifier = (expectedDeclaration.initializer as ts.BinaryExpression).left as ts.Identifier; - const actualDeclaration = host.getDeclarationOfIdentifier(aliasIdentifier) !; + const actualDeclaration = host.getDeclarationOfIdentifier(aliasIdentifier)!; expect(aliasIdentifier.getText()).toBe('AliasedClass_1'); - expect(actualDeclaration.node !.getText()).toBe(expectedDeclaration.getText()); + expect(actualDeclaration.node!.getText()).toBe(expectedDeclaration.getText()); }); it('should return the correct outer declaration for an aliased inner class declaration inside an ES5 IIFE', @@ -1907,23 +1923,24 @@ runInEachFileSystem(() => { loadTestFiles([PROGRAM_FILE]); const bundle = makeTestBundleProgram(PROGRAM_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const expectedDeclaration = getDeclaration( bundle.program, PROGRAM_FILE.name, 'FroalaEditorModule', isNamedVariableDeclaration); // Grab the `FroalaEditorModule_1` identifier returned from the `forRoot()` method - const forRootMethod = ((((expectedDeclaration.initializer as ts.ParenthesizedExpression) - .expression as ts.CallExpression) - .expression as ts.FunctionExpression) - .body.statements[2] as ts.ExpressionStatement); + const forRootMethod = + ((((expectedDeclaration.initializer as ts.ParenthesizedExpression).expression as + ts.CallExpression) + .expression as ts.FunctionExpression) + .body.statements[2] as ts.ExpressionStatement); const identifier = (((((forRootMethod.expression as ts.BinaryExpression).right as ts.FunctionExpression) .body.statements[0] as ts.ReturnStatement) .expression as ts.ObjectLiteralExpression) .properties[0] as ts.PropertyAssignment) .initializer as ts.Identifier; - const actualDeclaration = host.getDeclarationOfIdentifier(identifier) !; - expect(actualDeclaration.node !.getText()).toBe(expectedDeclaration.getText()); + const actualDeclaration = host.getDeclarationOfIdentifier(identifier)!; + expect(actualDeclaration.node!.getText()).toBe(expectedDeclaration.getText()); }); it('should recognize TypeScript helpers (as function declarations)', () => { @@ -1941,7 +1958,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -1968,7 +1985,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -1995,7 +2012,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -2022,7 +2039,7 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, file, @@ -2059,7 +2076,7 @@ runInEachFileSystem(() => { const [testFile, tslibFile] = files; const bundle = makeTestBundleProgram(testFile.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, testFile, @@ -2096,7 +2113,7 @@ runInEachFileSystem(() => { const [testFile, tslibFile] = files; const bundle = makeTestBundleProgram(testFile.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const testForHelper = createTestForTsHelper( bundle.program, host, testFile, @@ -2114,11 +2131,11 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/b.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.keys())).toEqual([ + expect(Array.from(exportDeclarations!.keys())).toEqual([ 'Directive', 'a', 'b', @@ -2130,8 +2147,8 @@ runInEachFileSystem(() => { ]); const values = - Array.from(exportDeclarations !.values()) - .map(declaration => [declaration.node !.getText(), declaration.viaModule]); + Array.from(exportDeclarations!.values()) + .map(declaration => [declaration.node!.getText(), declaration.viaModule]); expect(values).toEqual([ [`Directive: FnWithArg<(clazz: any) => any>`, null], [`a = 'a'`, null], @@ -2162,9 +2179,9 @@ runInEachFileSystem(() => { }; loadTestFiles([tslib]); const bundle = makeTestBundleProgram(tslib.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const sf = getSourceFileOrError(bundle.program, tslib.name); - const exportDeclarations = host.getExportsOfModule(sf) !; + const exportDeclarations = host.getExportsOfModule(sf)!; expect([...exportDeclarations].map(([exportName, {known}]) => [exportName, known])) .toEqual([ @@ -2180,55 +2197,55 @@ runInEachFileSystem(() => { it('should return the class symbol for an ES2015 class', () => { loadTestFiles([SIMPLE_ES2015_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_ES2015_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_ES2015_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); const classSymbol = host.getClassSymbol(node); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(node); - expect(classSymbol !.implementation.valueDeclaration).toBe(node); + expect(classSymbol!.declaration.valueDeclaration).toBe(node); + expect(classSymbol!.implementation.valueDeclaration).toBe(node); }); it('should return the class symbol for an ES5 class (outer variable declaration)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the class symbol for an ES5 class (inner function declaration)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(innerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the same class symbol (of the outer declaration) for outer and inner declarations', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; - const innerSymbol = host.getClassSymbol(innerNode) !; - const outerSymbol = host.getClassSymbol(outerNode) !; + const innerSymbol = host.getClassSymbol(innerNode)!; + const outerSymbol = host.getClassSymbol(outerNode)!; expect(innerSymbol.declaration).toBe(outerSymbol.declaration); expect(innerSymbol.implementation).toBe(outerSymbol.implementation); }); @@ -2237,37 +2254,37 @@ runInEachFileSystem(() => { () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'NoParensClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the class symbol for an ES5 class whose IIFE is not wrapped with inner parens', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'InnerParensClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return undefined if node is not an ES5 class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const classSymbol = host.getClassSymbol(node); @@ -2282,7 +2299,7 @@ runInEachFileSystem(() => { }; loadTestFiles([testFile]); const bundle = makeTestBundleProgram(testFile.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration(bundle.program, testFile.name, 'MyClass', isNamedVariableDeclaration); const classSymbol = host.getClassSymbol(node); @@ -2295,7 +2312,7 @@ runInEachFileSystem(() => { it('should return true if a given node is a TS class declaration', () => { loadTestFiles([SIMPLE_ES2015_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_ES2015_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_ES2015_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); expect(host.isClass(node)).toBe(true); @@ -2304,7 +2321,7 @@ runInEachFileSystem(() => { it('should return true if a given node is the outer variable declaration of a class', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration); expect(host.isClass(node)).toBe(true); @@ -2313,17 +2330,17 @@ runInEachFileSystem(() => { it('should return true if a given node is the inner variable declaration of a class', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; expect(host.isClass(innerNode)).toBe(true); }); it('should return false if a given node is a function declaration', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(host.isClass(node)).toBe(false); @@ -2339,7 +2356,7 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); return host.hasBaseClass(classNode); @@ -2386,7 +2403,7 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); const expression = host.getBaseClassExpression(classNode); @@ -2408,7 +2425,7 @@ runInEachFileSystem(() => { function TestClass() {} return TestClass; }(BaseClass));`); - expect(identifier !.text).toBe('BaseClass'); + expect(identifier!.text).toBe('BaseClass'); }); it('should find the base class of an IIFE with a unique name generated for the _super parameter', @@ -2423,7 +2440,7 @@ runInEachFileSystem(() => { function TestClass() {} return TestClass; }(BaseClass));`); - expect(identifier !.text).toBe('BaseClass'); + expect(identifier!.text).toBe('BaseClass'); }); it('should not find a base class for an IIFE without parameter', () => { @@ -2458,10 +2475,10 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); - const expression = host.getBaseClassExpression(classNode) !; + const expression = host.getBaseClassExpression(classNode)!; expect(expression.getText()).toBe('foo()'); }); }); @@ -2470,7 +2487,7 @@ runInEachFileSystem(() => { it('should return an array of all classes in the given source file', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(getRootFiles(DECORATED_FILES)[0]); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); @@ -2488,21 +2505,21 @@ runInEachFileSystem(() => { it('should return decorators of class symbol', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(getRootFiles(DECORATED_FILES)[0]); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); const classSymbolsPrimary = host.findClassSymbols(primaryFile); const classDecoratorsPrimary = classSymbolsPrimary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsPrimary.length).toEqual(2); - expect(classDecoratorsPrimary[0] !.map(d => d.name)).toEqual(['Directive']); - expect(classDecoratorsPrimary[1] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[0]!.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[1]!.map(d => d.name)).toEqual(['Directive']); const classSymbolsSecondary = host.findClassSymbols(secondaryFile); const classDecoratorsSecondary = classSymbolsSecondary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsSecondary.length).toEqual(1); - expect(classDecoratorsSecondary[0] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsSecondary[0]!.map(d => d.name)).toEqual(['Directive']); }); }); @@ -2515,10 +2532,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/class1.js'), 'Class1', ts.isVariableDeclaration); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find the dts declaration for exported functions', () => { @@ -2528,10 +2546,11 @@ runInEachFileSystem(() => { const dts = makeTestDtsBundleProgram(_('/ep/typings/func1.d.ts'), _('/')); const mooFn = getDeclaration( bundle.program, _('/ep/src/func1.js'), 'mooFn', ts.isFunctionDeclaration); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(mooFn); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); }); it('should return null if there is no matching class in the matching dts file', () => { @@ -2541,7 +2560,8 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const missingClass = getDeclaration( bundle.program, _('/ep/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2554,7 +2574,8 @@ runInEachFileSystem(() => { const missingClass = getDeclaration( bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2', ts.isVariableDeclaration); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2567,10 +2588,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find aliased exports', () => { @@ -2580,7 +2602,8 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const sourceClass = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', ts.isVariableDeclaration); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(sourceClass); if (dtsDeclaration === null) { @@ -2602,11 +2625,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const internalClass = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'InternalClass', ts.isVariableDeclaration); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(internalClass); - expect(dtsDeclaration !.getSourceFile().fileName) - .toEqual(_('/ep/typings/internal.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/internal.d.ts')); }); it('should match publicly and internal exported classes correctly, even if they have the same name', @@ -2615,18 +2638,19 @@ runInEachFileSystem(() => { loadTestFiles(TYPINGS_DTS_FILES); const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]); const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle, dts)); const class2 = getDeclaration( bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedVariableDeclaration); const class2DtsDeclaration = host.getDtsDeclaration(class2); - expect(class2DtsDeclaration !.getSourceFile().fileName) + expect(class2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/class2.d.ts')); const internalClass2 = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedVariableDeclaration); const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2); - expect(internalClass2DtsDeclaration !.getSourceFile().fileName) + expect(internalClass2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/internal.d.ts')); }); }); @@ -2635,7 +2659,7 @@ runInEachFileSystem(() => { it('should return the name of the inner class declaration', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const emptyClass = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); @@ -2659,7 +2683,7 @@ runInEachFileSystem(() => { it('should return the name of the inner class declaration', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const emptyClass = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); @@ -2684,10 +2708,10 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/functions.js')); const fns = host.getModuleWithProvidersFunctions(file); - expect(fns.map(fn => [fn.declaration.name !.getText(), fn.ngModule.node.name.text])) + expect(fns.map(fn => [fn.declaration.name!.getText(), fn.ngModule.node.name.text])) .toEqual([ ['ngModuleIdentifier', 'InternalModule'], ['ngModuleWithEmptyProviders', 'InternalModule'], @@ -2701,7 +2725,7 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/methods.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ @@ -2732,7 +2756,7 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/outer_aliased_class.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ @@ -2745,7 +2769,7 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(_('/src/index.js')); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/inner_aliased_class.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ @@ -2758,9 +2782,9 @@ runInEachFileSystem(() => { it('should return the last static property of the class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new Esm5ReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new Esm5ReflectionHost(new MockLogger(), false, bundle)); const classSymbol = - host.findClassSymbols(bundle.program.getSourceFile(SOME_DIRECTIVE_FILE.name) !)[0]; + host.findClassSymbols(bundle.program.getSourceFile(SOME_DIRECTIVE_FILE.name)!)[0]; const endOfClass = host.getEndOfClass(classSymbol); expect(endOfClass.getText()).toEqual(`SomeDirective.propDecorators = { "input1": [{ type: Input },], diff --git a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts index 6a549b65eb..89319ab05f 100644 --- a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts @@ -9,12 +9,15 @@ import * as ts from 'typescript'; import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system'; -import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing'; -import {ClassMemberKind, CtorParameter, Import, InlineDeclaration, KnownDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection'; +import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing'; +import {ClassMemberKind, CtorParameter, Import, InlineDeclaration, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration, KnownDeclaration, TypeScriptReflectionHost} from '../../../src/ngtsc/reflection'; import {getDeclaration} from '../../../src/ngtsc/testing'; import {loadFakeCore, loadTestFiles} from '../../../test/helpers'; +import {DelegatingReflectionHost} from '../../src/host/delegating_host'; import {getIifeBody} from '../../src/host/esm5_host'; -import {UmdReflectionHost, parseStatementForUmdModule} from '../../src/host/umd_host'; +import {NgccReflectionHost} from '../../src/host/ngcc_host'; +import {parseStatementForUmdModule, UmdReflectionHost} from '../../src/host/umd_host'; +import {BundleProgram} from '../../src/packages/bundle_program'; import {MockLogger} from '../helpers/mock_logger'; import {getRootFiles, makeTestBundleProgram} from '../helpers/utils'; @@ -45,6 +48,12 @@ runInEachFileSystem(() => { let TYPINGS_DTS_FILES: TestFile[]; let MODULE_WITH_PROVIDERS_PROGRAM: TestFile[]; + // Helpers + const createHost = (bundle: BundleProgram, ngccHost: UmdReflectionHost) => { + const tsHost = new TypeScriptReflectionHost(bundle.program.getTypeChecker()); + return new DelegatingReflectionHost(tsHost, ngccHost); + }; + beforeEach(() => { _ = absoluteFrom; @@ -1084,10 +1093,10 @@ runInEachFileSystem(() => { it('should find the decorators on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -1095,7 +1104,7 @@ runInEachFileSystem(() => { const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -1103,11 +1112,11 @@ runInEachFileSystem(() => { it('should find the decorators on a class at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators).toBeDefined(); expect(decorators.length).toEqual(1); @@ -1115,7 +1124,7 @@ runInEachFileSystem(() => { const decorator = decorators[0]; expect(decorator.name).toEqual('Directive'); expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'}); - expect(decorator.args !.map(arg => arg.getText())).toEqual([ + expect(decorator.args!.map(arg => arg.getText())).toEqual([ '{ selector: \'[someDirective]\' }', ]); }); @@ -1123,7 +1132,7 @@ runInEachFileSystem(() => { it('should return null if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const decorators = host.getDecoratorsOfDeclaration(functionNode); @@ -1133,7 +1142,7 @@ runInEachFileSystem(() => { it('should return null if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const decorators = host.getDecoratorsOfDeclaration(classNode); @@ -1143,7 +1152,7 @@ runInEachFileSystem(() => { it('should ignore `decorators` if it is not an array literal', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); @@ -1154,11 +1163,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements that are not object literals', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1167,11 +1176,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements that have no `type` property', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1180,11 +1189,11 @@ runInEachFileSystem(() => { it('should ignore decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1193,11 +1202,11 @@ runInEachFileSystem(() => { it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'}); @@ -1206,32 +1215,32 @@ runInEachFileSystem(() => { it('should find decorated members on a class at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const input1 = members.find(member => member.name === 'input1') !; + const input1 = members.find(member => member.name === 'input1')!; expect(input1.kind).toEqual(ClassMemberKind.Property); expect(input1.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); - const input2 = members.find(member => member.name === 'input2') !; + const input2 = members.find(member => member.name === 'input2')!; expect(input2.kind).toEqual(ClassMemberKind.Property); expect(input2.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); }); describe('(returned decorators `args`)', () => { it('should be an empty array if decorator has no `args` property', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1241,11 +1250,11 @@ runInEachFileSystem(() => { it('should be an empty array if decorator\'s `args` has no property assignment', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1255,11 +1264,11 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Directive'); @@ -1272,70 +1281,70 @@ runInEachFileSystem(() => { it('should find decorated members on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const input1 = members.find(member => member.name === 'input1') !; + const input1 = members.find(member => member.name === 'input1')!; expect(input1.kind).toEqual(ClassMemberKind.Property); expect(input1.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); - const input2 = members.find(member => member.name === 'input2') !; + const input2 = members.find(member => member.name === 'input2')!; expect(input2.kind).toEqual(ClassMemberKind.Property); expect(input2.isStatic).toEqual(false); - expect(input1.decorators !.map(d => d.name)).toEqual(['Input']); + expect(input1.decorators!.map(d => d.name)).toEqual(['Input']); }); it('should find non decorated properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const instanceProperty = members.find(member => member.name === 'instanceProperty') !; + const instanceProperty = members.find(member => member.name === 'instanceProperty')!; expect(instanceProperty.kind).toEqual(ClassMemberKind.Property); expect(instanceProperty.isStatic).toEqual(false); - expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true); - expect(instanceProperty.value !.getText()).toEqual(`'instance'`); + expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true); + expect(instanceProperty.value!.getText()).toEqual(`'instance'`); }); it('should find static methods on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const staticMethod = members.find(member => member.name === 'staticMethod') !; + const staticMethod = members.find(member => member.name === 'staticMethod')!; expect(staticMethod.kind).toEqual(ClassMemberKind.Method); expect(staticMethod.isStatic).toEqual(true); - expect(ts.isFunctionExpression(staticMethod.implementation !)).toEqual(true); + expect(ts.isFunctionExpression(staticMethod.implementation!)).toEqual(true); }); it('should find static properties on a class', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const staticProperty = members.find(member => member.name === 'staticProperty') !; + const staticProperty = members.find(member => member.name === 'staticProperty')!; expect(staticProperty.kind).toEqual(ClassMemberKind.Property); expect(staticProperty.isStatic).toEqual(true); - expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true); - expect(staticProperty.value !.getText()).toEqual(`'static'`); + expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true); + expect(staticProperty.value!.getText()).toEqual(`'static'`); }); it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(() => { @@ -1346,7 +1355,7 @@ runInEachFileSystem(() => { it('should return an empty array if there are no prop decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); @@ -1358,7 +1367,7 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); @@ -1370,13 +1379,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements that are not object literals', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotObjectLiteralProp', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1385,13 +1394,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements that have no `type` property', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1401,13 +1410,13 @@ runInEachFileSystem(() => { it('should ignore prop decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_PROP_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Directive'})); @@ -1416,11 +1425,11 @@ runInEachFileSystem(() => { it('should have import information on decorators', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const decorators = host.getDecoratorsOfDeclaration(classNode) !; + const decorators = host.getDecoratorsOfDeclaration(classNode)!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toEqual({name: 'Directive', from: '@angular/core'}); @@ -1430,13 +1439,13 @@ runInEachFileSystem(() => { it('should be an empty array if prop decorator has no `args` property', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1446,13 +1455,13 @@ runInEachFileSystem(() => { it('should be an empty array if prop decorator\'s `args` has no property assignment', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1462,13 +1471,13 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_PROP_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_PROP_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_PROP_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const members = host.getMembersOfClass(classNode); - const prop = members.find(m => m.name === 'prop') !; - const decorators = prop.decorators !; + const prop = members.find(m => m.name === 'prop')!; + const decorators = prop.decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Input'); @@ -1480,16 +1489,16 @@ runInEachFileSystem(() => { it('should find the decorated constructor parameters', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toBeDefined(); - expect(parameters !.map(parameter => parameter.name)).toEqual([ + expect(parameters!.map(parameter => parameter.name)).toEqual([ '_viewContainer', '_template', 'injected' ]); - expectTypeValueReferencesForParameters(parameters !, [ + expectTypeValueReferencesForParameters(parameters!, [ 'ViewContainerRef', 'TemplateRef', null, @@ -1499,17 +1508,17 @@ runInEachFileSystem(() => { it('should find the decorated constructor parameters at the top level', () => { loadTestFiles([TOPLEVEL_DECORATORS_FILE]); const bundle = makeTestBundleProgram(TOPLEVEL_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toBeDefined(); - expect(parameters !.map(parameter => parameter.name)).toEqual([ + expect(parameters!.map(parameter => parameter.name)).toEqual([ '_viewContainer', '_template', 'injected' ]); - expectTypeValueReferencesForParameters(parameters !, [ + expectTypeValueReferencesForParameters(parameters!, [ 'ViewContainerRef', 'TemplateRef', null, @@ -1519,11 +1528,11 @@ runInEachFileSystem(() => { it('should accept `ctorParameters` as an array', () => { loadTestFiles([CTOR_DECORATORS_ARRAY_FILE]); const bundle = makeTestBundleProgram(CTOR_DECORATORS_ARRAY_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, CTOR_DECORATORS_ARRAY_FILE.name, 'CtorDecoratedAsArray', isNamedVariableDeclaration); - const parameters = host.getConstructorParameters(classNode) !; + const parameters = host.getConstructorParameters(classNode)!; expect(parameters).toBeDefined(); expect(parameters.map(parameter => parameter.name)).toEqual(['arg1']); @@ -1533,10 +1542,12 @@ runInEachFileSystem(() => { it('should throw if the symbol is not a class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const functionNode = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); - expect(() => { host.getConstructorParameters(functionNode); }) + expect(() => { + host.getConstructorParameters(functionNode); + }) .toThrowError( 'Attempted to get constructor parameters of a non-class: "function foo() {}"'); }); @@ -1547,22 +1558,22 @@ runInEachFileSystem(() => { it('should return an array even if there are no decorators', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'NoDecoratorConstructorClass', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); expect(parameters).toEqual(jasmine.any(Array)); - expect(parameters !.length).toEqual(1); - expect(parameters ![0].name).toEqual('foo'); - expect(parameters ![0].decorators).toBe(null); + expect(parameters!.length).toEqual(1); + expect(parameters![0].name).toEqual('foo'); + expect(parameters![0].decorators).toBe(null); }); it('should return an empty array if there are no constructor parameters', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoParameters', isNamedVariableDeclaration); @@ -1577,14 +1588,14 @@ runInEachFileSystem(() => { it('should ignore `ctorParameters` if it does not return an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(1); - expect(parameters ![0]).toEqual(jasmine.objectContaining({ + expect(parameters!.length).toBe(1); + expect(parameters![0]).toEqual(jasmine.objectContaining({ name: 'arg1', decorators: null, })); @@ -1594,18 +1605,18 @@ runInEachFileSystem(() => { it('should ignore param decorator elements that are not object literals', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotObjectLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(2); - expect(parameters ![0]).toEqual(jasmine.objectContaining({ + expect(parameters!.length).toBe(2); + expect(parameters![0]).toEqual(jasmine.objectContaining({ name: 'arg1', decorators: null, })); - expect(parameters ![1]).toEqual(jasmine.objectContaining({ + expect(parameters![1]).toEqual(jasmine.objectContaining({ name: 'arg2', decorators: jasmine.any(Array) as any })); @@ -1614,12 +1625,12 @@ runInEachFileSystem(() => { it('should ignore param decorator elements that have no `type` property', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NoTypeProperty', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1628,12 +1639,12 @@ runInEachFileSystem(() => { it('should ignore param decorator elements whose `type` value is not an identifier', () => { loadTestFiles([INVALID_CTOR_DECORATORS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATORS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATORS_FILE.name, 'NotIdentifier', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0]).toEqual(jasmine.objectContaining({name: 'Inject'})); @@ -1642,7 +1653,7 @@ runInEachFileSystem(() => { it('should use `getImportOfIdentifier()` to retrieve import info', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); @@ -1651,7 +1662,7 @@ runInEachFileSystem(() => { .and.returnValue(mockImportInfo); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![2].decorators !; + const decorators = parameters![2].decorators!; expect(decorators.length).toEqual(1); expect(decorators[0].import).toBe(mockImportInfo); @@ -1662,13 +1673,13 @@ runInEachFileSystem(() => { it('should be an empty array if param decorator has no `args` property', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoArgsProperty', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - expect(parameters !.length).toBe(1); - const decorators = parameters ![0].decorators !; + expect(parameters!.length).toBe(1); + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1679,12 +1690,13 @@ runInEachFileSystem(() => { () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NoPropertyAssignment', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1694,12 +1706,12 @@ runInEachFileSystem(() => { it('should be an empty array if `args` property value is not an array literal', () => { loadTestFiles([INVALID_CTOR_DECORATOR_ARGS_FILE]); const bundle = makeTestBundleProgram(INVALID_CTOR_DECORATOR_ARGS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, INVALID_CTOR_DECORATOR_ARGS_FILE.name, 'NotArrayLiteral', isNamedVariableDeclaration); const parameters = host.getConstructorParameters(classNode); - const decorators = parameters ![0].decorators !; + const decorators = parameters![0].decorators!; expect(decorators.length).toBe(1); expect(decorators[0].name).toBe('Inject'); @@ -1713,45 +1725,45 @@ runInEachFileSystem(() => { () => { loadTestFiles([FUNCTION_BODY_FILE]); const bundle = makeTestBundleProgram(FUNCTION_BODY_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const fooNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration) !; - const fooDef = host.getDefinitionOfFunction(fooNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'foo', isNamedFunctionDeclaration)!; + const fooDef = host.getDefinitionOfFunction(fooNode)!; expect(fooDef.node).toBe(fooNode); - expect(fooDef.body !.length).toEqual(1); - expect(fooDef.body ![0].getText()).toEqual(`return x;`); + expect(fooDef.body!.length).toEqual(1); + expect(fooDef.body![0].getText()).toEqual(`return x;`); expect(fooDef.parameters.length).toEqual(1); expect(fooDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); const barNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration) !; - const barDef = host.getDefinitionOfFunction(barNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'bar', isNamedFunctionDeclaration)!; + const barDef = host.getDefinitionOfFunction(barNode)!; expect(barDef.node).toBe(barNode); - expect(barDef.body !.length).toEqual(1); - expect(ts.isReturnStatement(barDef.body ![0])).toBeTruthy(); - expect(barDef.body ![0].getText()).toEqual(`return x + y;`); + expect(barDef.body!.length).toEqual(1); + expect(ts.isReturnStatement(barDef.body![0])).toBeTruthy(); + expect(barDef.body![0].getText()).toEqual(`return x + y;`); expect(barDef.parameters.length).toEqual(2); expect(barDef.parameters[0].name).toEqual('x'); expect(fooDef.parameters[0].initializer).toBe(null); expect(barDef.parameters[1].name).toEqual('y'); - expect(barDef.parameters[1].initializer !.getText()).toEqual('42'); + expect(barDef.parameters[1].initializer!.getText()).toEqual('42'); const bazNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration) !; - const bazDef = host.getDefinitionOfFunction(bazNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'baz', isNamedFunctionDeclaration)!; + const bazDef = host.getDefinitionOfFunction(bazNode)!; expect(bazDef.node).toBe(bazNode); - expect(bazDef.body !.length).toEqual(3); + expect(bazDef.body!.length).toEqual(3); expect(bazDef.parameters.length).toEqual(1); expect(bazDef.parameters[0].name).toEqual('x'); expect(bazDef.parameters[0].initializer).toBe(null); const quxNode = getDeclaration( - bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration) !; - const quxDef = host.getDefinitionOfFunction(quxNode) !; + bundle.program, FUNCTION_BODY_FILE.name, 'qux', isNamedFunctionDeclaration)!; + const quxDef = host.getDefinitionOfFunction(quxNode)!; expect(quxDef.node).toBe(quxNode); - expect(quxDef.body !.length).toEqual(2); + expect(quxDef.body!.length).toEqual(2); expect(quxDef.parameters.length).toEqual(1); expect(quxDef.parameters[0].name).toEqual('x'); expect(quxDef.parameters[0].initializer).toBe(null); @@ -1762,7 +1774,7 @@ runInEachFileSystem(() => { it('should find the import of an identifier', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/file_b.js'), 'b', isNamedVariableDeclaration); const identifier = @@ -1772,14 +1784,14 @@ runInEachFileSystem(() => { null; expect(identifier).not.toBe(null); - const importOfIdent = host.getImportOfIdentifier(identifier !); + const importOfIdent = host.getImportOfIdentifier(identifier!); expect(importOfIdent).toEqual({name: 'a', from: './file_a'}); }); it('should return null if the identifier was not imported', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/file_b.js'), 'd', isNamedVariableDeclaration); const importOfIdent = host.getImportOfIdentifier(variableNode.initializer as ts.Identifier); @@ -1790,7 +1802,7 @@ runInEachFileSystem(() => { it('should handle factory functions not wrapped in parentheses', () => { loadTestFiles(IMPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const variableNode = getDeclaration(bundle.program, _('/file_c.js'), 'c', isNamedVariableDeclaration); const identifier = @@ -1800,7 +1812,7 @@ runInEachFileSystem(() => { null; expect(identifier).not.toBe(null); - const importOfIdent = host.getImportOfIdentifier(identifier !); + const importOfIdent = host.getImportOfIdentifier(identifier!); expect(importOfIdent).toEqual({name: 'a', from: './file_a'}); }); }); @@ -1808,24 +1820,25 @@ runInEachFileSystem(() => { describe('getDeclarationOfIdentifier', () => { // Helpers const createTestForTsHelper = - (host: UmdReflectionHost, factoryFn: ts.FunctionExpression, + (host: NgccReflectionHost, factoryFn: ts.FunctionExpression, getHelperDeclaration: (factoryFn: ts.FunctionExpression, name: string) => ts.Declaration) => (varName: string, helperName: string, knownAs: KnownDeclaration, - viaModule: string | null = null) => { + viaModule: string|null = null) => { const node = getVariableDeclaration(factoryFn, varName); const helperIdentifier = getIdentifierFromCallExpression(node); const helperDeclaration = host.getDeclarationOfIdentifier(helperIdentifier); expect(helperDeclaration).toEqual({ known: knownAs, - node: getHelperDeclaration(factoryFn, helperName), viaModule, + node: getHelperDeclaration(factoryFn, helperName), + viaModule, }); }; const getFunctionDeclaration = (factoryFn: ts.FunctionExpression, name: string) => factoryFn.body.statements.filter(ts.isFunctionDeclaration) - .find(decl => (decl.name !== undefined) && (decl.name.text === name)) !; + .find(decl => (decl.name !== undefined) && (decl.name.text === name))!; const getIdentifierFromCallExpression = (decl: ts.VariableDeclaration) => { if (decl.initializer !== undefined && ts.isCallExpression(decl.initializer)) { @@ -1839,16 +1852,16 @@ runInEachFileSystem(() => { const getVariableDeclaration = (factoryFn: ts.FunctionExpression, name: string) => factoryFn.body.statements.filter(ts.isVariableStatement) .map(stmt => stmt.declarationList.declarations[0]) - .find(decl => ts.isIdentifier(decl.name) && (decl.name.text === name)) !; + .find(decl => ts.isIdentifier(decl.name) && (decl.name.text === name))!; it('should return the declaration of a locally defined identifier', () => { loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const ctrDecorators = host.getConstructorParameters(classNode) !; - const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference !as{ + const ctrDecorators = host.getConstructorParameters(classNode)!; + const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference! as { local: true, expression: ts.Identifier, defaultImportStatement: null, @@ -1859,8 +1872,8 @@ runInEachFileSystem(() => { isNamedVariableDeclaration); const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe(null); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe(null); }); it('should return the correct declaration for an outer alias identifier', () => { @@ -1884,7 +1897,7 @@ runInEachFileSystem(() => { loadTestFiles([PROGRAM_FILE]); const bundle = makeTestBundleProgram(PROGRAM_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const expectedDeclaration = getDeclaration( bundle.program, PROGRAM_FILE.name, 'AliasedClass', isNamedVariableDeclaration); @@ -1895,28 +1908,29 @@ runInEachFileSystem(() => { expect(aliasIdentifier.getText()).toBe('AliasedClass_1'); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclaration); + expect(actualDeclaration!.node).toBe(expectedDeclaration); }); it('should return the source-file of an import namespace', () => { loadFakeCore(getFileSystem()); loadTestFiles([SOME_DIRECTIVE_FILE]); const bundle = makeTestBundleProgram(SOME_DIRECTIVE_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration( bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration); - const classDecorators = host.getDecoratorsOfDeclaration(classNode) !; - const identifierOfDirective = (((classDecorators[0].node as ts.ObjectLiteralExpression) - .properties[0] as ts.PropertyAssignment) - .initializer as ts.PropertyAccessExpression) - .expression as ts.Identifier; + const classDecorators = host.getDecoratorsOfDeclaration(classNode)!; + const identifierOfDirective = + (((classDecorators[0].node as ts.ObjectLiteralExpression).properties[0] as + ts.PropertyAssignment) + .initializer as ts.PropertyAccessExpression) + .expression as ts.Identifier; const expectedDeclarationNode = getSourceFileOrError(bundle.program, _('/node_modules/@angular/core/index.d.ts')); const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective); expect(actualDeclaration).not.toBe(null); - expect(actualDeclaration !.node).toBe(expectedDeclarationNode); - expect(actualDeclaration !.viaModule).toBe('@angular/core'); + expect(actualDeclaration!.node).toBe(expectedDeclarationNode); + expect(actualDeclaration!.viaModule).toBe('@angular/core'); }); it('should recognize TypeScript helpers (as function declarations)', () => { @@ -1940,9 +1954,9 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const {factoryFn} = parseStatementForUmdModule( - getSourceFileOrError(bundle.program, file.name).statements[0]) !; + getSourceFileOrError(bundle.program, file.name).statements[0])!; const testForHelper = createTestForTsHelper(host, factoryFn, getFunctionDeclaration); @@ -1972,9 +1986,9 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const {factoryFn} = parseStatementForUmdModule( - getSourceFileOrError(bundle.program, file.name).statements[0]) !; + getSourceFileOrError(bundle.program, file.name).statements[0])!; const testForHelper = createTestForTsHelper(host, factoryFn, getFunctionDeclaration); @@ -2004,9 +2018,9 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const {factoryFn} = parseStatementForUmdModule( - getSourceFileOrError(bundle.program, file.name).statements[0]) !; + getSourceFileOrError(bundle.program, file.name).statements[0])!; const testForHelper = createTestForTsHelper(host, factoryFn, getVariableDeclaration); @@ -2036,9 +2050,9 @@ runInEachFileSystem(() => { }; loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const {factoryFn} = parseStatementForUmdModule( - getSourceFileOrError(bundle.program, file.name).statements[0]) !; + getSourceFileOrError(bundle.program, file.name).statements[0])!; const testForHelper = createTestForTsHelper(host, factoryFn, getVariableDeclaration); @@ -2076,9 +2090,9 @@ runInEachFileSystem(() => { const [testFile, tslibFile] = files; const bundle = makeTestBundleProgram(testFile.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const {factoryFn} = parseStatementForUmdModule( - getSourceFileOrError(bundle.program, testFile.name).statements[0]) !; + getSourceFileOrError(bundle.program, testFile.name).statements[0])!; const tslibSourceFile = getSourceFileOrError(bundle.program, tslibFile.name); const testForHelper = createTestForTsHelper(host, factoryFn, () => tslibSourceFile); @@ -2094,12 +2108,12 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/b_module.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, '@angular/core'], ['a', `a = 'a'`, '/a_module'], @@ -2122,12 +2136,12 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/wildcard_reexports.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, _('/b_module')], ['a', `a = 'a'`, _('/b_module')], @@ -2150,13 +2164,13 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/wildcard_reexports_imported_helpers.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, _('/b_module')], ['a', `a = 'a'`, _('/b_module')], @@ -2179,11 +2193,11 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles([INLINE_EXPORT_FILE]); const bundle = makeTestBundleProgram(INLINE_EXPORT_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, INLINE_EXPORT_FILE.name); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - const decl = exportDeclarations !.get('directives') as InlineDeclaration; + const decl = exportDeclarations!.get('directives') as InlineDeclaration; expect(decl).not.toBeUndefined(); expect(decl.node).toBeNull(); expect(decl.expression).toBeDefined(); @@ -2201,9 +2215,9 @@ runInEachFileSystem(() => { }; loadTestFiles([tslib]); const bundle = makeTestBundleProgram(tslib.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const sf = getSourceFileOrError(bundle.program, tslib.name); - const exportDeclarations = host.getExportsOfModule(sf) !; + const exportDeclarations = host.getExportsOfModule(sf)!; expect([...exportDeclarations].map(([exportName, {known}]) => [exportName, known])) .toEqual([ @@ -2219,26 +2233,26 @@ runInEachFileSystem(() => { it('should return the class symbol for an ES2015 class', () => { loadTestFiles([SIMPLE_ES2015_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_ES2015_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_ES2015_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); const classSymbol = host.getClassSymbol(node); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(node); - expect(classSymbol !.implementation.valueDeclaration).toBe(node); + expect(classSymbol!.declaration.valueDeclaration).toBe(node); + expect(classSymbol!.implementation.valueDeclaration).toBe(node); }); it('should handle wildcard re-exports of other modules (with emitted helpers)', () => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/wildcard_reexports.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, _('/b_module')], ['a', `a = 'a'`, _('/b_module')], @@ -2261,13 +2275,13 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/wildcard_reexports_imported_helpers.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, _('/b_module')], ['a', `a = 'a'`, _('/b_module')], @@ -2290,12 +2304,12 @@ runInEachFileSystem(() => { loadFakeCore(getFileSystem()); loadTestFiles(EXPORTS_FILES); const bundle = makeTestBundleProgram(_('/index.js')); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/wildcard_reexports_with_require.js')); const exportDeclarations = host.getExportsOfModule(file); expect(exportDeclarations).not.toBe(null); - expect(Array.from(exportDeclarations !.entries()) - .map(entry => [entry[0], entry[1].node !.getText(), entry[1].viaModule])) + expect(Array.from(exportDeclarations!.entries()) + .map(entry => [entry[0], entry[1].node!.getText(), entry[1].viaModule])) .toEqual([ ['Directive', `Directive: FnWithArg<(clazz: any) => any>`, _('/b_module')], ['a', `a = 'a'`, _('/b_module')], @@ -2317,42 +2331,42 @@ runInEachFileSystem(() => { it('should return the class symbol for an ES5 class (outer variable declaration)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the class symbol for an ES5 class (inner function declaration)', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(innerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the same class symbol (of the outer declaration) for outer and inner declarations', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; - const innerSymbol = host.getClassSymbol(innerNode) !; - const outerSymbol = host.getClassSymbol(outerNode) !; + const innerSymbol = host.getClassSymbol(innerNode)!; + const outerSymbol = host.getClassSymbol(outerNode)!; expect(innerSymbol.declaration).toBe(outerSymbol.declaration); expect(innerSymbol.implementation).toBe(outerSymbol.implementation); }); @@ -2361,37 +2375,37 @@ runInEachFileSystem(() => { () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'NoParensClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return the class symbol for an ES5 class whose IIFE is not wrapped with inner parens', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'InnerParensClass', isNamedVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; const classSymbol = host.getClassSymbol(outerNode); expect(classSymbol).toBeDefined(); - expect(classSymbol !.declaration.valueDeclaration).toBe(outerNode); - expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode); + expect(classSymbol!.declaration.valueDeclaration).toBe(outerNode); + expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode); }); it('should return undefined if node is not an ES5 class', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); const classSymbol = host.getClassSymbol(node); @@ -2406,7 +2420,7 @@ runInEachFileSystem(() => { }; loadTestFiles([testFile]); const bundle = makeTestBundleProgram(testFile.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration(bundle.program, testFile.name, 'MyClass', isNamedVariableDeclaration); const classSymbol = host.getClassSymbol(node); @@ -2419,7 +2433,7 @@ runInEachFileSystem(() => { it('should return true if a given node is a TS class declaration', () => { loadTestFiles([SIMPLE_ES2015_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_ES2015_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_ES2015_CLASS_FILE.name, 'EmptyClass', isNamedClassDeclaration); expect(host.isClass(node)).toBe(true); @@ -2428,7 +2442,7 @@ runInEachFileSystem(() => { it('should return true if a given node is the outer variable declaration of a class', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration); expect(host.isClass(node)).toBe(true); @@ -2437,17 +2451,17 @@ runInEachFileSystem(() => { it('should return true if a given node is the inner variable declaration of a class', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const outerNode = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', ts.isVariableDeclaration); - const innerNode = getIifeBody(outerNode) !.statements.find(isNamedFunctionDeclaration) !; + const innerNode = getIifeBody(outerNode)!.statements.find(isNamedFunctionDeclaration)!; expect(host.isClass(innerNode)).toBe(true); }); it('should return false if a given node is a function declaration', () => { loadTestFiles([FOO_FUNCTION_FILE]); const bundle = makeTestBundleProgram(FOO_FUNCTION_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const node = getDeclaration( bundle.program, FOO_FUNCTION_FILE.name, 'foo', isNamedFunctionDeclaration); expect(host.isClass(node)).toBe(false); @@ -2463,7 +2477,7 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); return host.hasBaseClass(classNode); @@ -2510,7 +2524,7 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); const expression = host.getBaseClassExpression(classNode); @@ -2532,7 +2546,7 @@ runInEachFileSystem(() => { function TestClass() {} return TestClass; }(BaseClass));`); - expect(identifier !.text).toBe('BaseClass'); + expect(identifier!.text).toBe('BaseClass'); }); it('should find the base class of an IIFE with a unique name generated for the _super parameter', @@ -2547,7 +2561,7 @@ runInEachFileSystem(() => { function TestClass() {} return TestClass; }(BaseClass));`); - expect(identifier !.text).toBe('BaseClass'); + expect(identifier!.text).toBe('BaseClass'); }); it('should not find a base class for an IIFE without parameter', () => { @@ -2582,10 +2596,10 @@ runInEachFileSystem(() => { loadTestFiles([file]); const bundle = makeTestBundleProgram(file.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const classNode = getDeclaration(bundle.program, file.name, 'TestClass', isNamedVariableDeclaration); - const expression = host.getBaseClassExpression(classNode) !; + const expression = host.getBaseClassExpression(classNode)!; expect(expression.getText()).toBe('foo()'); }); }); @@ -2594,7 +2608,7 @@ runInEachFileSystem(() => { it('should return an array of all classes in the given source file', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(DECORATED_FILES[0].name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); @@ -2612,21 +2626,21 @@ runInEachFileSystem(() => { it('should return decorators of class symbol', () => { loadTestFiles(DECORATED_FILES); const bundle = makeTestBundleProgram(DECORATED_FILES[0].name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const primaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[0].name); const secondaryFile = getSourceFileOrError(bundle.program, DECORATED_FILES[1].name); const classSymbolsPrimary = host.findClassSymbols(primaryFile); const classDecoratorsPrimary = classSymbolsPrimary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsPrimary.length).toEqual(2); - expect(classDecoratorsPrimary[0] !.map(d => d.name)).toEqual(['Directive']); - expect(classDecoratorsPrimary[1] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[0]!.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsPrimary[1]!.map(d => d.name)).toEqual(['Directive']); const classSymbolsSecondary = host.findClassSymbols(secondaryFile); const classDecoratorsSecondary = classSymbolsSecondary.map(s => host.getDecoratorsOfSymbol(s)); expect(classDecoratorsSecondary.length).toEqual(1); - expect(classDecoratorsSecondary[0] !.map(d => d.name)).toEqual(['Directive']); + expect(classDecoratorsSecondary[0]!.map(d => d.name)).toEqual(['Directive']); }); }); @@ -2639,10 +2653,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/class1.js'), 'Class1', ts.isVariableDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find the dts declaration for exported functions', () => { @@ -2652,10 +2667,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(_('/ep/typings/func1.d.ts')); const mooFn = getDeclaration( bundle.program, _('/ep/src/func1.js'), 'mooFn', ts.isFunctionDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(mooFn); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts')); }); it('should return null if there is no matching class in the matching dts file', () => { @@ -2665,7 +2681,8 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const missingClass = getDeclaration( bundle.program, _('/ep/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2677,7 +2694,8 @@ runInEachFileSystem(() => { const missingClass = getDeclaration( bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2', ts.isVariableDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); expect(host.getDtsDeclaration(missingClass)).toBe(null); }); @@ -2690,10 +2708,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find the dts file that contains a matching class declaration, even if the source files do not match', @@ -2704,10 +2723,11 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const class1 = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(class1); - expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); + expect(dtsDeclaration!.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts')); }); it('should find aliased exports', () => { @@ -2717,7 +2737,8 @@ runInEachFileSystem(() => { const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); const sourceClass = getDeclaration( bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', ts.isVariableDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); const dtsDeclaration = host.getDtsDeclaration(sourceClass); if (dtsDeclaration === null) { @@ -2737,18 +2758,19 @@ runInEachFileSystem(() => { loadTestFiles(TYPINGS_DTS_FILES); const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]); const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); const class2 = getDeclaration( bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedVariableDeclaration); const class2DtsDeclaration = host.getDtsDeclaration(class2); - expect(class2DtsDeclaration !.getSourceFile().fileName) + expect(class2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/class2.d.ts')); const internalClass2 = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedVariableDeclaration); const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2); - expect(internalClass2DtsDeclaration !.getSourceFile().fileName) + expect(internalClass2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/internal.d.ts')); }); @@ -2762,14 +2784,15 @@ runInEachFileSystem(() => { bundle.program, _('/ep/src/class2.js'), 'Class2', ts.isVariableDeclaration); const internalClass2 = getDeclaration( bundle.program, _('/ep/src/internal.js'), 'Class2', ts.isVariableDeclaration); - const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts); + const host = + createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle, dts)); const class2DtsDeclaration = host.getDtsDeclaration(class2); - expect(class2DtsDeclaration !.getSourceFile().fileName) + expect(class2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/class2.d.ts')); const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2); - expect(internalClass2DtsDeclaration !.getSourceFile().fileName) + expect(internalClass2DtsDeclaration!.getSourceFile().fileName) .toEqual(_('/ep/typings/internal.d.ts')); }); }); @@ -2778,7 +2801,7 @@ runInEachFileSystem(() => { it('should return the name of the inner class declaration', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const emptyClass = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); @@ -2802,7 +2825,7 @@ runInEachFileSystem(() => { it('should return the name of the inner class declaration', () => { loadTestFiles([SIMPLE_CLASS_FILE]); const bundle = makeTestBundleProgram(SIMPLE_CLASS_FILE.name); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const emptyClass = getDeclaration( bundle.program, SIMPLE_CLASS_FILE.name, 'EmptyClass', isNamedVariableDeclaration); @@ -2827,10 +2850,10 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(getRootFiles(MODULE_WITH_PROVIDERS_PROGRAM)[0]); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/functions.js')); const fns = host.getModuleWithProvidersFunctions(file); - expect(fns.map(fn => [fn.declaration.name !.getText(), fn.ngModule.node.name.text])) + expect(fns.map(fn => [fn.declaration.name!.getText(), fn.ngModule.node.name.text])) .toEqual([ ['ngModuleIdentifier', 'InternalModule'], ['ngModuleWithEmptyProviders', 'InternalModule'], @@ -2843,7 +2866,7 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(getRootFiles(MODULE_WITH_PROVIDERS_PROGRAM)[0]); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/methods.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ @@ -2870,7 +2893,7 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(getRootFiles(MODULE_WITH_PROVIDERS_PROGRAM)[0]); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/outer_aliased_class.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([ @@ -2883,7 +2906,7 @@ runInEachFileSystem(() => { () => { loadTestFiles(MODULE_WITH_PROVIDERS_PROGRAM); const bundle = makeTestBundleProgram(getRootFiles(MODULE_WITH_PROVIDERS_PROGRAM)[0]); - const host = new UmdReflectionHost(new MockLogger(), false, bundle); + const host = createHost(bundle, new UmdReflectionHost(new MockLogger(), false, bundle)); const file = getSourceFileOrError(bundle.program, _('/src/inner_aliased_class.js')); const fn = host.getModuleWithProvidersFunctions(file); expect(fn.map(fn => [fn.declaration.getText(), fn.ngModule.node.name.text])).toEqual([