@@ -172,6 +172,7 @@ export class SymbolBuilder {
172
172
filter : isDirectiveDeclaration ,
173
173
} ) ;
174
174
const symbols : DirectiveSymbol [ ] = [ ] ;
175
+ const seenDirectives = new Set < ts . ClassDeclaration > ( ) ;
175
176
176
177
for ( const node of nodes ) {
177
178
const symbol = this . getSymbolOfTsNode ( node . parent ) ;
@@ -183,13 +184,16 @@ export class SymbolBuilder {
183
184
continue ;
184
185
}
185
186
186
- const meta = this . getDirectiveMeta ( element , symbol . tsSymbol . valueDeclaration ) ;
187
+ const declaration = symbol . tsSymbol . valueDeclaration ;
188
+ const meta = this . getDirectiveMeta ( element , declaration ) ;
187
189
188
- if ( meta !== null && meta . selector !== null ) {
189
- const ref = new Reference < ClassDeclaration > ( symbol . tsSymbol . valueDeclaration as any ) ;
190
+ // Host directives will be added as identifiers with the same offset as the host
191
+ // which means that they'll get added twice. De-duplicate them to avoid confusion.
192
+ if ( meta !== null && ! seenDirectives . has ( declaration ) ) {
193
+ const ref = new Reference < ClassDeclaration > ( declaration as ClassDeclaration ) ;
190
194
191
195
if ( meta . hostDirectives !== null ) {
192
- this . addHostDirectiveSymbols ( element , meta . hostDirectives , symbols ) ;
196
+ this . addHostDirectiveSymbols ( element , meta . hostDirectives , symbols , seenDirectives ) ;
193
197
}
194
198
195
199
const directiveSymbol : DirectiveSymbol = {
@@ -198,14 +202,15 @@ export class SymbolBuilder {
198
202
tsSymbol : symbol . tsSymbol ,
199
203
selector : meta . selector ,
200
204
isComponent : meta . isComponent ,
201
- ngModule : this . getDirectiveModule ( symbol . tsSymbol . valueDeclaration ) ,
205
+ ngModule : this . getDirectiveModule ( declaration ) ,
202
206
kind : SymbolKind . Directive ,
203
207
isStructural : meta . isStructural ,
204
208
isInScope : true ,
205
209
isHostDirective : false ,
206
210
} ;
207
211
208
212
symbols . push ( directiveSymbol ) ;
213
+ seenDirectives . add ( declaration ) ;
209
214
}
210
215
}
211
216
@@ -216,22 +221,25 @@ export class SymbolBuilder {
216
221
host : TmplAstTemplate | TmplAstElement ,
217
222
hostDirectives : HostDirectiveMeta [ ] ,
218
223
symbols : DirectiveSymbol [ ] ,
224
+ seenDirectives : Set < ts . ClassDeclaration > ,
219
225
) : void {
220
226
for ( const current of hostDirectives ) {
221
227
if ( ! isHostDirectiveMetaForGlobalMode ( current ) ) {
222
228
throw new Error ( 'Impossible state: typecheck code path in local compilation mode.' ) ;
223
229
}
224
230
225
- if ( ! ts . isClassDeclaration ( current . directive . node ) ) {
231
+ const node = current . directive . node ;
232
+
233
+ if ( ! ts . isClassDeclaration ( node ) || seenDirectives . has ( node ) ) {
226
234
continue ;
227
235
}
228
236
229
- const symbol = this . getSymbolOfTsNode ( current . directive . node ) ;
230
- const meta = this . getDirectiveMeta ( host , current . directive . node ) ;
237
+ const symbol = this . getSymbolOfTsNode ( node ) ;
238
+ const meta = this . getDirectiveMeta ( host , node ) ;
231
239
232
240
if ( meta !== null && symbol !== null && isSymbolWithValueDeclaration ( symbol . tsSymbol ) ) {
233
241
if ( meta . hostDirectives !== null ) {
234
- this . addHostDirectiveSymbols ( host , meta . hostDirectives , symbols ) ;
242
+ this . addHostDirectiveSymbols ( host , meta . hostDirectives , symbols , seenDirectives ) ;
235
243
}
236
244
237
245
const directiveSymbol : DirectiveSymbol = {
@@ -243,13 +251,14 @@ export class SymbolBuilder {
243
251
exposedOutputs : current . outputs ,
244
252
selector : meta . selector ,
245
253
isComponent : meta . isComponent ,
246
- ngModule : this . getDirectiveModule ( current . directive . node ) ,
254
+ ngModule : this . getDirectiveModule ( node ) ,
247
255
kind : SymbolKind . Directive ,
248
256
isStructural : meta . isStructural ,
249
257
isInScope : true ,
250
258
} ;
251
259
252
260
symbols . push ( directiveSymbol ) ;
261
+ seenDirectives . add ( node ) ;
253
262
}
254
263
}
255
264
}
0 commit comments