diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9a41b4a89ae..a857c8f60fd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4950,6 +4950,7 @@ module ts { if (fullTypeCheck) { checkCollisionWithCapturedSuperVariable(node, node.name); checkCollisionWithCapturedThisVariable(node, node.name); + checkCollistionWithRequireExportsInGeneratedCode(node, node.name); checkCollisionWithArgumentsInGeneratedCode(node); if (program.getCompilerOptions().noImplicitAny && !node.type) { switch (node.kind) { @@ -5692,6 +5693,24 @@ module ts { } } + function checkCollistionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) { + if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) { + return; + } + + // Uninstantiated modules shouldnt do this check + if (node.kind === SyntaxKind.ModuleDeclaration && !isInstantiated(node)) { + return; + } + + // In case of variable declaration, node.parent is variable statement so look at the variable statement's parent + var parent = node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent; + if (parent.kind === SyntaxKind.SourceFile && isExternalModule(parent)) { + // If the declaration happens to be in external module, report error that require and exports are reserved keywords + error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, name.text, name.text); + } + } + function checkVariableDeclaration(node: VariableDeclaration) { checkSourceElement(node.type); checkExportsOnMergedDeclarations(node); @@ -5719,6 +5738,7 @@ module ts { checkCollisionWithCapturedSuperVariable(node, node.name); checkCollisionWithCapturedThisVariable(node, node.name); + checkCollistionWithRequireExportsInGeneratedCode(node, node.name); if (!useTypeFromValueDeclaration) { // TypeScript 1.0 spec (April 2014): 5.1 // Multiple declarations for the same variable name in the same declaration space are permitted, @@ -5988,6 +6008,7 @@ module ts { checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0); checkTypeParameters(node.typeParameters); checkCollisionWithCapturedThisVariable(node, node.name); + checkCollistionWithRequireExportsInGeneratedCode(node, node.name); checkExportsOnMergedDeclarations(node); var symbol = getSymbolOfNode(node); var type = getDeclaredTypeOfSymbol(symbol); @@ -6203,6 +6224,7 @@ module ts { } checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0); checkCollisionWithCapturedThisVariable(node, node.name); + checkCollistionWithRequireExportsInGeneratedCode(node, node.name); checkExportsOnMergedDeclarations(node); var enumSymbol = getSymbolOfNode(node); var enumType = getDeclaredTypeOfSymbol(enumSymbol); @@ -6276,6 +6298,7 @@ module ts { function checkModuleDeclaration(node: ModuleDeclaration) { if (fullTypeCheck) { checkCollisionWithCapturedThisVariable(node, node.name); + checkCollistionWithRequireExportsInGeneratedCode(node, node.name); checkExportsOnMergedDeclarations(node); var symbol = getSymbolOfNode(node); if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !isInAmbientContext(node)) { @@ -6310,6 +6333,7 @@ module ts { function checkImportDeclaration(node: ImportDeclaration) { checkCollisionWithCapturedThisVariable(node, node.name); + checkCollistionWithRequireExportsInGeneratedCode(node, node.name); var symbol = getSymbolOfNode(node); var target: Symbol; diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 14360f39314..aa1b793f6ac 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -253,6 +253,7 @@ module ts { Import_name_cannot_be_0: { code: 2438, category: DiagnosticCategory.Error, key: "Import name cannot be '{0}'" }, Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: DiagnosticCategory.Error, key: "Import declaration in an ambient external module declaration cannot reference external module through relative external module name." }, Import_declaration_conflicts_with_local_declaration_of_0: { code: 2440, category: DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" }, + Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: { code: 2441, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index adceb133a93..eef8da8c857 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1004,6 +1004,11 @@ "category": "Error", "code": 2440 }, + "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module.": { + "category": "Error", + "code": 2441 + }, + "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", diff --git a/tests/baselines/reference/collisionExportsRequireAndAlias.errors.txt b/tests/baselines/reference/collisionExportsRequireAndAlias.errors.txt new file mode 100644 index 00000000000..2ed2ee5d10e --- /dev/null +++ b/tests/baselines/reference/collisionExportsRequireAndAlias.errors.txt @@ -0,0 +1,20 @@ +==== tests/cases/compiler/collisionExportsRequireAndAlias_file2.ts (2 errors) ==== + import require = require('collisionExportsRequireAndAlias_file1'); // Error + ~~~~~~~ +!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module. + import exports = require('collisionExportsRequireAndAlias_file3333'); // Error + ~~~~~~~ +!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module. + export function foo() { + require.bar(); + } + export function foo2() { + exports.bar2(); + } +==== tests/cases/compiler/collisionExportsRequireAndAlias_file1.ts (0 errors) ==== + export function bar() { + } + +==== tests/cases/compiler/collisionExportsRequireAndAlias_file3333.ts (0 errors) ==== + export function bar2() { + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionExportsRequireAndAlias.js b/tests/baselines/reference/collisionExportsRequireAndAlias.js index 83f23accccf..2e4210f4910 100644 --- a/tests/baselines/reference/collisionExportsRequireAndAlias.js +++ b/tests/baselines/reference/collisionExportsRequireAndAlias.js @@ -1,23 +1,42 @@ -//// [collisionExportsRequireAndAlias.ts] -// TODO: re-enable, fails when run in the browser with full compiler suite, but not when run alone - -////@module: amd -//// @Filename: collisionExportsRequireAndAlias_file1.ts -//export function bar() { -//} - -//// @Filename: collisionExportsRequireAndAlias_file3333.ts -//export function bar2() { -//} -//// @Filename: collisionExportsRequireAndAlias_file2.ts -//import require = require('collisionExportsRequireAndAlias_file1'); // Error -//import exports = require('collisionExportsRequireAndAlias_file3333'); // Error -//export function foo() { -// require.bar(); -//} -//export function foo2() { -// exports.bar2(); -//} +//// [tests/cases/compiler/collisionExportsRequireAndAlias.ts] //// -//// [collisionExportsRequireAndAlias.js] -// TODO: re-enable, fails when run in the browser with full compiler suite, but not when run alone +//// [collisionExportsRequireAndAlias_file1.ts] +export function bar() { +} + +//// [collisionExportsRequireAndAlias_file3333.ts] +export function bar2() { +} +//// [collisionExportsRequireAndAlias_file2.ts] +import require = require('collisionExportsRequireAndAlias_file1'); // Error +import exports = require('collisionExportsRequireAndAlias_file3333'); // Error +export function foo() { + require.bar(); +} +export function foo2() { + exports.bar2(); +} + +//// [collisionExportsRequireAndAlias_file1.js] +define(["require", "exports"], function (require, exports) { + function bar() { + } + exports.bar = bar; +}); +//// [collisionExportsRequireAndAlias_file3333.js] +define(["require", "exports"], function (require, exports) { + function bar2() { + } + exports.bar2 = bar2; +}); +//// [collisionExportsRequireAndAlias_file2.js] +define(["require", "exports", 'collisionExportsRequireAndAlias_file1', 'collisionExportsRequireAndAlias_file3333'], function (require, exports, require, exports) { + function foo() { + require.bar(); + } + exports.foo = foo; + function foo2() { + exports.bar2(); + } + exports.foo2 = foo2; +}); diff --git a/tests/baselines/reference/collisionExportsRequireAndAlias.types b/tests/baselines/reference/collisionExportsRequireAndAlias.types deleted file mode 100644 index 0e13caf3247..00000000000 --- a/tests/baselines/reference/collisionExportsRequireAndAlias.types +++ /dev/null @@ -1,21 +0,0 @@ -=== tests/cases/compiler/collisionExportsRequireAndAlias.ts === -// TODO: re-enable, fails when run in the browser with full compiler suite, but not when run alone -No type information for this code. -No type information for this code.////@module: amd -No type information for this code.//// @Filename: collisionExportsRequireAndAlias_file1.ts -No type information for this code.//export function bar() { -No type information for this code.//} -No type information for this code. -No type information for this code.//// @Filename: collisionExportsRequireAndAlias_file3333.ts -No type information for this code.//export function bar2() { -No type information for this code.//} -No type information for this code.//// @Filename: collisionExportsRequireAndAlias_file2.ts -No type information for this code.//import require = require('collisionExportsRequireAndAlias_file1'); // Error -No type information for this code.//import exports = require('collisionExportsRequireAndAlias_file3333'); // Error -No type information for this code.//export function foo() { -No type information for this code.// require.bar(); -No type information for this code.//} -No type information for this code.//export function foo2() { -No type information for this code.// exports.bar2(); -No type information for this code.//} -No type information for this code. \ No newline at end of file diff --git a/tests/baselines/reference/collisionExportsRequireAndClass.errors.txt b/tests/baselines/reference/collisionExportsRequireAndClass.errors.txt new file mode 100644 index 00000000000..9b90ab50c11 --- /dev/null +++ b/tests/baselines/reference/collisionExportsRequireAndClass.errors.txt @@ -0,0 +1,10 @@ +==== tests/cases/compiler/collisionExportsRequireAndClass.ts (2 errors) ==== + export class require { + ~~~~~~~ +!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module. + } + export class exports { + ~~~~~~~ +!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module. + } + \ No newline at end of file diff --git a/tests/baselines/reference/collisionExportsRequireAndClass.types b/tests/baselines/reference/collisionExportsRequireAndClass.types deleted file mode 100644 index 07debc40147..00000000000 --- a/tests/baselines/reference/collisionExportsRequireAndClass.types +++ /dev/null @@ -1,8 +0,0 @@ -=== tests/cases/compiler/collisionExportsRequireAndClass.ts === -export class require { ->require : require -} -export class exports { ->exports : exports -} - diff --git a/tests/baselines/reference/collisionExportsRequireAndEnum.errors.txt b/tests/baselines/reference/collisionExportsRequireAndEnum.errors.txt new file mode 100644 index 00000000000..0ecd5edef83 --- /dev/null +++ b/tests/baselines/reference/collisionExportsRequireAndEnum.errors.txt @@ -0,0 +1,13 @@ +==== tests/cases/compiler/collisionExportsRequireAndEnum.ts (2 errors) ==== + export enum require { // Error + ~~~~~~~ +!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module. + _thisVal1, + _thisVal2, + } + export enum exports { // Error + ~~~~~~~ +!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module. + _thisVal1, + _thisVal2, + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionExportsRequireAndEnum.types b/tests/baselines/reference/collisionExportsRequireAndEnum.types deleted file mode 100644 index b347b72284b..00000000000 --- a/tests/baselines/reference/collisionExportsRequireAndEnum.types +++ /dev/null @@ -1,19 +0,0 @@ -=== tests/cases/compiler/collisionExportsRequireAndEnum.ts === -export enum require { // Error ->require : require - - _thisVal1, ->_thisVal1 : require - - _thisVal2, ->_thisVal2 : require -} -export enum exports { // Error ->exports : exports - - _thisVal1, ->_thisVal1 : exports - - _thisVal2, ->_thisVal2 : exports -} diff --git a/tests/baselines/reference/collisionExportsRequireAndFunction.errors.txt b/tests/baselines/reference/collisionExportsRequireAndFunction.errors.txt new file mode 100644 index 00000000000..bf35c4ce334 --- /dev/null +++ b/tests/baselines/reference/collisionExportsRequireAndFunction.errors.txt @@ -0,0 +1,12 @@ +==== tests/cases/compiler/collisionExportsRequireAndFunction.ts (2 errors) ==== + export function exports() { + ~~~~~~~ +!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module. + return 1; + } + export function require() { + ~~~~~~~ +!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module. + return "require"; + } + \ No newline at end of file diff --git a/tests/baselines/reference/collisionExportsRequireAndFunction.types b/tests/baselines/reference/collisionExportsRequireAndFunction.types deleted file mode 100644 index 8b90397c6fe..00000000000 --- a/tests/baselines/reference/collisionExportsRequireAndFunction.types +++ /dev/null @@ -1,12 +0,0 @@ -=== tests/cases/compiler/collisionExportsRequireAndFunction.ts === -export function exports() { ->exports : () => number - - return 1; -} -export function require() { ->require : () => string - - return "require"; -} - diff --git a/tests/baselines/reference/collisionExportsRequireAndModule.errors.txt b/tests/baselines/reference/collisionExportsRequireAndModule.errors.txt new file mode 100644 index 00000000000..1fe42767adb --- /dev/null +++ b/tests/baselines/reference/collisionExportsRequireAndModule.errors.txt @@ -0,0 +1,23 @@ +==== tests/cases/compiler/collisionExportsRequireAndModule.ts (2 errors) ==== + export module require { + ~~~~~~~ +!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module. + export interface I { + } + export class C { + } + } + export function foo(): require.I { + return null; + } + export module exports { + ~~~~~~~ +!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module. + export interface I { + } + export class C { + } + } + export function foo2(): exports.I { + return null; + } \ No newline at end of file diff --git a/tests/baselines/reference/collisionExportsRequireAndModule.types b/tests/baselines/reference/collisionExportsRequireAndModule.types deleted file mode 100644 index c462a508d06..00000000000 --- a/tests/baselines/reference/collisionExportsRequireAndModule.types +++ /dev/null @@ -1,35 +0,0 @@ -=== tests/cases/compiler/collisionExportsRequireAndModule.ts === -export module require { ->require : typeof require - - export interface I { ->I : I - } - export class C { ->C : C - } -} -export function foo(): require.I { ->foo : () => require.I ->require : unknown ->I : require.I - - return null; -} -export module exports { ->exports : typeof exports - - export interface I { ->I : I - } - export class C { ->C : C - } -} -export function foo2(): exports.I { ->foo2 : () => exports.I ->exports : unknown ->I : exports.I - - return null; -} diff --git a/tests/baselines/reference/collisionExportsRequireAndVar.errors.txt b/tests/baselines/reference/collisionExportsRequireAndVar.errors.txt new file mode 100644 index 00000000000..127a40f0f0b --- /dev/null +++ b/tests/baselines/reference/collisionExportsRequireAndVar.errors.txt @@ -0,0 +1,10 @@ +==== tests/cases/compiler/collisionExportsRequireAndVar.ts (2 errors) ==== + export function foo() { + } + var exports = 1; + ~~~~~~~ +!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module. + var require = "require"; + ~~~~~~~ +!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module. + \ No newline at end of file diff --git a/tests/baselines/reference/collisionExportsRequireAndVar.types b/tests/baselines/reference/collisionExportsRequireAndVar.types deleted file mode 100644 index 656c705aa23..00000000000 --- a/tests/baselines/reference/collisionExportsRequireAndVar.types +++ /dev/null @@ -1,10 +0,0 @@ -=== tests/cases/compiler/collisionExportsRequireAndVar.ts === -export function foo() { ->foo : () => void -} -var exports = 1; ->exports : number - -var require = "require"; ->require : string - diff --git a/tests/cases/compiler/collisionExportsRequireAndAlias.ts b/tests/cases/compiler/collisionExportsRequireAndAlias.ts index 4c249d83a0c..b79da28f66b 100644 --- a/tests/cases/compiler/collisionExportsRequireAndAlias.ts +++ b/tests/cases/compiler/collisionExportsRequireAndAlias.ts @@ -1,19 +1,17 @@ -// TODO: re-enable, fails when run in the browser with full compiler suite, but not when run alone +//@module: amd +// @Filename: collisionExportsRequireAndAlias_file1.ts +export function bar() { +} -////@module: amd -//// @Filename: collisionExportsRequireAndAlias_file1.ts -//export function bar() { -//} - -//// @Filename: collisionExportsRequireAndAlias_file3333.ts -//export function bar2() { -//} -//// @Filename: collisionExportsRequireAndAlias_file2.ts -//import require = require('collisionExportsRequireAndAlias_file1'); // Error -//import exports = require('collisionExportsRequireAndAlias_file3333'); // Error -//export function foo() { -// require.bar(); -//} -//export function foo2() { -// exports.bar2(); -//} \ No newline at end of file +// @Filename: collisionExportsRequireAndAlias_file3333.ts +export function bar2() { +} +// @Filename: collisionExportsRequireAndAlias_file2.ts +import require = require('collisionExportsRequireAndAlias_file1'); // Error +import exports = require('collisionExportsRequireAndAlias_file3333'); // Error +export function foo() { + require.bar(); +} +export function foo2() { + exports.bar2(); +} \ No newline at end of file