From 3da5f1ef6f8c37faa0c333b8f2a9d6603c128223 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sat, 26 Jul 2014 08:13:52 -0700 Subject: [PATCH] Error when importing shadowed internal module. Fixes #73. --- src/compiler/checker.ts | 19 ++++++++++++++++--- .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 ++++ ...WithClassNotReferencingInstance.errors.txt | 16 ++++++++++++++++ ...tedModuleNotReferencingInstance.errors.txt | 13 +++++++++++++ ...WithClassNotReferencingInstance.errors.txt | 15 +++++++++++++++ .../reboundIdentifierOnImportAlias.errors.txt | 10 ++++++++++ .../shadowedInternalModule.errors.txt | 4 +++- 8 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/internalImportInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt create mode 100644 tests/baselines/reference/internalImportInstantiatedModuleNotReferencingInstance.errors.txt create mode 100644 tests/baselines/reference/internalImportUnInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt create mode 100644 tests/baselines/reference/reboundIdentifierOnImportAlias.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9f1b0abaecfb4..e8be6b02403ae 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5720,6 +5720,13 @@ module ts { checkSourceElement(node.body); } + function getFirstIdentifier(node: EntityName): Identifier { + while (node.kind === SyntaxKind.QualifiedName) { + node = (node).left; + } + return node; + } + function checkImportDeclaration(node: ImportDeclaration) { checkCollisionWithCapturedThisVariable(node, node.name); var symbol = getSymbolOfNode(node); @@ -5730,8 +5737,15 @@ module ts { // Import declaration for an internal module if (target !== unknownSymbol) { if (target.flags & SymbolFlags.Value) { - // Target is a value symbol, check that it can be evaluated as an expression - checkExpression(node.entityName); + // Target is a value symbol, check that it is not hidden by a local declaration with the same name and + // ensure it can be evaluated as an expression + var moduleName = getFirstIdentifier(node.entityName); + if (resolveEntityName(node, moduleName, SymbolFlags.Value | SymbolFlags.Namespace).flags & SymbolFlags.Namespace) { + checkExpression(node.entityName); + } + else { + error(moduleName, Diagnostics.Module_0_is_hidden_by_a_local_declaration_with_the_same_name, identifierToString(moduleName)); + } } if (target.flags & SymbolFlags.Type) { checkTypeNameIsReserved(node.name, Diagnostics.Import_name_cannot_be_0); @@ -5741,7 +5755,6 @@ module ts { else { // Import declaration for an external module if (node.parent.kind === SyntaxKind.SourceFile) { - // Parent is a source file, check that external modules are enabled target = resolveImport(symbol); } else if (node.parent.kind === SyntaxKind.ModuleBlock && (node.parent.parent).name.kind === SyntaxKind.StringLiteral) { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index b243ef02d1d2f..19040501a427e 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -293,6 +293,7 @@ module ts { A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged: { code: -9999999, category: DiagnosticCategory.Error, key: "A module declaration cannot be located prior to a class or function with which it is merged" }, Cannot_compile_external_modules_unless_the_module_flag_is_provided: { code: -9999999, category: DiagnosticCategory.Error, key: "Cannot compile external modules unless the '--module' flag is provided." }, Import_declaration_conflicts_with_local_declaration_of_0: { code: -9999999, category: DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" }, + Module_0_is_hidden_by_a_local_declaration_with_the_same_name: { code: -9999999, category: DiagnosticCategory.Error, key: "Module '{0}' is hidden by a local declaration with the same name" }, Filename_0_differs_from_already_included_filename_1_only_in_casing: { code: -9999999, category: DiagnosticCategory.Error, key: "Filename '{0}' differs from already included filename '{1}' only in casing" }, Argument_for_module_option_must_be_commonjs_or_amd: { code: -9999999, category: DiagnosticCategory.Error, key: "Argument for '--module' option must be 'commonjs' or 'amd'." }, Argument_for_target_option_must_be_es3_or_es5: { code: -9999999, category: DiagnosticCategory.Error, key: "Argument for '--target' option must be 'es3' or 'es5'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c088fd4eddc86..d1ad50ab4770d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1193,6 +1193,10 @@ "category": "Error", "code": -9999999 }, + "Module '{0}' is hidden by a local declaration with the same name": { + "category": "Error", + "code": -9999999 + }, "Filename '{0}' differs from already included filename '{1}' only in casing": { "category": "Error", "code": -9999999 diff --git a/tests/baselines/reference/internalImportInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt b/tests/baselines/reference/internalImportInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt new file mode 100644 index 0000000000000..64d2e92bdd468 --- /dev/null +++ b/tests/baselines/reference/internalImportInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt @@ -0,0 +1,16 @@ +==== tests/cases/compiler/internalImportInstantiatedModuleMergedWithClassNotReferencingInstance.ts (1 errors) ==== + class A { + aProp: string; + } + module A { + export interface X { s: string } + export var a = 10; + } + + module B { + var A = 1; + import Y = A; + ~ +!!! Module 'A' is hidden by a local declaration with the same name + } + \ No newline at end of file diff --git a/tests/baselines/reference/internalImportInstantiatedModuleNotReferencingInstance.errors.txt b/tests/baselines/reference/internalImportInstantiatedModuleNotReferencingInstance.errors.txt new file mode 100644 index 0000000000000..3cbb49c6809e4 --- /dev/null +++ b/tests/baselines/reference/internalImportInstantiatedModuleNotReferencingInstance.errors.txt @@ -0,0 +1,13 @@ +==== tests/cases/compiler/internalImportInstantiatedModuleNotReferencingInstance.ts (1 errors) ==== + module A { + export interface X { s: string } + export var a = 10; + } + + module B { + var A = 1; + import Y = A; + ~ +!!! Module 'A' is hidden by a local declaration with the same name + } + \ No newline at end of file diff --git a/tests/baselines/reference/internalImportUnInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt b/tests/baselines/reference/internalImportUnInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt new file mode 100644 index 0000000000000..3e50f2be298cf --- /dev/null +++ b/tests/baselines/reference/internalImportUnInstantiatedModuleMergedWithClassNotReferencingInstance.errors.txt @@ -0,0 +1,15 @@ +==== tests/cases/compiler/internalImportUnInstantiatedModuleMergedWithClassNotReferencingInstance.ts (1 errors) ==== + class A { + aProp: string; + } + module A { + export interface X { s: string } + } + + module B { + var A = 1; + import Y = A; + ~ +!!! Module 'A' is hidden by a local declaration with the same name + } + \ No newline at end of file diff --git a/tests/baselines/reference/reboundIdentifierOnImportAlias.errors.txt b/tests/baselines/reference/reboundIdentifierOnImportAlias.errors.txt new file mode 100644 index 0000000000000..4a26641b0376e --- /dev/null +++ b/tests/baselines/reference/reboundIdentifierOnImportAlias.errors.txt @@ -0,0 +1,10 @@ +==== tests/cases/compiler/reboundIdentifierOnImportAlias.ts (1 errors) ==== + module Foo { + export var x = "hello"; + } + module Bar { + var Foo = 1; + import F = Foo; + ~~~ +!!! Module 'Foo' is hidden by a local declaration with the same name + } \ No newline at end of file diff --git a/tests/baselines/reference/shadowedInternalModule.errors.txt b/tests/baselines/reference/shadowedInternalModule.errors.txt index c46bac9a0682f..b702a93a0ac81 100644 --- a/tests/baselines/reference/shadowedInternalModule.errors.txt +++ b/tests/baselines/reference/shadowedInternalModule.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts (1 errors) ==== +==== tests/cases/conformance/internalModules/importDeclarations/shadowedInternalModule.ts (2 errors) ==== // all errors imported modules conflict with local variables module A { @@ -12,6 +12,8 @@ module B { var A = { x: 0, y: 0 }; import Point = A; + ~ +!!! Module 'A' is hidden by a local declaration with the same name } module X {