@@ -18,7 +18,7 @@ import {getSourceFileOrNull} from '../../util/src/typescript';
18
18
import { OptimizeFor , ProgramTypeCheckAdapter , TemplateId , TemplateTypeChecker , TypeCheckingConfig , TypeCheckingProgramStrategy , UpdateMode } from '../api' ;
19
19
20
20
import { InliningMode , ShimTypeCheckingData , TypeCheckContextImpl , TypeCheckingHost } from './context' ;
21
- import { findTypeCheckBlock , shouldReportDiagnostic , TemplateSourceResolver , translateDiagnostic } from './diagnostics' ;
21
+ import { findTypeCheckBlock , shouldReportDiagnostic , TemplateDiagnostic , TemplateSourceResolver , translateDiagnostic } from './diagnostics' ;
22
22
import { TemplateSourceManager } from './source' ;
23
23
24
24
/**
@@ -112,10 +112,44 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker {
112
112
diagnostics . push ( ...shimRecord . genesisDiagnostics ) ;
113
113
}
114
114
115
-
116
115
return diagnostics . filter ( ( diag : ts . Diagnostic | null ) : diag is ts . Diagnostic => diag !== null ) ;
117
116
}
118
117
118
+ getDiagnosticsForComponent ( component : ts . ClassDeclaration ) : ts . Diagnostic [ ] {
119
+ this . ensureShimForComponent ( component ) ;
120
+
121
+ const sf = component . getSourceFile ( ) ;
122
+ const sfPath = absoluteFromSourceFile ( sf ) ;
123
+ const shimPath = this . typeCheckingStrategy . shimPathForComponent ( component ) ;
124
+
125
+ const fileRecord = this . getFileData ( sfPath ) ;
126
+
127
+ if ( ! fileRecord . shimData . has ( shimPath ) ) {
128
+ return [ ] ;
129
+ }
130
+
131
+ const templateId = fileRecord . sourceManager . getTemplateId ( component ) ;
132
+ const shimRecord = fileRecord . shimData . get ( shimPath ) ! ;
133
+
134
+ const typeCheckProgram = this . typeCheckingStrategy . getProgram ( ) ;
135
+
136
+ const diagnostics : ( TemplateDiagnostic | null ) [ ] = [ ] ;
137
+ if ( shimRecord . hasInlines ) {
138
+ const inlineSf = getSourceFileOrError ( typeCheckProgram , sfPath ) ;
139
+ diagnostics . push ( ...typeCheckProgram . getSemanticDiagnostics ( inlineSf ) . map (
140
+ diag => convertDiagnostic ( diag , fileRecord . sourceManager ) ) ) ;
141
+ }
142
+
143
+ const shimSf = getSourceFileOrError ( typeCheckProgram , shimPath ) ;
144
+ diagnostics . push ( ...typeCheckProgram . getSemanticDiagnostics ( shimSf ) . map (
145
+ diag => convertDiagnostic ( diag , fileRecord . sourceManager ) ) ) ;
146
+ diagnostics . push ( ...shimRecord . genesisDiagnostics ) ;
147
+
148
+ return diagnostics . filter (
149
+ ( diag : TemplateDiagnostic | null ) : diag is TemplateDiagnostic =>
150
+ diag !== null && diag . templateId === templateId ) ;
151
+ }
152
+
119
153
getTypeCheckBlock ( component : ts . ClassDeclaration ) : ts . Node | null {
120
154
this . ensureAllShimsForOneFile ( component . getSourceFile ( ) ) ;
121
155
@@ -219,6 +253,28 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker {
219
253
this . updateFromContext ( ctx ) ;
220
254
}
221
255
256
+ private ensureShimForComponent ( component : ts . ClassDeclaration ) : void {
257
+ const sf = component . getSourceFile ( ) ;
258
+ const sfPath = absoluteFromSourceFile ( sf ) ;
259
+
260
+ this . maybeAdoptPriorResultsForFile ( sf ) ;
261
+
262
+ const fileData = this . getFileData ( sfPath ) ;
263
+ const shimPath = this . typeCheckingStrategy . shimPathForComponent ( component ) ;
264
+
265
+ if ( fileData . shimData . has ( shimPath ) ) {
266
+ // All data for this component is available.
267
+ return ;
268
+ }
269
+
270
+ const host =
271
+ new SingleShimTypeCheckingHost ( sfPath , fileData , this . typeCheckingStrategy , this , shimPath ) ;
272
+ const ctx = this . newContext ( host ) ;
273
+
274
+ this . typeCheckAdapter . typeCheck ( sf , ctx ) ;
275
+ this . updateFromContext ( ctx ) ;
276
+ }
277
+
222
278
private newContext ( host : TypeCheckingHost ) : TypeCheckContextImpl {
223
279
const inlining = this . typeCheckingStrategy . supportsInlineOperations ? InliningMode . InlineOps :
224
280
InliningMode . Error ;
@@ -272,7 +328,7 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker {
272
328
}
273
329
274
330
function convertDiagnostic (
275
- diag : ts . Diagnostic , sourceResolver : TemplateSourceResolver ) : ts . Diagnostic | null {
331
+ diag : ts . Diagnostic , sourceResolver : TemplateSourceResolver ) : TemplateDiagnostic | null {
276
332
if ( ! shouldReportDiagnostic ( diag ) ) {
277
333
return null ;
278
334
}
@@ -367,8 +423,8 @@ class SingleFileTypeCheckingHost implements TypeCheckingHost {
367
423
private seenInlines = false ;
368
424
369
425
constructor (
370
- private sfPath : AbsoluteFsPath , private fileData : FileTypeCheckingData ,
371
- private strategy : TypeCheckingProgramStrategy , private impl : TemplateTypeCheckerImpl ) { }
426
+ protected sfPath : AbsoluteFsPath , protected fileData : FileTypeCheckingData ,
427
+ protected strategy : TypeCheckingProgramStrategy , protected impl : TemplateTypeCheckerImpl ) { }
372
428
373
429
private assertPath ( sfPath : AbsoluteFsPath ) : void {
374
430
if ( this . sfPath !== sfPath ) {
@@ -431,3 +487,30 @@ class SingleFileTypeCheckingHost implements TypeCheckingHost {
431
487
this . fileData . isComplete = true ;
432
488
}
433
489
}
490
+
491
+ /**
492
+ * Drives a `TypeCheckContext` to generate type-checking code efficiently for only those components
493
+ * which map to a single shim of a single input file.
494
+ */
495
+ class SingleShimTypeCheckingHost extends SingleFileTypeCheckingHost {
496
+ constructor (
497
+ sfPath : AbsoluteFsPath , fileData : FileTypeCheckingData , strategy : TypeCheckingProgramStrategy ,
498
+ impl : TemplateTypeCheckerImpl , private shimPath : AbsoluteFsPath ) {
499
+ super ( sfPath , fileData , strategy , impl ) ;
500
+ }
501
+
502
+ shouldCheckNode ( node : ts . ClassDeclaration ) : boolean {
503
+ if ( this . sfPath !== absoluteFromSourceFile ( node . getSourceFile ( ) ) ) {
504
+ return false ;
505
+ }
506
+
507
+ // Only generate a TCB for the component if it maps to the requested shim file.
508
+ const shimPath = this . strategy . shimPathForComponent ( node ) ;
509
+ if ( shimPath !== this . shimPath ) {
510
+ return false ;
511
+ }
512
+
513
+ // Only need to generate a TCB for the class if no shim exists for it currently.
514
+ return ! this . fileData . shimData . has ( shimPath ) ;
515
+ }
516
+ }
0 commit comments