From 5ed389b6b48edd489e5f185e20eb319fed89422b Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 18 Mar 2016 10:29:01 -0700 Subject: [PATCH] check if import collides with exported local name --- src/compiler/checker.ts | 12 ++++++++--- .../functionAndImportNameConflict.errors.txt | 13 ++++++++++++ .../functionAndImportNameConflict.js | 21 +++++++++++++++++++ .../compiler/functionAndImportNameConflict.ts | 9 ++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/functionAndImportNameConflict.errors.txt create mode 100644 tests/baselines/reference/functionAndImportNameConflict.js create mode 100644 tests/cases/compiler/functionAndImportNameConflict.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 09672f5c09cf4..44f625d9a3829 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -15063,10 +15063,16 @@ namespace ts { const symbol = getSymbolOfNode(node); const target = resolveAlias(symbol); if (target !== unknownSymbol) { + // For external modules symbol represent local symbol for an alias. + // This local symbol will merge any other local declarations (excluding other aliases) + // and symbol.flags will contains combined representation for all merged declaration. + // Based on symbol.flags we can compute a set of excluded meanings (meaning that resolved alias should not have, + // otherwise it will conflict with some local declaration). Note that in addition to normal flags we include matching SymbolFlags.Export* + // in order to prevent collisions with declarations that were exported from the current module (they still contribute to local names). const excludedMeanings = - (symbol.flags & SymbolFlags.Value ? SymbolFlags.Value : 0) | - (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | - (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); + (symbol.flags & (SymbolFlags.Value | SymbolFlags.ExportValue) ? SymbolFlags.Value : 0) | + (symbol.flags & (SymbolFlags.Type | SymbolFlags.ExportType) ? SymbolFlags.Type : 0) | + (symbol.flags & (SymbolFlags.Namespace | SymbolFlags.ExportNamespace) ? SymbolFlags.Namespace : 0); if (target.flags & excludedMeanings) { const message = node.kind === SyntaxKind.ExportSpecifier ? Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : diff --git a/tests/baselines/reference/functionAndImportNameConflict.errors.txt b/tests/baselines/reference/functionAndImportNameConflict.errors.txt new file mode 100644 index 0000000000000..4ca496cfb6531 --- /dev/null +++ b/tests/baselines/reference/functionAndImportNameConflict.errors.txt @@ -0,0 +1,13 @@ +tests/cases/compiler/f2.ts(1,9): error TS2440: Import declaration conflicts with local declaration of 'f' + + +==== tests/cases/compiler/f1.ts (0 errors) ==== + export function f() { + } + +==== tests/cases/compiler/f2.ts (1 errors) ==== + import {f} from './f1'; + ~ +!!! error TS2440: Import declaration conflicts with local declaration of 'f' + export function f() { + } \ No newline at end of file diff --git a/tests/baselines/reference/functionAndImportNameConflict.js b/tests/baselines/reference/functionAndImportNameConflict.js new file mode 100644 index 0000000000000..8391823aa3abc --- /dev/null +++ b/tests/baselines/reference/functionAndImportNameConflict.js @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/functionAndImportNameConflict.ts] //// + +//// [f1.ts] +export function f() { +} + +//// [f2.ts] +import {f} from './f1'; +export function f() { +} + +//// [f1.js] +"use strict"; +function f() { +} +exports.f = f; +//// [f2.js] +"use strict"; +function f() { +} +exports.f = f; diff --git a/tests/cases/compiler/functionAndImportNameConflict.ts b/tests/cases/compiler/functionAndImportNameConflict.ts new file mode 100644 index 0000000000000..9126dd20910fa --- /dev/null +++ b/tests/cases/compiler/functionAndImportNameConflict.ts @@ -0,0 +1,9 @@ +// @module: commonjs +// @filename: f1.ts +export function f() { +} + +// @filename: f2.ts +import {f} from './f1'; +export function f() { +} \ No newline at end of file