From c77656e2dd959cf70d4999f0cfc419f20a6f9e9e Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 11 Dec 2019 17:00:47 +0000 Subject: [PATCH] fix(ngcc): handle imports in dts files when processing UMD (#34356) When statically evalulating UMD code it is possible to find that we are looking for the declaration of an identifier that actually came from a typings file (rather than a UMD file). Previously, the UMD reflection host would always try to use a UMD specific algorithm for finding identifier declarations, but when the id is actually in a typings file this resulted in the returned declaration being the containing file of the declaration rather than the declaration itself. Now the UMD reflection host will check to see if the file containing the identifier is a typings file and use the appropriate stategy. PR Close #34356 --- .../compiler-cli/ngcc/src/host/umd_host.ts | 3 +- .../ngcc/test/host/umd_host_spec.ts | 37 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/packages/compiler-cli/ngcc/src/host/umd_host.ts b/packages/compiler-cli/ngcc/src/host/umd_host.ts index e5dc0b2674..7d49bafcc5 100644 --- a/packages/compiler-cli/ngcc/src/host/umd_host.ts +++ b/packages/compiler-cli/ngcc/src/host/umd_host.ts @@ -36,7 +36,8 @@ export class UmdReflectionHost extends Esm5ReflectionHost { } getDeclarationOfIdentifier(id: ts.Identifier): Declaration|null { - return this.getUmdImportedDeclaration(id) || super.getDeclarationOfIdentifier(id); + return (!id.getSourceFile().isDeclarationFile && this.getUmdImportedDeclaration(id)) || + super.getDeclarationOfIdentifier(id); } getExportsOfModule(module: ts.Node): Map|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 df14a01567..0f24f1b71f 100644 --- a/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts +++ b/packages/compiler-cli/ngcc/test/host/umd_host_spec.ts @@ -1777,6 +1777,43 @@ runInEachFileSystem(() => { expect(actualDeclaration !.node).toBe(expectedDeclarationNode); expect(actualDeclaration !.viaModule).toBe('@angular/core'); }); + + it('should return the correct declaration of an identifier imported in a typings file', + () => { + + const FILES = [ + { + name: _('/node_modules/test-package/index.d.ts'), + contents: ` + import {SubModule} from 'sub_module'; + export const x = SubModule; + `, + }, + { + name: _('/node_modules/packages.json'), + contents: '{ "typings: "index.d.ts" }', + }, + { + name: _('/node_modules/sub_module/index.d.ts'), + contents: `export class SubModule {}`, + } + ]; + loadTestFiles(FILES); + const {program, host: compilerHost} = makeTestBundleProgram(FILES[0].name); + const host = new UmdReflectionHost(new MockLogger(), false, program, compilerHost); + const expectedDeclaration = + getDeclaration(program, FILES[2].name, 'SubModule', isNamedClassDeclaration); + const x = getDeclaration(program, FILES[0].name, 'x', isNamedVariableDeclaration); + if (x.initializer === undefined || !ts.isIdentifier(x.initializer)) { + return fail('Expected constant `x` to have an identifer as an initializer.'); + } + const decl = host.getDeclarationOfIdentifier(x.initializer); + if (decl === null) { + return fail('Expected to find a declaration for ' + x.initializer.getText()); + } + expect(decl.viaModule).toEqual('sub_module'); + expect(decl.node).toBe(expectedDeclaration); + }); }); describe('getExportsOfModule()', () => {