@@ -609,10 +609,11 @@ export class Program extends DiagnosticEmitter {
609
609
}
610
610
611
611
/** Gets the (possibly merged) program element linked to the specified declaration. */
612
- getElementByDeclaration ( declaration : DeclarationStatement ) : DeclaredElement {
612
+ getElementByDeclaration ( declaration : DeclarationStatement ) : DeclaredElement | null {
613
613
var elementsByDeclaration = this . elementsByDeclaration ;
614
- assert ( elementsByDeclaration . has ( declaration ) ) ;
615
- return elementsByDeclaration . get ( declaration ) ! ;
614
+ return elementsByDeclaration . has ( declaration )
615
+ ? elementsByDeclaration . get ( declaration )
616
+ : null ;
616
617
}
617
618
618
619
/** Initializes the program and its elements prior to compilation. */
@@ -1088,19 +1089,28 @@ export class Program extends DiagnosticEmitter {
1088
1089
ensureGlobal ( name : string , element : DeclaredElement ) : DeclaredElement {
1089
1090
var elementsByName = this . elementsByName ;
1090
1091
if ( elementsByName . has ( name ) ) {
1091
- let actual = elementsByName . get ( name ) ! ;
1092
+ let existing = elementsByName . get ( name ) ! ;
1092
1093
// NOTE: this is effectively only performed when merging native types with
1093
1094
// their respective namespaces in std/builtins, but can also trigger when a
1094
1095
// user has multiple global elements of the same name in different files,
1095
1096
// which might result in unexpected shared symbols accross files. considering
1096
1097
// this a wonky feature for now that we might want to revisit later.
1097
- if ( actual !== element ) {
1098
- let merged = tryMerge ( elementsByName . get ( name ) ! , element ) ;
1098
+ if ( existing !== element ) {
1099
+ let merged = tryMerge ( existing , element ) ;
1099
1100
if ( ! merged ) {
1100
- this . error (
1101
- DiagnosticCode . Duplicate_identifier_0 ,
1102
- element . identifierNode . range , name
1103
- ) ;
1101
+ if ( isDeclaredElement ( existing . kind ) ) {
1102
+ this . errorRelated (
1103
+ DiagnosticCode . Duplicate_identifier_0 ,
1104
+ element . identifierNode . range ,
1105
+ ( < DeclaredElement > existing ) . declaration . name . range ,
1106
+ name
1107
+ ) ;
1108
+ } else {
1109
+ this . error (
1110
+ DiagnosticCode . Duplicate_identifier_0 ,
1111
+ element . identifierNode . range , name
1112
+ ) ;
1113
+ }
1104
1114
return element ;
1105
1115
}
1106
1116
element = merged ;
@@ -1675,12 +1685,17 @@ export class Program extends DiagnosticEmitter {
1675
1685
if ( element ) {
1676
1686
let exports = parent . exports ;
1677
1687
if ( ! exports ) parent . exports = exports = new Map ( ) ;
1678
- else if ( exports . has ( "default" ) ) {
1679
- this . error (
1680
- DiagnosticCode . Duplicate_identifier_0 ,
1681
- declaration . name . range , "default"
1682
- ) ;
1683
- return ;
1688
+ else {
1689
+ if ( exports . has ( "default" ) ) {
1690
+ let existing = exports . get ( "default" ) ! ;
1691
+ this . errorRelated (
1692
+ DiagnosticCode . Duplicate_identifier_0 ,
1693
+ declaration . name . range ,
1694
+ existing . declaration . name . range ,
1695
+ "default"
1696
+ ) ;
1697
+ return ;
1698
+ }
1684
1699
}
1685
1700
exports . set ( "default" , element ) ;
1686
1701
}
@@ -2119,18 +2134,27 @@ export abstract class Element {
2119
2134
var members = this . members ;
2120
2135
if ( ! members ) this . members = members = new Map ( ) ;
2121
2136
else if ( members . has ( name ) ) {
2122
- let actual = members . get ( name ) ! ;
2123
- if ( actual . parent !== this ) {
2137
+ let existing = members . get ( name ) ! ;
2138
+ if ( existing . parent !== this ) {
2124
2139
// override non-own element
2125
2140
} else {
2126
- let merged = tryMerge ( actual , element ) ;
2141
+ let merged = tryMerge ( existing , element ) ;
2127
2142
if ( merged ) {
2128
2143
element = merged ; // use merged element
2129
2144
} else {
2130
- this . program . error (
2131
- DiagnosticCode . Duplicate_identifier_0 ,
2132
- element . identifierNode . range , element . identifierNode . text
2133
- ) ;
2145
+ if ( isDeclaredElement ( existing . kind ) ) {
2146
+ this . program . errorRelated (
2147
+ DiagnosticCode . Duplicate_identifier_0 ,
2148
+ element . identifierNode . range ,
2149
+ ( < DeclaredElement > existing ) . declaration . name . range ,
2150
+ element . identifierNode . text
2151
+ ) ;
2152
+ } else {
2153
+ this . program . error (
2154
+ DiagnosticCode . Duplicate_identifier_0 ,
2155
+ element . identifierNode . range , element . identifierNode . text
2156
+ ) ;
2157
+ }
2134
2158
return false ;
2135
2159
}
2136
2160
}
@@ -3188,12 +3212,22 @@ export class ClassPrototype extends DeclaredElement {
3188
3212
var instanceMembers = this . instanceMembers ;
3189
3213
if ( ! instanceMembers ) this . instanceMembers = instanceMembers = new Map ( ) ;
3190
3214
else if ( instanceMembers . has ( name ) ) {
3191
- let merged = tryMerge ( instanceMembers . get ( name ) ! , element ) ;
3215
+ let existing = instanceMembers . get ( name ) ! ;
3216
+ let merged = tryMerge ( existing , element ) ;
3192
3217
if ( ! merged ) {
3193
- this . program . error (
3194
- DiagnosticCode . Duplicate_identifier_0 ,
3195
- element . identifierNode . range , element . identifierNode . text
3196
- ) ;
3218
+ if ( isDeclaredElement ( existing . kind ) ) {
3219
+ this . program . errorRelated (
3220
+ DiagnosticCode . Duplicate_identifier_0 ,
3221
+ element . identifierNode . range ,
3222
+ ( < DeclaredElement > existing ) . declaration . name . range ,
3223
+ element . identifierNode . text
3224
+ ) ;
3225
+ } else {
3226
+ this . program . error (
3227
+ DiagnosticCode . Duplicate_identifier_0 ,
3228
+ element . identifierNode . range , element . identifierNode . text
3229
+ ) ;
3230
+ }
3197
3231
return false ;
3198
3232
}
3199
3233
element = merged ;
0 commit comments