@@ -16,6 +16,7 @@ import {
16
16
makeBindingParser ,
17
17
R3ClassMetadata ,
18
18
R3DirectiveMetadata ,
19
+ R3TargetBinder ,
19
20
WrappedNodeExpr ,
20
21
} from '@angular/compiler' ;
21
22
import ts from 'typescript' ;
@@ -47,7 +48,7 @@ import {
47
48
Decorator ,
48
49
ReflectionHost ,
49
50
} from '../../../reflection' ;
50
- import { LocalModuleScopeRegistry } from '../../../scope' ;
51
+ import { LocalModuleScopeRegistry , TypeCheckScopeRegistry } from '../../../scope' ;
51
52
import {
52
53
AnalysisOutput ,
53
54
CompilationMode ,
@@ -79,6 +80,12 @@ import {
79
80
import { extractDirectiveMetadata , extractHostBindingResources , HostBindingNodes } from './shared' ;
80
81
import { DirectiveSymbol } from './symbol' ;
81
82
import { JitDeclarationRegistry } from '../../common/src/jit_declaration_registry' ;
83
+ import {
84
+ HostBindingsContext ,
85
+ TypeCheckableDirectiveMeta ,
86
+ TypeCheckContext ,
87
+ } from '../../../typecheck/api' ;
88
+ import { createHostElement } from '../../../typecheck' ;
82
89
83
90
const FIELD_DECORATORS = [
84
91
'Input' ,
@@ -138,11 +145,14 @@ export class DirectiveDecoratorHandler
138
145
private perf : PerfRecorder ,
139
146
private importTracker : ImportedSymbolsTracker ,
140
147
private includeClassMetadata : boolean ,
148
+ private typeCheckScopeRegistry : TypeCheckScopeRegistry ,
141
149
private readonly compilationMode : CompilationMode ,
142
150
private readonly jitDeclarationRegistry : JitDeclarationRegistry ,
143
151
private readonly resourceRegistry : ResourceRegistry ,
144
152
private readonly strictStandalone : boolean ,
145
153
private readonly implicitStandaloneValue : boolean ,
154
+ private readonly usePoisonedData : boolean ,
155
+ private readonly typeCheckHostBindings : boolean ,
146
156
) { }
147
157
148
158
readonly precedence = HandlerPrecedence . PRIMARY ;
@@ -303,6 +313,53 @@ export class DirectiveDecoratorHandler
303
313
} ) ;
304
314
}
305
315
316
+ typeCheck (
317
+ ctx : TypeCheckContext ,
318
+ node : ClassDeclaration ,
319
+ meta : Readonly < DirectiveHandlerData > ,
320
+ ) : void {
321
+ // Currently type checking in directives is only supported for host bindings
322
+ // so we can skip everything below if type checking is disabled.
323
+ if ( ! this . typeCheckHostBindings ) {
324
+ return ;
325
+ }
326
+
327
+ if ( ! ts . isClassDeclaration ( node ) || ( meta . isPoisoned && ! this . usePoisonedData ) ) {
328
+ return ;
329
+ }
330
+ const scope = this . typeCheckScopeRegistry . getTypeCheckScope ( node ) ;
331
+ if ( scope . isPoisoned && ! this . usePoisonedData ) {
332
+ // Don't type-check components that had errors in their scopes, unless requested.
333
+ return ;
334
+ }
335
+
336
+ const hostElement = createHostElement (
337
+ 'directive' ,
338
+ meta . meta . selector ,
339
+ node ,
340
+ meta . hostBindingNodes . literal ,
341
+ meta . hostBindingNodes . bindingDecorators ,
342
+ meta . hostBindingNodes . listenerDecorators ,
343
+ ) ;
344
+
345
+ if ( hostElement !== null ) {
346
+ const binder = new R3TargetBinder < TypeCheckableDirectiveMeta > ( scope . matcher ) ;
347
+ const hostBindingsContext : HostBindingsContext = {
348
+ node : hostElement ,
349
+ sourceMapping : { type : 'direct' , node} ,
350
+ } ;
351
+
352
+ ctx . addDirective (
353
+ new Reference ( node ) ,
354
+ binder ,
355
+ scope . schemas ,
356
+ null ,
357
+ hostBindingsContext ,
358
+ meta . meta . isStandalone ,
359
+ ) ;
360
+ }
361
+ }
362
+
306
363
resolve (
307
364
node : ClassDeclaration ,
308
365
analysis : DirectiveHandlerData ,
@@ -354,7 +411,13 @@ export class DirectiveDecoratorHandler
354
411
diagnostics . push ( ...hostDirectivesDiagnotics ) ;
355
412
}
356
413
357
- return { diagnostics : diagnostics . length > 0 ? diagnostics : undefined } ;
414
+ if ( diagnostics . length > 0 ) {
415
+ return { diagnostics} ;
416
+ }
417
+
418
+ // Note: we need to produce *some* sort of the data in order
419
+ // for the host binding diagnostics to be surfaced.
420
+ return { data : { } } ;
358
421
}
359
422
360
423
compileFull (
0 commit comments