From 064b0c71433cc4ff0320853797170b9e5b7dd6a0 Mon Sep 17 00:00:00 2001 From: wessberg Date: Wed, 14 Apr 2021 01:54:17 +0200 Subject: [PATCH] fix(deconflicting): fix issue where ModuleDeclarations could sometimes not be traced back to an original SourceFile, leading to invalid deconflicting. Closes #129 --- .../visitor/deconflict-module-declaration.ts | 2 +- .../util/get-original-source-file.ts | 16 ++++++- test/export-default.test.ts | 44 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/service/transformer/declaration-bundler/transformers/deconflicter/visitor/deconflict-module-declaration.ts b/src/service/transformer/declaration-bundler/transformers/deconflicter/visitor/deconflict-module-declaration.ts index 3a54ea6f..32c644a7 100644 --- a/src/service/transformer/declaration-bundler/transformers/deconflicter/visitor/deconflict-module-declaration.ts +++ b/src/service/transformer/declaration-bundler/transformers/deconflicter/visitor/deconflict-module-declaration.ts @@ -17,7 +17,7 @@ export function deconflictModuleDeclaration(options: DeconflicterVisitorOptions< const {node, continuation, lexicalEnvironment, compatFactory, typescript, sourceFile, declarationToDeconflictedBindingMap} = options; let nameContResult: TS.ModuleDeclaration["name"]; const id = getIdForNode(options); - const originalSourceFile = getOriginalSourceFile(node, sourceFile, typescript); + const originalSourceFile = getOriginalSourceFile(node.name, sourceFile, typescript, true); // Check if it is a namespace ModuleDeclaration. If it is, its name can be deconflicted. If it isn't, it should augment and merge with any existing declarations for it const isNamespace = (node.flags & typescript.NodeFlags.Namespace) !== 0; diff --git a/src/service/transformer/declaration-bundler/util/get-original-source-file.ts b/src/service/transformer/declaration-bundler/util/get-original-source-file.ts index d35c07a0..2226cf8e 100644 --- a/src/service/transformer/declaration-bundler/util/get-original-source-file.ts +++ b/src/service/transformer/declaration-bundler/util/get-original-source-file.ts @@ -2,6 +2,18 @@ import {SafeNode} from "../../../../type/safe-node"; import {TS} from "../../../../type/ts"; import {getOriginalNode} from "./get-original-node"; -export function getOriginalSourceFile(node: T, currentSourceFile: TS.SourceFile, typescript: typeof TS): TS.SourceFile { - return getOriginalNode(node, typescript).getSourceFile() ?? currentSourceFile; +export function getOriginalSourceFile(node: T, currentSourceFile: TS.SourceFile, typescript: typeof TS, print = false): TS.SourceFile { + const originalNode = getOriginalNode(node, typescript); + let sourceFile: TS.SourceFile|undefined = originalNode.getSourceFile(); + if (sourceFile != null) return sourceFile; + + if (print) console.log(originalNode); + + if (originalNode._parent != null) { + if (originalNode._parent.kind === typescript.SyntaxKind.SourceFile) { + return originalNode._parent as TS.SourceFile; + } + sourceFile = originalNode._parent?.getSourceFile(); + } + return sourceFile ?? currentSourceFile; } diff --git a/test/export-default.test.ts b/test/export-default.test.ts index 7ef853e7..8d78d5ef 100644 --- a/test/export-default.test.ts +++ b/test/export-default.test.ts @@ -425,3 +425,47 @@ test("Handles default exports inside ExportSpecifiers. #3", withTypeScript, asyn `) ); }); + +test("Handles default exports inside ExportSpecifiers. #4", withTypeScript, async (t, {typescript}) => { + const bundle = await generateRollupBundle( + [ + { + entry: true, + fileName: "index.ts", + text: `\ + export { default as Foo } from "./foo"; + ` + }, + { + entry: false, + fileName: "foo.ts", + text: `\ + function Foo(a: string, b: string): string { + return a + b; + } + Foo.tags = ['foo', 'bar', 'baz']; + + export default Foo; + ` + } + ], + { + typescript, + debug: false + } + ); + const { + declarations: [file] + } = bundle; + + t.deepEqual( + formatCode(file.code), + formatCode(`\ + declare function Foo(a: string, b: string): string; + declare namespace Foo { + var tags: string[]; + } + export { Foo }; + `) + ); +});