Skip to content

Commit 4735c00

Browse files
committed
Merge pull request #5420 from weswigham/undefined-unique
Error on redeclarations of undefined
2 parents b1fac59 + cb4a408 commit 4735c00

14 files changed

+148
-1
lines changed

src/compiler/checker.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ namespace ts {
5151
const emitResolver = createResolver();
5252

5353
const undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
54+
undefinedSymbol.declarations = [];
5455
const argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments");
5556

5657
const checker: TypeChecker = {
@@ -234,6 +235,10 @@ namespace ts {
234235
ResolvedReturnType
235236
}
236237

238+
const builtinGlobals: SymbolTable = {
239+
[undefinedSymbol.name]: undefinedSymbol
240+
};
241+
237242
initializeTypeChecker();
238243

239244
return checker;
@@ -360,6 +365,24 @@ namespace ts {
360365
}
361366
}
362367

368+
function addToSymbolTable(target: SymbolTable, source: SymbolTable, message: DiagnosticMessage) {
369+
for (const id in source) {
370+
if (hasProperty(source, id)) {
371+
if (hasProperty(target, id)) {
372+
// Error on redeclarations
373+
forEach(target[id].declarations, addDeclarationDiagnostic(id, message));
374+
}
375+
else {
376+
target[id] = source[id];
377+
}
378+
}
379+
}
380+
381+
function addDeclarationDiagnostic(id: string, message: DiagnosticMessage) {
382+
return (declaration: Declaration) => diagnostics.add(createDiagnosticForNode(declaration, message, id));
383+
}
384+
}
385+
363386
function getSymbolLinks(symbol: Symbol): SymbolLinks {
364387
if (symbol.flags & SymbolFlags.Transient) return <TransientSymbol>symbol;
365388
const id = getSymbolId(symbol);
@@ -15327,10 +15350,12 @@ namespace ts {
1532715350
}
1532815351
});
1532915352

15353+
// Setup global builtins
15354+
addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
15355+
1533015356
getSymbolLinks(undefinedSymbol).type = undefinedType;
1533115357
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
1533215358
getSymbolLinks(unknownSymbol).type = unknownType;
15333-
globals[undefinedSymbol.name] = undefinedSymbol;
1533415359

1533515360
// Initialize special types
1533615361
globalArrayType = <GenericType>getGlobalType("Array", /*arity*/ 1);

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,10 @@
11881188
"category": "Error",
11891189
"code": 2396
11901190
},
1191+
"Declaration name conflicts with built-in global identifier '{0}'.": {
1192+
"category": "Error",
1193+
"code": 2397
1194+
},
11911195
"Duplicate identifier '_this'. Compiler uses variable declaration '_this' to capture 'this' reference.": {
11921196
"category": "Error",
11931197
"code": 2399
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests/cases/compiler/undefinedTypeAssignment1.ts(1,1): error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
2+
3+
4+
==== tests/cases/compiler/undefinedTypeAssignment1.ts (1 errors) ====
5+
type undefined = string;
6+
~~~~~~~~~~~~~~~~~~~~~~~~
7+
!!! error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
8+
function p(undefined = "wat") {
9+
return undefined;
10+
}
11+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//// [undefinedTypeAssignment1.ts]
2+
type undefined = string;
3+
function p(undefined = "wat") {
4+
return undefined;
5+
}
6+
7+
8+
//// [undefinedTypeAssignment1.js]
9+
function p(undefined) {
10+
if (undefined === void 0) { undefined = "wat"; }
11+
return undefined;
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
tests/cases/compiler/undefinedTypeAssignment2.ts(1,5): error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
2+
3+
4+
==== tests/cases/compiler/undefinedTypeAssignment2.ts (1 errors) ====
5+
var undefined = void 0;
6+
~~~~~~~~~
7+
!!! error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [undefinedTypeAssignment2.ts]
2+
var undefined = void 0;
3+
4+
5+
//// [undefinedTypeAssignment2.js]
6+
var undefined = void 0;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
tests/cases/compiler/undefinedTypeAssignment3.ts(1,5): error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
2+
3+
4+
==== tests/cases/compiler/undefinedTypeAssignment3.ts (1 errors) ====
5+
var undefined = null;
6+
~~~~~~~~~
7+
!!! error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//// [undefinedTypeAssignment3.ts]
2+
var undefined = null;
3+
4+
5+
//// [undefinedTypeAssignment3.js]
6+
var undefined = null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tests/cases/compiler/undefinedTypeAssignment4.ts(1,7): error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
2+
tests/cases/compiler/undefinedTypeAssignment4.ts(4,11): error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
3+
tests/cases/compiler/undefinedTypeAssignment4.ts(7,11): error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
4+
5+
6+
==== tests/cases/compiler/undefinedTypeAssignment4.ts (3 errors) ====
7+
class undefined {
8+
~~~~~~~~~
9+
!!! error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
10+
foo: string;
11+
}
12+
interface undefined {
13+
~~~~~~~~~
14+
!!! error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
15+
member: number;
16+
}
17+
namespace undefined {
18+
~~~~~~~~~
19+
!!! error TS2397: Declaration name conflicts with built-in global identifier 'undefined'.
20+
export var x = 42;
21+
}
22+
var x: undefined;
23+
var y: typeof undefined;
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [undefinedTypeAssignment4.ts]
2+
class undefined {
3+
foo: string;
4+
}
5+
interface undefined {
6+
member: number;
7+
}
8+
namespace undefined {
9+
export var x = 42;
10+
}
11+
var x: undefined;
12+
var y: typeof undefined;
13+
14+
15+
//// [undefinedTypeAssignment4.js]
16+
var undefined = (function () {
17+
function undefined() {
18+
}
19+
return undefined;
20+
})();
21+
var undefined;
22+
(function (undefined) {
23+
undefined.x = 42;
24+
})(undefined || (undefined = {}));
25+
var x;
26+
var y;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
type undefined = string;
2+
function p(undefined = "wat") {
3+
return undefined;
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
var undefined = void 0;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
var undefined = null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class undefined {
2+
foo: string;
3+
}
4+
interface undefined {
5+
member: number;
6+
}
7+
namespace undefined {
8+
export var x = 42;
9+
}
10+
var x: undefined;
11+
var y: typeof undefined;

0 commit comments

Comments
 (0)