@@ -11,6 +11,7 @@ import ts from 'typescript';
1111
1212import { AbsoluteFsPath } from '../../file_system' ;
1313import { Reference } from '../../imports' ;
14+ import { HostDirectiveMeta } from '../../metadata' ;
1415import { ClassDeclaration } from '../../reflection' ;
1516import { ComponentScopeKind , ComponentScopeReader } from '../../scope' ;
1617import { isAssignment , isSymbolWithValueDeclaration } from '../../util/src/typescript' ;
@@ -118,38 +119,80 @@ export class SymbolBuilder {
118119
119120 const nodes = findAllMatchingNodes (
120121 this . typeCheckBlock , { withSpan : elementSourceSpan , filter : isDirectiveDeclaration } ) ;
121- return nodes
122- . map ( node => {
123- const symbol = this . getSymbolOfTsNode ( node . parent ) ;
124- if ( symbol === null || ! isSymbolWithValueDeclaration ( symbol . tsSymbol ) ||
125- ! ts . isClassDeclaration ( symbol . tsSymbol . valueDeclaration ) ) {
126- return null ;
127- }
128- const meta = this . getDirectiveMeta ( element , symbol . tsSymbol . valueDeclaration ) ;
129- if ( meta === null ) {
130- return null ;
131- }
132-
133- const ngModule = this . getDirectiveModule ( symbol . tsSymbol . valueDeclaration ) ;
134- if ( meta . selector === null ) {
135- return null ;
136- }
137- const isComponent = meta . isComponent ?? null ;
138- const ref = new Reference < ClassDeclaration > ( symbol . tsSymbol . valueDeclaration as any ) ;
139- const directiveSymbol : DirectiveSymbol = {
140- ...symbol ,
141- ref,
142- tsSymbol : symbol . tsSymbol ,
143- selector : meta . selector ,
144- isComponent,
145- ngModule,
146- kind : SymbolKind . Directive ,
147- isStructural : meta . isStructural ,
148- isInScope : true ,
149- } ;
150- return directiveSymbol ;
151- } )
152- . filter ( ( d ) : d is DirectiveSymbol => d !== null ) ;
122+ const symbols : DirectiveSymbol [ ] = [ ] ;
123+
124+ for ( const node of nodes ) {
125+ const symbol = this . getSymbolOfTsNode ( node . parent ) ;
126+ if ( symbol === null || ! isSymbolWithValueDeclaration ( symbol . tsSymbol ) ||
127+ ! ts . isClassDeclaration ( symbol . tsSymbol . valueDeclaration ) ) {
128+ continue ;
129+ }
130+
131+ const meta = this . getDirectiveMeta ( element , symbol . tsSymbol . valueDeclaration ) ;
132+
133+ if ( meta !== null && meta . selector !== null ) {
134+ const ref = new Reference < ClassDeclaration > ( symbol . tsSymbol . valueDeclaration as any ) ;
135+
136+ if ( meta . hostDirectives !== null ) {
137+ this . addHostDirectiveSymbols ( element , meta . hostDirectives , symbols ) ;
138+ }
139+
140+ const directiveSymbol : DirectiveSymbol = {
141+ ...symbol ,
142+ ref,
143+ tsSymbol : symbol . tsSymbol ,
144+ selector : meta . selector ,
145+ isComponent : meta . isComponent ,
146+ ngModule : this . getDirectiveModule ( symbol . tsSymbol . valueDeclaration ) ,
147+ kind : SymbolKind . Directive ,
148+ isStructural : meta . isStructural ,
149+ isInScope : true ,
150+ isHostDirective : false ,
151+ } ;
152+
153+ symbols . push ( directiveSymbol ) ;
154+ }
155+ }
156+
157+ return symbols ;
158+ }
159+
160+ private addHostDirectiveSymbols (
161+ host : TmplAstTemplate | TmplAstElement , hostDirectives : HostDirectiveMeta [ ] ,
162+ symbols : DirectiveSymbol [ ] ) : void {
163+ for ( const current of hostDirectives ) {
164+ if ( ! ts . isClassDeclaration ( current . directive . node ) ) {
165+ continue ;
166+ }
167+
168+ const symbol = this . getSymbolOfTsNode ( current . directive . node ) ;
169+ const meta = this . getDirectiveMeta ( host , current . directive . node ) ;
170+
171+ if ( meta !== null && symbol !== null && isSymbolWithValueDeclaration ( symbol . tsSymbol ) ) {
172+ if ( meta . hostDirectives !== null ) {
173+ this . addHostDirectiveSymbols ( host , meta . hostDirectives , symbols ) ;
174+ }
175+
176+ const directiveSymbol : DirectiveSymbol = {
177+ ...symbol ,
178+ isHostDirective : true ,
179+ ref : current . directive ,
180+ tsSymbol : symbol . tsSymbol ,
181+ exposedInputs : current . inputs ,
182+ exposedOutputs : current . outputs ,
183+ // TODO(crisbeto): rework `DirectiveSymbol` to make
184+ // `selector` nullable and remove the `|| ''` here.
185+ selector : meta . selector || '' ,
186+ isComponent : meta . isComponent ,
187+ ngModule : this . getDirectiveModule ( current . directive . node ) ,
188+ kind : SymbolKind . Directive ,
189+ isStructural : meta . isStructural ,
190+ isInScope : true ,
191+ } ;
192+
193+ symbols . push ( directiveSymbol ) ;
194+ }
195+ }
153196 }
154197
155198 private getDirectiveMeta (
@@ -376,6 +419,7 @@ export class SymbolBuilder {
376419 isStructural,
377420 selector,
378421 ngModule,
422+ isHostDirective : false ,
379423 isInScope : true , // TODO: this should always be in scope in this context, right?
380424 } ;
381425 }
0 commit comments