From b5f81f9eded21079d2a7575085080875f40ec1bf Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 5 Jun 2017 18:39:32 -0700 Subject: [PATCH] Fix emit when type import merges with local value --- Jakefile.js | 2 +- src/compiler/checker.ts | 17 ++++++++++++--- .../symbolMergeValueAndImportedType.js | 17 +++++++++++++++ .../symbolMergeValueAndImportedType.symbols | 17 +++++++++++++++ .../symbolMergeValueAndImportedType.types | 21 +++++++++++++++++++ .../symbolMergeValueAndImportedType.ts | 9 ++++++++ 6 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/symbolMergeValueAndImportedType.js create mode 100644 tests/baselines/reference/symbolMergeValueAndImportedType.symbols create mode 100644 tests/baselines/reference/symbolMergeValueAndImportedType.types create mode 100644 tests/cases/compiler/symbolMergeValueAndImportedType.ts diff --git a/Jakefile.js b/Jakefile.js index 439fced0720..ce173525a84 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -925,7 +925,7 @@ function runConsoleTests(defaultReporter, runInParallel) { } } -var testTimeout = 20000; +var testTimeout = 22000; desc("Runs all the tests in parallel using the built run.js file. Optional arguments are: t[ests]=category1|category2|... d[ebug]=true."); task("runtests-parallel", ["build-rules", "tests", builtLocalDirectory], function () { runConsoleTests('min', /*runInParallel*/ true); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1ab88880d9e..62bfbe0df6c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1473,8 +1473,15 @@ namespace ts { } } + /** + * Indicates that a symbol is an alias that does not merge with a local declaration. + */ + function isNonLocalAlias(symbol: Symbol, excludes = SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace) { + return symbol && (symbol.flags & (SymbolFlags.Alias | excludes)) === SymbolFlags.Alias; + } + function resolveSymbol(symbol: Symbol, dontResolveAlias?: boolean): Symbol { - const shouldResolve = !dontResolveAlias && symbol && symbol.flags & SymbolFlags.Alias && !(symbol.flags & (SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace)); + const shouldResolve = !dontResolveAlias && isNonLocalAlias(symbol); return shouldResolve ? resolveAlias(symbol) : symbol; } @@ -12015,7 +12022,9 @@ namespace ts { return getTypeOfSymbol(symbol); } - if (symbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { + // We should only mark aliases as referenced if there isn't a local value declaration + // for the symbol. + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value) && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) { markAliasSymbolAsReferenced(symbol); } @@ -22864,7 +22873,9 @@ namespace ts { node = getParseTreeNode(node, isIdentifier); if (node) { const symbol = getReferencedValueSymbol(node); - if (symbol && symbol.flags & SymbolFlags.Alias) { + // We should only get the declaration of an alias if there isn't a local value + // declaration for the symbol + if (isNonLocalAlias(symbol, /*excludes*/ SymbolFlags.Value)) { return getDeclarationOfAliasSymbol(symbol); } } diff --git a/tests/baselines/reference/symbolMergeValueAndImportedType.js b/tests/baselines/reference/symbolMergeValueAndImportedType.js new file mode 100644 index 00000000000..70da47268d5 --- /dev/null +++ b/tests/baselines/reference/symbolMergeValueAndImportedType.js @@ -0,0 +1,17 @@ +//// [tests/cases/compiler/symbolMergeValueAndImportedType.ts] //// + +//// [main.ts] +import { X } from "./other"; +const X = 42; +console.log('X is ' + X); +//// [other.ts] +export type X = {}; + +//// [other.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const X = 42; +console.log('X is ' + X); diff --git a/tests/baselines/reference/symbolMergeValueAndImportedType.symbols b/tests/baselines/reference/symbolMergeValueAndImportedType.symbols new file mode 100644 index 00000000000..7e1422faa46 --- /dev/null +++ b/tests/baselines/reference/symbolMergeValueAndImportedType.symbols @@ -0,0 +1,17 @@ +=== tests/cases/compiler/main.ts === +import { X } from "./other"; +>X : Symbol(X, Decl(main.ts, 0, 8), Decl(main.ts, 1, 5)) + +const X = 42; +>X : Symbol(X, Decl(main.ts, 0, 8), Decl(main.ts, 1, 5)) + +console.log('X is ' + X); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>X : Symbol(X, Decl(main.ts, 0, 8), Decl(main.ts, 1, 5)) + +=== tests/cases/compiler/other.ts === +export type X = {}; +>X : Symbol(X, Decl(other.ts, 0, 0)) + diff --git a/tests/baselines/reference/symbolMergeValueAndImportedType.types b/tests/baselines/reference/symbolMergeValueAndImportedType.types new file mode 100644 index 00000000000..a7dc72ab0b6 --- /dev/null +++ b/tests/baselines/reference/symbolMergeValueAndImportedType.types @@ -0,0 +1,21 @@ +=== tests/cases/compiler/main.ts === +import { X } from "./other"; +>X : 42 + +const X = 42; +>X : 42 +>42 : 42 + +console.log('X is ' + X); +>console.log('X is ' + X) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>'X is ' + X : string +>'X is ' : "X is " +>X : 42 + +=== tests/cases/compiler/other.ts === +export type X = {}; +>X : X + diff --git a/tests/cases/compiler/symbolMergeValueAndImportedType.ts b/tests/cases/compiler/symbolMergeValueAndImportedType.ts new file mode 100644 index 00000000000..4779ff22e9d --- /dev/null +++ b/tests/cases/compiler/symbolMergeValueAndImportedType.ts @@ -0,0 +1,9 @@ +// @target: es2015 +// @module: commonjs +// @lib: es2015,dom +// @filename: main.ts +import { X } from "./other"; +const X = 42; +console.log('X is ' + X); +// @filename: other.ts +export type X = {}; \ No newline at end of file