From eb112ab492c26c6346ea587646dd617093e72b78 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Sat, 21 Apr 2018 12:50:05 -0700 Subject: [PATCH] Deduplicate declarations in combined type/value symbols (#23593) --- src/compiler/checker.ts | 6 ++-- ...aliasDoesNotDuplicateSignatures.errors.txt | 21 ++++++++++++ .../aliasDoesNotDuplicateSignatures.js | 23 +++++++++++++ .../aliasDoesNotDuplicateSignatures.symbols | 32 +++++++++++++++++++ .../aliasDoesNotDuplicateSignatures.types | 32 +++++++++++++++++++ .../aliasDoesNotDuplicateSignatures.ts | 13 ++++++++ 6 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/aliasDoesNotDuplicateSignatures.errors.txt create mode 100644 tests/baselines/reference/aliasDoesNotDuplicateSignatures.js create mode 100644 tests/baselines/reference/aliasDoesNotDuplicateSignatures.symbols create mode 100644 tests/baselines/reference/aliasDoesNotDuplicateSignatures.types create mode 100644 tests/cases/compiler/aliasDoesNotDuplicateSignatures.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8d37b888178..99b3420131f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1841,7 +1841,7 @@ namespace ts { return valueSymbol; } const result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.escapedName); - result.declarations = concatenate(valueSymbol.declarations, typeSymbol.declarations); + result.declarations = deduplicate(concatenate(valueSymbol.declarations, typeSymbol.declarations), equateValues); result.parent = valueSymbol.parent || typeSymbol.parent; if (valueSymbol.valueDeclaration) result.valueDeclaration = valueSymbol.valueDeclaration; if (typeSymbol.members) result.members = typeSymbol.members; @@ -1876,7 +1876,7 @@ namespace ts { let symbolFromVariable: Symbol; // First check if module was specified with "export=". If so, get the member from the resolved type - if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get("export=" as __String)) { + if (moduleSymbol && moduleSymbol.exports && moduleSymbol.exports.get(InternalSymbolName.ExportEquals)) { symbolFromVariable = getPropertyOfType(getTypeOfSymbol(targetSymbol), name.escapedText); } else { @@ -1889,7 +1889,7 @@ namespace ts { if (!symbolFromModule && allowSyntheticDefaultImports && name.escapedText === InternalSymbolName.Default) { symbolFromModule = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias); } - const symbol = symbolFromModule && symbolFromVariable ? + const symbol = symbolFromModule && symbolFromVariable && symbolFromModule !== symbolFromVariable ? combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) : symbolFromModule || symbolFromVariable; if (!symbol) { diff --git a/tests/baselines/reference/aliasDoesNotDuplicateSignatures.errors.txt b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.errors.txt new file mode 100644 index 00000000000..38e2c8cfe17 --- /dev/null +++ b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.errors.txt @@ -0,0 +1,21 @@ +tests/cases/compiler/user.ts(3,5): error TS2322: Type '() => void' is not assignable to type 'string'. +tests/cases/compiler/user.ts(4,5): error TS2322: Type '() => void' is not assignable to type 'string'. + + +==== tests/cases/compiler/demo.d.ts (0 errors) ==== + declare namespace demoNS { + function f(): void; + } + declare module 'demoModule' { + import alias = demoNS; + export = alias; + } +==== tests/cases/compiler/user.ts (2 errors) ==== + import { f } from 'demoModule'; + // Assign an incorrect type here to see the type of 'f'. + let x1: string = demoNS.f; + ~~ +!!! error TS2322: Type '() => void' is not assignable to type 'string'. + let x2: string = f; + ~~ +!!! error TS2322: Type '() => void' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/aliasDoesNotDuplicateSignatures.js b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.js new file mode 100644 index 00000000000..0ae878bebc5 --- /dev/null +++ b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.js @@ -0,0 +1,23 @@ +//// [tests/cases/compiler/aliasDoesNotDuplicateSignatures.ts] //// + +//// [demo.d.ts] +declare namespace demoNS { + function f(): void; +} +declare module 'demoModule' { + import alias = demoNS; + export = alias; +} +//// [user.ts] +import { f } from 'demoModule'; +// Assign an incorrect type here to see the type of 'f'. +let x1: string = demoNS.f; +let x2: string = f; + +//// [user.js] +"use strict"; +exports.__esModule = true; +var demoModule_1 = require("demoModule"); +// Assign an incorrect type here to see the type of 'f'. +var x1 = demoNS.f; +var x2 = demoModule_1.f; diff --git a/tests/baselines/reference/aliasDoesNotDuplicateSignatures.symbols b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.symbols new file mode 100644 index 00000000000..21ae7940f96 --- /dev/null +++ b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.symbols @@ -0,0 +1,32 @@ +=== tests/cases/compiler/demo.d.ts === +declare namespace demoNS { +>demoNS : Symbol(demoNS, Decl(demo.d.ts, 0, 0)) + + function f(): void; +>f : Symbol(f, Decl(demo.d.ts, 0, 26)) +} +declare module 'demoModule' { +>'demoModule' : Symbol('demoModule', Decl(demo.d.ts, 2, 1)) + + import alias = demoNS; +>alias : Symbol(alias, Decl(demo.d.ts, 3, 29)) +>demoNS : Symbol(alias, Decl(demo.d.ts, 0, 0)) + + export = alias; +>alias : Symbol(alias, Decl(demo.d.ts, 3, 29)) +} +=== tests/cases/compiler/user.ts === +import { f } from 'demoModule'; +>f : Symbol(f, Decl(user.ts, 0, 8)) + +// Assign an incorrect type here to see the type of 'f'. +let x1: string = demoNS.f; +>x1 : Symbol(x1, Decl(user.ts, 2, 3)) +>demoNS.f : Symbol(f, Decl(demo.d.ts, 0, 26)) +>demoNS : Symbol(demoNS, Decl(demo.d.ts, 0, 0)) +>f : Symbol(f, Decl(demo.d.ts, 0, 26)) + +let x2: string = f; +>x2 : Symbol(x2, Decl(user.ts, 3, 3)) +>f : Symbol(f, Decl(user.ts, 0, 8)) + diff --git a/tests/baselines/reference/aliasDoesNotDuplicateSignatures.types b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.types new file mode 100644 index 00000000000..ada54494a83 --- /dev/null +++ b/tests/baselines/reference/aliasDoesNotDuplicateSignatures.types @@ -0,0 +1,32 @@ +=== tests/cases/compiler/demo.d.ts === +declare namespace demoNS { +>demoNS : typeof demoNS + + function f(): void; +>f : () => void +} +declare module 'demoModule' { +>'demoModule' : typeof 'demoModule' + + import alias = demoNS; +>alias : typeof alias +>demoNS : typeof alias + + export = alias; +>alias : typeof alias +} +=== tests/cases/compiler/user.ts === +import { f } from 'demoModule'; +>f : () => void + +// Assign an incorrect type here to see the type of 'f'. +let x1: string = demoNS.f; +>x1 : string +>demoNS.f : () => void +>demoNS : typeof demoNS +>f : () => void + +let x2: string = f; +>x2 : string +>f : () => void + diff --git a/tests/cases/compiler/aliasDoesNotDuplicateSignatures.ts b/tests/cases/compiler/aliasDoesNotDuplicateSignatures.ts new file mode 100644 index 00000000000..fcae45f3dc1 --- /dev/null +++ b/tests/cases/compiler/aliasDoesNotDuplicateSignatures.ts @@ -0,0 +1,13 @@ +// @filename: demo.d.ts +declare namespace demoNS { + function f(): void; +} +declare module 'demoModule' { + import alias = demoNS; + export = alias; +} +// @filename: user.ts +import { f } from 'demoModule'; +// Assign an incorrect type here to see the type of 'f'. +let x1: string = demoNS.f; +let x2: string = f; \ No newline at end of file