Skip to content

Commit 39ba2ed

Browse files
committed
exported symbols now don't take the exclusive slot in locals
1 parent 2b8f04a commit 39ba2ed

10 files changed

+239
-112
lines changed

src/compiler/binder.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,40 +125,47 @@ module ts {
125125
function declareModuleMember(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) {
126126
// Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue,
127127
// ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set
128-
// on it. There are 2 main reasons:
129-
//
130-
// 1. We treat locals and exports of the same name as mutually exclusive within a container.
131-
// That means the binder will issue a Duplicate Identifier error if you mix locals and exports
132-
// with the same name in the same container.
133-
// TODO: Make this a more specific error and decouple it from the exclusion logic.
128+
// on it. Reasons:
129+
// 1. During name resolution i.e for types we need to distingush local and exported symbols.
130+
// All members are added to the exported one so local should never be returned.
134131
// 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol,
135132
// but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way
136133
// when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope.
134+
// Exported members will share local symbol with non-exported members
137135
var exportKind = 0;
138-
var exportExcludes = 0;
139136
if (symbolKind & SymbolFlags.Value) {
140137
exportKind |= SymbolFlags.ExportValue;
141-
exportExcludes |= SymbolFlags.Value;
142138
}
143139
if (symbolKind & SymbolFlags.Type) {
144140
exportKind |= SymbolFlags.ExportType;
145-
exportExcludes |= SymbolFlags.Type;
146141
}
147142
if (symbolKind & SymbolFlags.Namespace) {
148143
exportKind |= SymbolFlags.ExportNamespace;
149-
exportExcludes |= SymbolFlags.Namespace;
150144
}
151145
if (node.flags & NodeFlags.Export || (node.kind !== SyntaxKind.ImportDeclaration && isAmbientContext(container))) {
152146
if (exportKind) {
153-
var local = declareSymbol(container.locals, undefined, node, exportKind, exportExcludes);
154-
local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
147+
var exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
148+
var localSymbol = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes);
149+
node.symbol = exportSymbol;
150+
// export function foo(); // 1
151+
// export function foo() {} // 2
152+
// at (1) we'll create two symbols: local and exported and link then together
153+
// at (2) the same symbols will be returned as exported and local.
154+
// make sure that local symbol is added to the list of local symbols just once.
155+
if (!localSymbol.exportSymbol) {
156+
if (!exportSymbol.localSymbols) {
157+
exportSymbol.localSymbols = [];
158+
}
159+
exportSymbol.localSymbols.push(localSymbol);
160+
}
161+
localSymbol.exportSymbol = exportSymbol;
155162
}
156163
else {
157164
declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes);
158165
}
159166
}
160167
else {
161-
declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes | exportKind);
168+
declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes);
162169
}
163170
}
164171

src/compiler/checker.ts

