Skip to content

Commit f582902

Browse files
committed
Merge pull request #569 from Microsoft/collisions
Report error if exports or require is used for declaration name in external module
2 parents 4381f72 + 7b45cdf commit f582902

File tree

54 files changed

+2402
-156
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2402
-156
lines changed

src/compiler/checker.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4957,6 +4957,7 @@ module ts {
49574957
if (fullTypeCheck) {
49584958
checkCollisionWithCapturedSuperVariable(node, node.name);
49594959
checkCollisionWithCapturedThisVariable(node, node.name);
4960+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
49604961
checkCollisionWithArgumentsInGeneratedCode(node);
49614962
if (program.getCompilerOptions().noImplicitAny && !node.type) {
49624963
switch (node.kind) {
@@ -5699,6 +5700,24 @@ module ts {
56995700
}
57005701
}
57015702

5703+
function checkCollistionWithRequireExportsInGeneratedCode(node: Node, name: Identifier) {
5704+
if (!needCollisionCheckForIdentifier(node, name, "require") && !needCollisionCheckForIdentifier(node, name, "exports")) {
5705+
return;
5706+
}
5707+
5708+
// Uninstantiated modules shouldnt do this check
5709+
if (node.kind === SyntaxKind.ModuleDeclaration && !isInstantiated(node)) {
5710+
return;
5711+
}
5712+
5713+
// In case of variable declaration, node.parent is variable statement so look at the variable statement's parent
5714+
var parent = node.kind === SyntaxKind.VariableDeclaration ? node.parent.parent : node.parent;
5715+
if (parent.kind === SyntaxKind.SourceFile && isExternalModule(<SourceFile>parent)) {
5716+
// If the declaration happens to be in external module, report error that require and exports are reserved keywords
5717+
error(name, Diagnostics.Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module, name.text, name.text);
5718+
}
5719+
}
5720+
57025721
function checkVariableDeclaration(node: VariableDeclaration) {
57035722
checkSourceElement(node.type);
57045723
checkExportsOnMergedDeclarations(node);
@@ -5726,6 +5745,7 @@ module ts {
57265745

57275746
checkCollisionWithCapturedSuperVariable(node, node.name);
57285747
checkCollisionWithCapturedThisVariable(node, node.name);
5748+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
57295749
if (!useTypeFromValueDeclaration) {
57305750
// TypeScript 1.0 spec (April 2014): 5.1
57315751
// Multiple declarations for the same variable name in the same declaration space are permitted,
@@ -5995,6 +6015,7 @@ module ts {
59956015
checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
59966016
checkTypeParameters(node.typeParameters);
59976017
checkCollisionWithCapturedThisVariable(node, node.name);
6018+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
59986019
checkExportsOnMergedDeclarations(node);
59996020
var symbol = getSymbolOfNode(node);
60006021
var type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
@@ -6210,6 +6231,7 @@ module ts {
62106231
}
62116232
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
62126233
checkCollisionWithCapturedThisVariable(node, node.name);
6234+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
62136235
checkExportsOnMergedDeclarations(node);
62146236
var enumSymbol = getSymbolOfNode(node);
62156237
var enumType = getDeclaredTypeOfSymbol(enumSymbol);
@@ -6283,6 +6305,7 @@ module ts {
62836305
function checkModuleDeclaration(node: ModuleDeclaration) {
62846306
if (fullTypeCheck) {
62856307
checkCollisionWithCapturedThisVariable(node, node.name);
6308+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
62866309
checkExportsOnMergedDeclarations(node);
62876310
var symbol = getSymbolOfNode(node);
62886311
if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !isInAmbientContext(node)) {
@@ -6317,6 +6340,7 @@ module ts {
63176340

63186341
function checkImportDeclaration(node: ImportDeclaration) {
63196342
checkCollisionWithCapturedThisVariable(node, node.name);
6343+
checkCollistionWithRequireExportsInGeneratedCode(node, node.name);
63206344
var symbol = getSymbolOfNode(node);
63216345
var target: Symbol;
63226346

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: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//// [tests/cases/compiler/collisionExportsRequireAndAmbientClass.ts] ////
2+
3+
//// [collisionExportsRequireAndAmbientClass_externalmodule.ts]
4+
export declare class require {
5+
}
6+
export declare class exports {
7+
}
8+
declare module m1 {
9+
class require {
10+
}
11+
class exports {
12+
}
13+
}
14+
module m2 {
15+
export declare class require {
16+
}
17+
export declare class exports {
18+
}
19+
}
20+
21+
//// [collisionExportsRequireAndAmbientClass_globalFile.ts]
22+
declare class require {
23+
}
24+
declare class exports {
25+
}
26+
declare module m3 {
27+
class require {
28+
}
29+
class exports {
30+
}
31+
}
32+
module m4 {
33+
export declare class require {
34+
}
35+
export declare class exports {
36+
}
37+
var a = 10;
38+
}
39+
40+
//// [collisionExportsRequireAndAmbientClass_externalmodule.js]
41+
define(["require", "exports"], function (require, exports) {
42+
var m2;
43+
(function (m2) {
44+
})(m2 || (m2 = {}));
45+
});
46+
//// [collisionExportsRequireAndAmbientClass_globalFile.js]
47+
var m4;
48+
(function (m4) {
49+
var a = 10;
50+
})(m4 || (m4 = {}));
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
=== tests/cases/compiler/collisionExportsRequireAndAmbientClass_externalmodule.ts ===
2+
export declare class require {
3+
>require : require
4+
}
5+
export declare class exports {
6+
>exports : exports
7+
}
8+
declare module m1 {
9+
>m1 : typeof m1
10+
11+
class require {
12+
>require : require
13+
}
14+
class exports {
15+
>exports : exports
16+
}
17+
}
18+
module m2 {
19+
>m2 : typeof m2
20+
21+
export declare class require {
22+
>require : require
23+
}
24+
export declare class exports {
25+
>exports : exports
26+
}
27+
}
28+
29+
=== tests/cases/compiler/collisionExportsRequireAndAmbientClass_globalFile.ts ===
30+
declare class require {
31+
>require : require
32+
}
33+
declare class exports {
34+
>exports : exports
35+
}
36+
declare module m3 {
37+
>m3 : typeof m3
38+
39+
class require {
40+
>require : require
41+
}
42+
class exports {
43+
>exports : exports
44+
}
45+
}
46+
module m4 {
47+
>m4 : typeof m4
48+
49+
export declare class require {
50+
>require : require
51+
}
52+
export declare class exports {
53+
>exports : exports
54+
}
55+
var a = 10;
56+
>a : number
57+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//// [tests/cases/compiler/collisionExportsRequireAndAmbientEnum.ts] ////
2+
3+
//// [collisionExportsRequireAndAmbientEnum_externalmodule.ts]
4+
export declare enum require {
5+
_thisVal1,
6+
_thisVal2,
7+
}
8+
export declare enum exports {
9+
_thisVal1,
10+
_thisVal2,
11+
}
12+
declare module m1 {
13+
enum require {
14+
_thisVal1,
15+
_thisVal2,
16+
}
17+
enum exports {
18+
_thisVal1,
19+
_thisVal2,
20+
}
21+
}
22+
module m2 {
23+
export declare enum require {
24+
_thisVal1,
25+
_thisVal2,
26+
}
27+
export declare enum exports {
28+
_thisVal1,
29+
_thisVal2,
30+
}
31+
}
32+
33+
//// [collisionExportsRequireAndAmbientEnum_globalFile.ts]
34+
declare enum require {
35+
_thisVal1,
36+
_thisVal2,
37+
}
38+
declare enum exports {
39+
_thisVal1,
40+
_thisVal2,
41+
}
42+
declare module m3 {
43+
enum require {
44+
_thisVal1,
45+
_thisVal2,
46+
}
47+
enum exports {
48+
_thisVal1,
49+
_thisVal2,
50+
}
51+
}
52+
module m4 {
53+
export declare enum require {
54+
_thisVal1,
55+
_thisVal2,
56+
}
57+
export declare enum exports {
58+
_thisVal1,
59+
_thisVal2,
60+
}
61+
}
62+
63+
//// [collisionExportsRequireAndAmbientEnum_externalmodule.js]
64+
define(["require", "exports"], function (require, exports) {
65+
var m2;
66+
(function (m2) {
67+
})(m2 || (m2 = {}));
68+
});
69+
//// [collisionExportsRequireAndAmbientEnum_globalFile.js]
70+
var m4;
71+
(function (m4) {
72+
})(m4 || (m4 = {}));

0 commit comments

Comments
 (0)