diff --git a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts index ca3d6532c6396..b8304951b73ea 100644 --- a/packages/compiler-cli/ngcc/src/host/commonjs_host.ts +++ b/packages/compiler-cli/ngcc/src/host/commonjs_host.ts @@ -181,7 +181,7 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { } else { return { name, - declaration: {node: null, known: null, expression, viaModule: null}, + declaration: {node: null, known: null, expression, viaModule: null, importName: null}, }; } } @@ -204,7 +204,8 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost { return null; } const viaModule = isExternalImport(importPath) ? importPath : null; - return {node: module, known: null, viaModule, identity: null}; + const importName = viaModule && id.text; + return {node: module, known: null, viaModule, importName, identity: null}; } private resolveModuleName(moduleName: string, containingFile: ts.SourceFile): ts.SourceFile diff --git a/packages/compiler-cli/ngcc/src/host/esm2015_host.ts b/packages/compiler-cli/ngcc/src/host/esm2015_host.ts index 579ab00546a9c..ce92a320d9ac5 100644 --- a/packages/compiler-cli/ngcc/src/host/esm2015_host.ts +++ b/packages/compiler-cli/ngcc/src/host/esm2015_host.ts @@ -1606,7 +1606,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N kind: TypeValueReferenceKind.IMPORTED, valueDeclaration: decl.node, moduleName: decl.viaModule, - importedName: decl.node.name.text, + importedName: decl.importName!, // viaModule and importName are both non-null together nestedPath: null, }; } else { diff --git a/packages/compiler-cli/ngcc/src/host/esm5_host.ts b/packages/compiler-cli/ngcc/src/host/esm5_host.ts index 5464fbcff4cbe..42f2f61451182 100644 --- a/packages/compiler-cli/ngcc/src/host/esm5_host.ts +++ b/packages/compiler-cli/ngcc/src/host/esm5_host.ts @@ -86,6 +86,7 @@ export class Esm5ReflectionHost extends Esm2015ReflectionHost { known: nonEmittedNorImportedTsHelperDeclaration, node: null, viaModule: null, + importName: null, }; } } diff --git a/packages/compiler-cli/ngcc/src/host/umd_host.ts b/packages/compiler-cli/ngcc/src/host/umd_host.ts index 5a4b73ed70b35..0a18db6a5ca49 100644 --- a/packages/compiler-cli/ngcc/src/host/umd_host.ts +++ b/packages/compiler-cli/ngcc/src/host/umd_host.ts @@ -175,11 +175,15 @@ export class UmdReflectionHost extends Esm5ReflectionHost { if (decl.node !== null) { reexports.push({ name, - declaration: {node: decl.node, known: null, viaModule, identity: decl.identity} + declaration: + {node: decl.node, known: null, viaModule, importName: name, identity: decl.identity} }); } else { - reexports.push( - {name, declaration: {node: null, known: null, expression: decl.expression, viaModule}}); + reexports.push({ + name, + declaration: + {node: null, known: null, expression: decl.expression, viaModule, importName: name} + }); } }); return reexports; @@ -203,7 +207,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost { } return { name, - declaration: {node: null, known: null, expression, viaModule: null}, + declaration: {node: null, known: null, expression, viaModule: null, importName: null}, }; } @@ -245,8 +249,9 @@ export class UmdReflectionHost extends Esm5ReflectionHost { // did not know that we were importing the declaration. const viaModule = declaration.viaModule === null ? moduleDeclaration.viaModule : declaration.viaModule; + const importName = viaModule && id.text; - return {...declaration, viaModule, known: getTsHelperFnFromIdentifier(id)}; + return {...declaration, viaModule, importName, known: getTsHelperFnFromIdentifier(id)}; } private getUmdModuleDeclaration(id: ts.Identifier): Declaration|null { @@ -261,7 +266,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost { } const viaModule = isExternalImport(importPath) ? importPath : null; - return {node: module, viaModule, known: null, identity: null}; + return {node: module, viaModule, known: null, identity: null, importName: null}; } private getImportPathFromParameter(id: ts.Identifier): string|null { 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 d2e1fcf02b76d..a60c06cff7084 100644 --- a/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/commonjs_host_spec.ts @@ -1780,6 +1780,7 @@ exports.MissingClass2 = MissingClass2; known: knownAs, node: getHelperDeclaration(helperName), viaModule, + importName: viaModule && helperName, identity: null, }); }; @@ -2104,6 +2105,7 @@ exports.MissingClass2 = MissingClass2; expression: helperIdentifier, node: null, viaModule: null, + importName: null, }); }; @@ -2138,6 +2140,7 @@ exports.MissingClass2 = MissingClass2; expression: helperIdentifier, node: null, viaModule: null, + importName: null, }); }; 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 b5db58d50b2b0..ec62e729098a2 100644 --- a/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/esm2015_host_spec.ts @@ -1140,6 +1140,50 @@ runInEachFileSystem(() => { }); describe('getConstructorParameters()', () => { + describe('getConstructorParameters()', () => { + it('should find the correct imported identifier for decorated constructor parameter types', + () => { + const files = [ + { + name: _('/node_modules/shared-lib/foo.d.ts'), + contents: ` + declare class Foo {} + export {Foo as Bar}; + `, + }, + { + name: _('/node_modules/shared-lib/index.d.ts'), + contents: ` + export {Bar as Baz} from './foo'; + `, + }, + { + name: _('/main.js'), + contents: ` + import {Baz} from 'shared-lib'; + + export class SomeClass { + constructor(arg1) {} + } + SomeClass.ctorParameters = [{ type: Baz }]; + `, + }, + ]; + + loadTestFiles(files); + const bundle = makeTestBundleProgram(_('/main.js')); + const host = + createHost(bundle, new Esm2015ReflectionHost(new MockLogger(), false, bundle)); + const classNode = getDeclaration( + bundle.program, _('/main.js'), 'SomeClass', isNamedClassDeclaration); + + const parameters = host.getConstructorParameters(classNode)!; + + expect(parameters).toEqual([jasmine.objectContaining({name: 'arg1'})]); + expectTypeValueReferencesForParameters(parameters, ['Baz'], 'shared-lib'); + }); + }); + it('should find the decorated constructor parameters', () => { loadFakeCore(getFileSystem()); loadTestFiles([SOME_DIRECTIVE_FILE]); 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 0fb7428196efa..13cf0614af938 100644 --- a/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/esm5_host_spec.ts @@ -1799,6 +1799,7 @@ runInEachFileSystem(() => { known: knownAs, node: getHelperDeclaration(helperName), viaModule, + importName: viaModule && helperName, identity: null, }); }; @@ -2195,6 +2196,7 @@ runInEachFileSystem(() => { expression: helperIdentifier, node: null, viaModule: null, + importName: null, }); }; @@ -2226,6 +2228,7 @@ runInEachFileSystem(() => { expression: helperIdentifier, node: null, viaModule: null, + importName: null, }); }; 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 a25b09fb5a3bc..8a42ccf427a6e 100644 --- a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts @@ -1591,7 +1591,7 @@ runInEachFileSystem(() => { `; break; case 'inlined_with_suffix': - fileHeaderWithUmd = ` + fileHeaderWithUmd = ` (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports)) : typeof define === 'function' && define.amd ? define('test', ['exports'], factory) : @@ -1904,6 +1904,7 @@ runInEachFileSystem(() => { known: knownAs, node: getHelperDeclaration(factoryFn, helperName), viaModule, + importName: viaModule && helperName, identity: null, }); }; @@ -2207,6 +2208,7 @@ runInEachFileSystem(() => { expression: helperIdentifier, node: null, viaModule: null, + importName: null, }); }; @@ -2246,6 +2248,7 @@ runInEachFileSystem(() => { expression: helperIdentifier, node: null, viaModule: null, + importName: null, }); }; diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts index 7c8d53e9257ca..2c535d1ec1db1 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts @@ -960,6 +960,7 @@ runInEachFileSystem(() => { known: tsHelperFn, node: id, viaModule: null, + importName: null, identity: null, }; } diff --git a/packages/compiler-cli/src/ngtsc/reflection/src/host.ts b/packages/compiler-cli/src/ngtsc/reflection/src/host.ts index 3d28a12d31940..6259576e6ed74 100644 --- a/packages/compiler-cli/src/ngtsc/reflection/src/host.ts +++ b/packages/compiler-cli/src/ngtsc/reflection/src/host.ts @@ -540,6 +540,7 @@ export interface BaseDeclaration { * of the application and was not imported from an absolute path, this will be `null`. */ viaModule: string|null; + importName: string|null; /** * TypeScript reference to the declaration itself, if one exists. diff --git a/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts b/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts index 85be99477c5fb..15eacae964b2a 100644 --- a/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts +++ b/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts @@ -303,6 +303,7 @@ export class TypeScriptReflectionHost implements ReflectionHost { importInfo !== null && importInfo.from !== null && !importInfo.from.startsWith('.') ? importInfo.from : null; + const importName = importInfo && importInfo.name; // Now, resolve the Symbol to its declaration by following any and all aliases. while (symbol.flags & ts.SymbolFlags.Alias) { @@ -316,6 +317,7 @@ export class TypeScriptReflectionHost implements ReflectionHost { node: symbol.valueDeclaration, known: null, viaModule, + importName, identity: null, }; } else if (symbol.declarations !== undefined && symbol.declarations.length > 0) { @@ -323,6 +325,7 @@ export class TypeScriptReflectionHost implements ReflectionHost { node: symbol.declarations[0], known: null, viaModule, + importName, identity: null, }; } else { diff --git a/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts b/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts index f4cfd540acc12..16a3159a7ada8 100644 --- a/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts +++ b/packages/compiler-cli/src/ngtsc/reflection/test/ts_host_spec.ts @@ -363,6 +363,7 @@ runInEachFileSystem(() => { node: targetDecl, known: null, viaModule: 'absolute', + importName: 'Target', identity: null, }); }); @@ -394,6 +395,7 @@ runInEachFileSystem(() => { node: targetDecl, known: null, viaModule: 'absolute', + importName: 'Target', identity: null, }); });