Lines changed: 191 additions & 64 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ module ts {
131131
A_signature_with_an_implementation_cannot_use_a_string_literal_type: { code: 2163, category: DiagnosticCategory.Error, key: "A signature with an implementation cannot use a string literal type." },
132132
Interface_0_cannot_simultaneously_extend_types_1_and_2_Colon: { code: 2189, category: DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}':" },
133133
Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: { code: 2190, category: DiagnosticCategory.Error, key: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it." },
134+
All_declarations_of_merged_declaration_0_must_be_exported_or_not_exported: { code: 2192, category: DiagnosticCategory.Error, key: "All declarations of merged declaration '{0}' must be exported or not exported." },
134135
super_cannot_be_referenced_in_constructor_arguments: { code: 2193, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in constructor arguments." },
135136
Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2194, category: DiagnosticCategory.Error, key: "Return type of constructor signature must be assignable to the instance type of the class" },
136137
Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2196, category: DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." },

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,10 @@
518518
"category": "Error",
519519
"code": 2190
520520
},
521+
"All declarations of merged declaration '{0}' must be exported or not exported.": {
522+
"category": "Error",
523+
"code": 2192
524+
},
521525
"'super' cannot be referenced in constructor arguments.":{
522526
"category": "Error",
523527
"code": 2193

src/compiler/types.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,9 @@ module ts {
648648
IndexSignature = 0x00020000, // Index signature
649649
TypeParameter = 0x00040000, // Type parameter
650650

651-
// Export markers (see comment in declareModuleMember in binder)
652-
ExportValue = 0x00080000, // Exported value marker
653-
ExportType = 0x00100000, // Exported type marker
654-
ExportNamespace = 0x00200000, // Exported namespace marker
651+
ExportValue = 0x00080000, // Exported value marker
652+
ExportType = 0x00100000, // Exported type marker
653+
ExportNamespace = 0x00200000, // Exported namespace marker
655654

656655
Import = 0x00400000, // Import
657656
Instantiated = 0x00800000, // Instantiated symbol
@@ -707,7 +706,8 @@ module ts {
707706
exports?: SymbolTable; // Module exports
708707
exportSymbol?: Symbol; // Exported symbol associated with this symbol
709708
exportAssignSymbol?: Symbol; // Symbol exported from external module
710-
valueDeclaration?: Declaration // First value declaration of the symbol
709+
valueDeclaration?: Declaration;// First value declaration of the symbol
710+
localSymbols?: Symbol[]; // List of local symbols that contribute to the export symbol
711711
}
712712

713713
export interface SymbolLinks {

tests/baselines/reference/anonymousModules.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
var bar = 2;
2626
~~~
27-
!!! Duplicate identifier 'bar'.
27+
!!! All declarations of merged declaration 'bar' must be exported or not exported.
2828

2929
module {
3030
~

tests/baselines/reference/duplicateSymbolsExportMatching.errors.txt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
interface I { }
2626
export interface I { } // error
2727
~
28-
!!! Duplicate identifier 'I'.
28+
!!! All declarations of merged declaration 'I' must be exported or not exported.
2929
export interface E { }
3030
interface E { } // error
3131
~
32-
!!! Duplicate identifier 'E'.
32+
!!! All declarations of merged declaration 'E' must be exported or not exported.
3333
}
3434

3535
// Should report error only once for instantiated module
@@ -39,7 +39,7 @@
3939
}
4040
export module inst { // one error
4141
~~~~
42-
!!! Duplicate identifier 'inst'.
42+
!!! All declarations of merged declaration 'inst' must be exported or not exported.
4343
var t;
4444
}
4545
}
@@ -49,28 +49,28 @@
4949
var v: string;
5050
export var v: string; // one error (visibility)
5151
~
52-
!!! Duplicate identifier 'v'.
52+
!!! All declarations of merged declaration 'v' must be exported or not exported.
5353
var w: number;
5454
export var w: string; // two errors (visibility and type mismatch)
5555
~
56-
!!! Duplicate identifier 'w'.
56+
!!! All declarations of merged declaration 'w' must be exported or not exported.
5757
}
5858

5959
module M {
6060
module F {
61+
~
62+
!!! A module declaration cannot be located prior to a class or function with which it is merged
6163
var t;
6264
}
6365
export function F() { } // Only one error for duplicate identifier (don't consider visibility)
64-
~
65-
!!! Duplicate identifier 'F'.
6666
}
6767

6868
module M {
6969
class C { }
7070
module C { }
7171
export module C { // Two visibility errors (one for the clodule symbol, and one for the merged container symbol)
7272
~
73-
!!! Duplicate identifier 'C'.
73+
!!! All declarations of merged declaration 'C' must be exported or not exported.
7474
var t;
7575
}
7676
}
@@ -79,4 +79,4 @@
7979
interface D { }
8080
export interface D { }
8181
~
82-
!!! Duplicate identifier 'D'.
82+
!!! All declarations of merged declaration 'D' must be exported or not exported.

tests/baselines/reference/functionOverloadErrors.errors.txt

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
==== tests/cases/conformance/functions/functionOverloadErrors.ts (19 errors) ====
1+
==== tests/cases/conformance/functions/functionOverloadErrors.ts (14 errors) ====
22
//Function overload signature with initializer
33
function fn1(x = 3);
44
~~~~~
@@ -86,26 +86,16 @@
8686
//Function overloads with differing export
8787
module M {
8888
export function fn1();
89-
~~~~~~~~~~~~~~~~~~~~~~
90-
!!! Function implementation expected.
89+
~~~
90+
!!! Overload signatures must all be exported or not exported.
9191
function fn1(n: string);
92-
~~~~~~~~~~~~~~~~~~~~~~~~
93-
!!! Function implementation expected.
94-
~~~
95-
!!! Duplicate identifier 'fn1'.
9692
function fn1() { }
97-
~~~
98-
!!! Duplicate identifier 'fn1'.
9993

10094
function fn2(n: string);
101-
~~~~~~~~~~~~~~~~~~~~~~~~
102-
!!! Function implementation expected.
95+
~~~
96+
!!! Overload signatures must all be exported or not exported.
10397
export function fn2();
104-
~~~
105-
!!! Duplicate identifier 'fn2'.
10698
export function fn2() { }
107-
~~~
108-
!!! Duplicate identifier 'fn2'.
10999
}
110100

111101
//Function overloads with differing ambience

tests/baselines/reference/multivar.errors.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
declare var d1, d2;
2323
var b2;
2424
~~
25-
!!! Duplicate identifier 'b2'.
25+
!!! All declarations of merged declaration 'b2' must be exported or not exported.
2626

2727
declare var v1;
2828
}

tests/baselines/reference/overloadModifiersMustAgree.errors.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
==== tests/cases/compiler/overloadModifiersMustAgree.ts (5 errors) ====
1+
==== tests/cases/compiler/overloadModifiersMustAgree.ts (4 errors) ====
22
class baz {
33
public foo();
44
~~~
@@ -10,10 +10,8 @@
1010
~~~
1111
!!! Overload signatures must all be ambient or non-ambient.
1212
export function bar(s: string);
13-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14-
!!! Function implementation expected.
1513
~~~
16-
!!! Duplicate identifier 'bar'.
14+
!!! Overload signatures must all be exported or not exported.
1715
function bar(s?: string) { }
1816

1917
interface I {

0 commit comments

Comments
 (0)