From dd98c17b10b9fafc5bfbfc70f98ea7ba45dd2ab7 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 9 Aug 2022 16:36:53 -0700 Subject: [PATCH] Merge multiple symbols even when re-exported (#49987) * Merge multiple symbols even when re-exported As far as I remember, the target of `mergeSymbol` needs to be a merged symbol, not a symbol with a mergeId that points to mergedSymbol. However, mergeSymbolTable didn't check for this. I can't remember if symbol tables may contain symbols-with-mergeId. If they can, then mergeSymbolTable needs to call getMergedSymbol on the individual targets of the merge. That's what I did in this PR. * Call getMergeSymbol eagerly On the source, not target, of mergeSymbolTable's contents --- src/compiler/checker.ts | 2 +- .../mergeMultipleInterfacesReexported.js | 65 +++++++++++++++++++ .../mergeMultipleInterfacesReexported.symbols | 50 ++++++++++++++ .../mergeMultipleInterfacesReexported.types | 43 ++++++++++++ ...onDoesNamespaceEnumMergeOfReexport.symbols | 4 +- .../mergeMultipleInterfacesReexported.ts | 30 +++++++++ 6 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/mergeMultipleInterfacesReexported.js create mode 100644 tests/baselines/reference/mergeMultipleInterfacesReexported.symbols create mode 100644 tests/baselines/reference/mergeMultipleInterfacesReexported.types create mode 100644 tests/cases/compiler/mergeMultipleInterfacesReexported.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0c36c132968..701747ce8de 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1426,7 +1426,7 @@ namespace ts { function mergeSymbolTable(target: SymbolTable, source: SymbolTable, unidirectional = false) { source.forEach((sourceSymbol, id) => { const targetSymbol = target.get(id); - target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : sourceSymbol); + target.set(id, targetSymbol ? mergeSymbol(targetSymbol, sourceSymbol, unidirectional) : getMergedSymbol(sourceSymbol)); }); } diff --git a/tests/baselines/reference/mergeMultipleInterfacesReexported.js b/tests/baselines/reference/mergeMultipleInterfacesReexported.js new file mode 100644 index 00000000000..a6282d6844d --- /dev/null +++ b/tests/baselines/reference/mergeMultipleInterfacesReexported.js @@ -0,0 +1,65 @@ +//// [tests/cases/compiler/mergeMultipleInterfacesReexported.ts] //// + +//// [index.ts] +export * from './eventList'; + +//// [test.ts] +import { EventList } from "./eventList"; + +declare const p012: "p0" | "p1" | "p2" +const t: keyof EventList = p012 + +//// [eventList.ts] +export interface EventList { + p0: []; +} + +//// [foo.ts] +declare module './index' { + interface EventList { + p1: [] + } +} +export {}; + + +//// [bar.ts] +declare module './index' { + interface EventList { + p2: [] + } +} +export {}; + + +//// [eventList.js] +"use strict"; +exports.__esModule = true; +//// [index.js] +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +exports.__esModule = true; +__exportStar(require("./eventList"), exports); +//// [test.js] +"use strict"; +exports.__esModule = true; +var t = p012; +//// [foo.js] +"use strict"; +exports.__esModule = true; +//// [bar.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/mergeMultipleInterfacesReexported.symbols b/tests/baselines/reference/mergeMultipleInterfacesReexported.symbols new file mode 100644 index 00000000000..c40babde0a3 --- /dev/null +++ b/tests/baselines/reference/mergeMultipleInterfacesReexported.symbols @@ -0,0 +1,50 @@ +=== tests/cases/compiler/index.ts === +export * from './eventList'; +No type information for this code. +No type information for this code.=== tests/cases/compiler/test.ts === +import { EventList } from "./eventList"; +>EventList : Symbol(EventList, Decl(test.ts, 0, 8)) + +declare const p012: "p0" | "p1" | "p2" +>p012 : Symbol(p012, Decl(test.ts, 2, 13)) + +const t: keyof EventList = p012 +>t : Symbol(t, Decl(test.ts, 3, 5)) +>EventList : Symbol(EventList, Decl(test.ts, 0, 8)) +>p012 : Symbol(p012, Decl(test.ts, 2, 13)) + +=== tests/cases/compiler/eventList.ts === +export interface EventList { +>EventList : Symbol(EventList, Decl(eventList.ts, 0, 0), Decl(foo.ts, 0, 26), Decl(bar.ts, 0, 26)) + + p0: []; +>p0 : Symbol(EventList.p0, Decl(eventList.ts, 0, 28)) +} + +=== tests/cases/compiler/foo.ts === +declare module './index' { +>'./index' : Symbol("tests/cases/compiler/index", Decl(index.ts, 0, 0), Decl(foo.ts, 0, 0), Decl(bar.ts, 0, 0)) + + interface EventList { +>EventList : Symbol(EventList, Decl(eventList.ts, 0, 0), Decl(foo.ts, 0, 26), Decl(bar.ts, 0, 26)) + + p1: [] +>p1 : Symbol(EventList.p1, Decl(foo.ts, 1, 25)) + } +} +export {}; + + +=== tests/cases/compiler/bar.ts === +declare module './index' { +>'./index' : Symbol("tests/cases/compiler/index", Decl(index.ts, 0, 0), Decl(foo.ts, 0, 0), Decl(bar.ts, 0, 0)) + + interface EventList { +>EventList : Symbol(EventList, Decl(eventList.ts, 0, 0), Decl(foo.ts, 0, 26), Decl(bar.ts, 0, 26)) + + p2: [] +>p2 : Symbol(EventList.p2, Decl(bar.ts, 1, 25)) + } +} +export {}; + diff --git a/tests/baselines/reference/mergeMultipleInterfacesReexported.types b/tests/baselines/reference/mergeMultipleInterfacesReexported.types new file mode 100644 index 00000000000..1096770ca61 --- /dev/null +++ b/tests/baselines/reference/mergeMultipleInterfacesReexported.types @@ -0,0 +1,43 @@ +=== tests/cases/compiler/index.ts === +export * from './eventList'; +No type information for this code. +No type information for this code.=== tests/cases/compiler/test.ts === +import { EventList } from "./eventList"; +>EventList : any + +declare const p012: "p0" | "p1" | "p2" +>p012 : "p0" | "p1" | "p2" + +const t: keyof EventList = p012 +>t : keyof EventList +>p012 : "p0" | "p1" | "p2" + +=== tests/cases/compiler/eventList.ts === +export interface EventList { + p0: []; +>p0 : [] +} + +=== tests/cases/compiler/foo.ts === +declare module './index' { +>'./index' : typeof import("tests/cases/compiler/index") + + interface EventList { + p1: [] +>p1 : [] + } +} +export {}; + + +=== tests/cases/compiler/bar.ts === +declare module './index' { +>'./index' : typeof import("tests/cases/compiler/index") + + interface EventList { + p2: [] +>p2 : [] + } +} +export {}; + diff --git a/tests/baselines/reference/moduleAugmentationDoesNamespaceEnumMergeOfReexport.symbols b/tests/baselines/reference/moduleAugmentationDoesNamespaceEnumMergeOfReexport.symbols index 0f6a0ad51e4..89c0878d840 100644 --- a/tests/baselines/reference/moduleAugmentationDoesNamespaceEnumMergeOfReexport.symbols +++ b/tests/baselines/reference/moduleAugmentationDoesNamespaceEnumMergeOfReexport.symbols @@ -45,9 +45,9 @@ const g: ns.Root = ns.Root.A; >ns : Symbol(ns, Decl(augment.ts, 0, 6)) >Root : Symbol(ns.Root, Decl(file.ts, 0, 0), Decl(augment.ts, 2, 29)) >ns.Root.A : Symbol(ns.Root.A, Decl(augment.ts, 4, 22)) ->ns.Root : Symbol(ns.Root, Decl(augment.ts, 2, 29)) +>ns.Root : Symbol(ns.Root, Decl(file.ts, 0, 0), Decl(augment.ts, 2, 29)) >ns : Symbol(ns, Decl(augment.ts, 0, 6)) ->Root : Symbol(ns.Root, Decl(augment.ts, 2, 29)) +>Root : Symbol(ns.Root, Decl(file.ts, 0, 0), Decl(augment.ts, 2, 29)) >A : Symbol(ns.Root.A, Decl(augment.ts, 4, 22)) f.x; diff --git a/tests/cases/compiler/mergeMultipleInterfacesReexported.ts b/tests/cases/compiler/mergeMultipleInterfacesReexported.ts new file mode 100644 index 00000000000..4f1164b7ab2 --- /dev/null +++ b/tests/cases/compiler/mergeMultipleInterfacesReexported.ts @@ -0,0 +1,30 @@ +// @filename: index.ts +export * from './eventList'; + +// @filename: test.ts +import { EventList } from "./eventList"; + +declare const p012: "p0" | "p1" | "p2" +const t: keyof EventList = p012 + +// @filename: eventList.ts +export interface EventList { + p0: []; +} + +// @filename: foo.ts +declare module './index' { + interface EventList { + p1: [] + } +} +export {}; + + +// @filename: bar.ts +declare module './index' { + interface EventList { + p2: [] + } +} +export {};