Skip to content

Commit a87a779

Browse files
committed
Report error if exports or require is used for declaration name in external module
Fixes #63
1 parent 655039c commit a87a779

17 files changed

+175
-145
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4950,6 +4950,7 @@ module ts {
49504950
if (fullTypeCheck) {
49514951
checkCollisionWithCapturedSuperVariable(node, node.name);
49524952
checkCollisionWithCapturedThisVariable(node, node.name);
4953+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
49534954
checkCollisionWithArgumentsInGeneratedCode(node);
49544955
if (program.getCompilerOptions().noImplicitAny && !node.type) {
49554956
switch (node.kind) {
@@ -5692,6 +5693,24 @@ module ts {
56925693
}
56935694
}
56945695

5696+
function checkCollistionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) {
5697+
if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
5698+
return;
5699+
}
5700+
5701+
// Uninstantiated modules shouldnt do this check
5702+
if (node.kind === SyntaxKind.ModuleDeclaration && !isInstantiated(node)) {
5703+
return;
5704+
}
5705+
5706+
// In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
5707+
var parent = node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent;
5708+
if (parent.kind === SyntaxKind.SourceFile && isExternalModule(<SourceFile>parent)) {
5709+
// If the declaration happens to be in external module, report error that require and exports are reserved keywords
5710+
error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, name.text, name.text);
5711+
}
5712+
}
5713+
56955714
function checkVariableDeclaration(node: VariableDeclaration) {
56965715
checkSourceElement(node.type);
56975716
checkExportsOnMergedDeclarations(node);
@@ -5719,6 +5738,7 @@ module ts {
57195738

57205739
checkCollisionWithCapturedSuperVariable(node, node.name);
57215740
checkCollisionWithCapturedThisVariable(node, node.name);
5741+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
57225742
if (!useTypeFromValueDeclaration) {
57235743
// TypeScript 1.0 spec (April 2014): 5.1
57245744
// Multiple declarations for the same variable name in the same declaration space are permitted,
@@ -5988,6 +6008,7 @@ module ts {
59886008
checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
59896009
checkTypeParameters(node.typeParameters);
59906010
checkCollisionWithCapturedThisVariable(node, node.name);
6011+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
59916012
checkExportsOnMergedDeclarations(node);
59926013
var symbol = getSymbolOfNode(node);
59936014
var type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
@@ -6203,6 +6224,7 @@ module ts {
62036224
}
62046225
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
62056226
checkCollisionWithCapturedThisVariable(node, node.name);
6227+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
62066228
checkExportsOnMergedDeclarations(node);
62076229
var enumSymbol = getSymbolOfNode(node);
62086230
var enumType = getDeclaredTypeOfSymbol(enumSymbol);
@@ -6276,6 +6298,7 @@ module ts {
62766298
function checkModuleDeclaration(node: ModuleDeclaration) {
62776299
if (fullTypeCheck) {
62786300
checkCollisionWithCapturedThisVariable(node, node.name);
6301+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
62796302
checkExportsOnMergedDeclarations(node);
62806303
var symbol = getSymbolOfNode(node);
62816304
if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !isInAmbientContext(node)) {
@@ -6310,6 +6333,7 @@ module ts {
63106333

63116334
function checkImportDeclaration(node: ImportDeclaration) {
63126335
checkCollisionWithCapturedThisVariable(node, node.name);
6336+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
63136337
var symbol = getSymbolOfNode(node);
63146338
var target: Symbol;
63156339

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ module ts {
253253
Import_name_cannot_be_0: { code: 2438, category: DiagnosticCategory.Error, key: "Import name cannot be '{0}'" },
254254
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." },
255255
Import_declaration_conflicts_with_local_declaration_of_0: { code: 2440, category: DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" },
256+
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." },
256257
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
257258
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}'." },
258259
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}'." },

src/compiler/diagnosticMessages.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,11 @@
10041004
"category": "Error",
10051005
"code": 2440
10061006
},
1007+
"Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module.": {
1008+
"category": "Error",
1009+
"code": 2441
1010+
},
1011+
10071012

10081013
"Import declaration '{0}' is using private name '{1}'.": {
10091014
"category": "Error",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
==== tests/cases/compiler/collisionExportsRequireAndAlias_file2.ts (2 errors) ====
2+
import require = require('collisionExportsRequireAndAlias_file1'); // Error
3+
~~~~~~~
4+
!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module.
5+
import exports = require('collisionExportsRequireAndAlias_file3333'); // Error
6+
~~~~~~~
7+
!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module.
8+
export function foo() {
9+
require.bar();
10+
}
11+
export function foo2() {
12+
exports.bar2();
13+
}
14+
==== tests/cases/compiler/collisionExportsRequireAndAlias_file1.ts (0 errors) ====
15+
export function bar() {
16+
}
17+
18+
==== tests/cases/compiler/collisionExportsRequireAndAlias_file3333.ts (0 errors) ====
19+
export function bar2() {
20+
}
Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
1-
//// [collisionExportsRequireAndAlias.ts]
2-
// TODO: re-enable, fails when run in the browser with full compiler suite, but not when run alone
3-
4-
////@module: amd
5-
//// @Filename: collisionExportsRequireAndAlias_file1.ts
6-
//export function bar() {
7-
//}
8-
9-
//// @Filename: collisionExportsRequireAndAlias_file3333.ts
10-
//export function bar2() {
11-
//}
12-
//// @Filename: collisionExportsRequireAndAlias_file2.ts
13-
//import require = require('collisionExportsRequireAndAlias_file1'); // Error
14-
//import exports = require('collisionExportsRequireAndAlias_file3333'); // Error
15-
//export function foo() {
16-
// require.bar();
17-
//}
18-
//export function foo2() {
19-
// exports.bar2();
20-
//}
1+
//// [tests/cases/compiler/collisionExportsRequireAndAlias.ts] ////
212

22-
//// [collisionExportsRequireAndAlias.js]
23-
// TODO: re-enable, fails when run in the browser with full compiler suite, but not when run alone
3+
//// [collisionExportsRequireAndAlias_file1.ts]
4+
export function bar() {
5+
}
6+
7+
//// [collisionExportsRequireAndAlias_file3333.ts]
8+
export function bar2() {
9+
}
10+
//// [collisionExportsRequireAndAlias_file2.ts]
11+
import require = require('collisionExportsRequireAndAlias_file1'); // Error
12+
import exports = require('collisionExportsRequireAndAlias_file3333'); // Error
13+
export function foo() {
14+
require.bar();
15+
}
16+
export function foo2() {
17+
exports.bar2();
18+
}
19+
20+
//// [collisionExportsRequireAndAlias_file1.js]
21+
define(["require", "exports"], function (require, exports) {
22+
function bar() {
23+
}
24+
exports.bar = bar;
25+
});
26+
//// [collisionExportsRequireAndAlias_file3333.js]
27+
define(["require", "exports"], function (require, exports) {
28+
function bar2() {
29+
}
30+
exports.bar2 = bar2;
31+
});
32+
//// [collisionExportsRequireAndAlias_file2.js]
33+
define(["require", "exports", 'collisionExportsRequireAndAlias_file1', 'collisionExportsRequireAndAlias_file3333'], function (require, exports, require, exports) {
34+
function foo() {
35+
require.bar();
36+
}
37+
exports.foo = foo;
38+
function foo2() {
39+
exports.bar2();
40+
}
41+
exports.foo2 = foo2;
42+
});

tests/baselines/reference/collisionExportsRequireAndAlias.types

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
==== tests/cases/compiler/collisionExportsRequireAndClass.ts (2 errors) ====
2+
export class require {
3+
~~~~~~~
4+
!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module.
5+
}
6+
export class exports {
7+
~~~~~~~
8+
!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module.
9+
}
10+

tests/baselines/reference/collisionExportsRequireAndClass.types

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
==== tests/cases/compiler/collisionExportsRequireAndEnum.ts (2 errors) ====
2+
export enum require { // Error
3+
~~~~~~~
4+
!!! Duplicate identifier 'require'. Compiler reserves name 'require' in top level scope of an external module.
5+
_thisVal1,
6+
_thisVal2,
7+
}
8+
export enum exports { // Error
9+
~~~~~~~
10+
!!! Duplicate identifier 'exports'. Compiler reserves name 'exports' in top level scope of an external module.
11+
_thisVal1,
12+
_thisVal2,
13+
}

tests/baselines/reference/collisionExportsRequireAndEnum.types

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)