@@ -49,7 +49,11 @@ namespace ts {
49
49
/**
50
50
* program corresponding to this state
51
51
*/
52
- program : Program ;
52
+ program : Program | undefined ;
53
+ /**
54
+ * compilerOptions for the program
55
+ */
56
+ compilerOptions : CompilerOptions ;
53
57
}
54
58
55
59
function hasSameKeys < T , U > ( map1 : ReadonlyMap < T > | undefined , map2 : ReadonlyMap < U > | undefined ) : boolean {
@@ -64,13 +68,14 @@ namespace ts {
64
68
const state = BuilderState . create ( newProgram , getCanonicalFileName , oldState ) as BuilderProgramState ;
65
69
state . program = newProgram ;
66
70
const compilerOptions = newProgram . getCompilerOptions ( ) ;
71
+ state . compilerOptions = compilerOptions ;
67
72
if ( ! compilerOptions . outFile && ! compilerOptions . out ) {
68
73
state . semanticDiagnosticsPerFile = createMap < ReadonlyArray < Diagnostic > > ( ) ;
69
74
}
70
75
state . changedFilesSet = createMap < true > ( ) ;
71
76
72
77
const useOldState = BuilderState . canReuseOldState ( state . referencedMap , oldState ) ;
73
- const oldCompilerOptions = useOldState ? oldState ! . program . getCompilerOptions ( ) : undefined ;
78
+ const oldCompilerOptions = useOldState ? oldState ! . compilerOptions : undefined ;
74
79
const canCopySemanticDiagnostics = useOldState && oldState ! . semanticDiagnosticsPerFile && ! ! state . semanticDiagnosticsPerFile &&
75
80
! compilerOptionsAffectSemanticDiagnostics ( compilerOptions , oldCompilerOptions ! ) ;
76
81
if ( useOldState ) {
@@ -109,7 +114,7 @@ namespace ts {
109
114
state . changedFilesSet . set ( sourceFilePath , true ) ;
110
115
}
111
116
else if ( canCopySemanticDiagnostics ) {
112
- const sourceFile = state . program . getSourceFileByPath ( sourceFilePath as Path ) ! ;
117
+ const sourceFile = newProgram . getSourceFileByPath ( sourceFilePath as Path ) ! ;
113
118
114
119
if ( sourceFile . isDeclarationFile && ! copyDeclarationFileDiagnostics ) { return ; }
115
120
if ( sourceFile . hasNoDefaultLib && ! copyLibFileDiagnostics ) { return ; }
@@ -179,18 +184,19 @@ namespace ts {
179
184
180
185
// With --out or --outFile all outputs go into single file
181
186
// so operations are performed directly on program, return program
182
- const compilerOptions = state . program . getCompilerOptions ( ) ;
187
+ const program = Debug . assertDefined ( state . program ) ;
188
+ const compilerOptions = program . getCompilerOptions ( ) ;
183
189
if ( compilerOptions . outFile || compilerOptions . out ) {
184
190
Debug . assert ( ! state . semanticDiagnosticsPerFile ) ;
185
- return state . program ;
191
+ return program ;
186
192
}
187
193
188
194
// Get next batch of affected files
189
195
state . currentAffectedFilesSignatures = state . currentAffectedFilesSignatures || createMap ( ) ;
190
196
if ( state . exportedModulesMap ) {
191
197
state . currentAffectedFilesExportedModulesMap = state . currentAffectedFilesExportedModulesMap || createMap < BuilderState . ReferencedSet | false > ( ) ;
192
198
}
193
- state . affectedFiles = BuilderState . getFilesAffectedBy ( state , state . program , nextKey . value as Path , cancellationToken , computeHash , state . currentAffectedFilesSignatures , state . currentAffectedFilesExportedModulesMap ) ;
199
+ state . affectedFiles = BuilderState . getFilesAffectedBy ( state , program , nextKey . value as Path , cancellationToken , computeHash , state . currentAffectedFilesSignatures , state . currentAffectedFilesExportedModulesMap ) ;
194
200
state . currentChangedFilePath = nextKey . value as Path ;
195
201
state . affectedFilesIndex = 0 ;
196
202
state . seenAffectedFiles = state . seenAffectedFiles || createMap < true > ( ) ;
@@ -209,9 +215,10 @@ namespace ts {
209
215
// Clean lib file diagnostics if its all files excluding default files to emit
210
216
if ( state . allFilesExcludingDefaultLibraryFile === state . affectedFiles && ! state . cleanedDiagnosticsOfLibFiles ) {
211
217
state . cleanedDiagnosticsOfLibFiles = true ;
212
- const options = state . program . getCompilerOptions ( ) ;
213
- if ( forEach ( state . program . getSourceFiles ( ) , f =>
214
- state . program . isSourceFileDefaultLibrary ( f ) &&
218
+ const program = Debug . assertDefined ( state . program ) ;
219
+ const options = program . getCompilerOptions ( ) ;
220
+ if ( forEach ( program . getSourceFiles ( ) , f =>
221
+ program . isSourceFileDefaultLibrary ( f ) &&
215
222
! skipTypeChecking ( f , options ) &&
216
223
removeSemanticDiagnosticsOf ( state , f . path )
217
224
) ) {
@@ -336,7 +343,7 @@ namespace ts {
336
343
}
337
344
338
345
// Diagnostics werent cached, get them from program, and cache the result
339
- const diagnostics = state . program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ;
346
+ const diagnostics = Debug . assertDefined ( state . program ) . getSemanticDiagnostics ( sourceFile , cancellationToken ) ;
340
347
state . semanticDiagnosticsPerFile ! . set ( path , diagnostics ) ;
341
348
return diagnostics ;
342
349
}
@@ -370,7 +377,7 @@ namespace ts {
370
377
rootNames : newProgramOrRootNames ,
371
378
options : hostOrOptions as CompilerOptions ,
372
379
host : oldProgramOrHost as CompilerHost ,
373
- oldProgram : oldProgram && oldProgram . getProgram ( ) ,
380
+ oldProgram : oldProgram && oldProgram . getProgramOrUndefined ( ) ,
374
381
configFileParsingDiagnostics,
375
382
projectReferences
376
383
} ) ;
@@ -413,7 +420,7 @@ namespace ts {
413
420
414
421
const result = createRedirectedBuilderProgram ( state , configFileParsingDiagnostics ) ;
415
422
result . getState = ( ) => state ;
416
- result . getAllDependencies = sourceFile => BuilderState . getAllDependencies ( state , state . program , sourceFile ) ;
423
+ result . getAllDependencies = sourceFile => BuilderState . getAllDependencies ( state , Debug . assertDefined ( state . program ) , sourceFile ) ;
417
424
result . getSemanticDiagnostics = getSemanticDiagnostics ;
418
425
result . emit = emit ;
419
426
@@ -445,7 +452,7 @@ namespace ts {
445
452
state ,
446
453
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
447
454
// Otherwise just affected file
448
- state . program . emit ( affected === state . program ? undefined : affected as SourceFile , writeFile || host . writeFile , cancellationToken , emitOnlyDtsFiles , customTransformers ) ,
455
+ Debug . assertDefined ( state . program ) . emit ( affected === state . program ? undefined : affected as SourceFile , writeFile || host . writeFile , cancellationToken , emitOnlyDtsFiles , customTransformers ) ,
449
456
affected
450
457
) ;
451
458
}
@@ -486,7 +493,7 @@ namespace ts {
486
493
} ;
487
494
}
488
495
}
489
- return state . program . emit ( targetSourceFile , writeFile || host . writeFile , cancellationToken , emitOnlyDtsFiles , customTransformers ) ;
496
+ return Debug . assertDefined ( state . program ) . emit ( targetSourceFile , writeFile || host . writeFile , cancellationToken , emitOnlyDtsFiles , customTransformers ) ;
490
497
}
491
498
492
499
/**
@@ -534,11 +541,11 @@ namespace ts {
534
541
*/
535
542
function getSemanticDiagnostics ( sourceFile ?: SourceFile , cancellationToken ?: CancellationToken ) : ReadonlyArray < Diagnostic > {
536
543
assertSourceFileOkWithoutNextAffectedCall ( state , sourceFile ) ;
537
- const compilerOptions = state . program . getCompilerOptions ( ) ;
544
+ const compilerOptions = Debug . assertDefined ( state . program ) . getCompilerOptions ( ) ;
538
545
if ( compilerOptions . outFile || compilerOptions . out ) {
539
546
Debug . assert ( ! state . semanticDiagnosticsPerFile ) ;
540
547
// We dont need to cache the diagnostics just return them from program
541
- return state . program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ;
548
+ return Debug . assertDefined ( state . program ) . getSemanticDiagnostics ( sourceFile , cancellationToken ) ;
542
549
}
543
550
544
551
if ( sourceFile ) {
@@ -555,29 +562,31 @@ namespace ts {
555
562
}
556
563
557
564
let diagnostics : Diagnostic [ ] | undefined ;
558
- for ( const sourceFile of state . program . getSourceFiles ( ) ) {
565
+ for ( const sourceFile of Debug . assertDefined ( state . program ) . getSourceFiles ( ) ) {
559
566
diagnostics = addRange ( diagnostics , getSemanticDiagnosticsOfFile ( state , sourceFile , cancellationToken ) ) ;
560
567
}
561
568
return diagnostics || emptyArray ;
562
569
}
563
570
}
564
571
565
- export function createRedirectedBuilderProgram ( state : { program : Program ; } , configFileParsingDiagnostics : ReadonlyArray < Diagnostic > ) : BuilderProgram {
572
+ export function createRedirectedBuilderProgram ( state : { program : Program | undefined ; compilerOptions : CompilerOptions ; } , configFileParsingDiagnostics : ReadonlyArray < Diagnostic > ) : BuilderProgram {
566
573
return {
567
574
getState : notImplemented ,
568
- getProgram : ( ) => state . program ,
569
- getCompilerOptions : ( ) => state . program . getCompilerOptions ( ) ,
570
- getSourceFile : fileName => state . program . getSourceFile ( fileName ) ,
571
- getSourceFiles : ( ) => state . program . getSourceFiles ( ) ,
572
- getOptionsDiagnostics : cancellationToken => state . program . getOptionsDiagnostics ( cancellationToken ) ,
573
- getGlobalDiagnostics : cancellationToken => state . program . getGlobalDiagnostics ( cancellationToken ) ,
575
+ getProgram : ( ) => Debug . assertDefined ( state . program ) ,
576
+ getProgramOrUndefined : ( ) => state . program ,
577
+ releaseProgram : ( ) => state . program = undefined ,
578
+ getCompilerOptions : ( ) => state . compilerOptions ,
579
+ getSourceFile : fileName => Debug . assertDefined ( state . program ) . getSourceFile ( fileName ) ,
580
+ getSourceFiles : ( ) => Debug . assertDefined ( state . program ) . getSourceFiles ( ) ,
581
+ getOptionsDiagnostics : cancellationToken => Debug . assertDefined ( state . program ) . getOptionsDiagnostics ( cancellationToken ) ,
582
+ getGlobalDiagnostics : cancellationToken => Debug . assertDefined ( state . program ) . getGlobalDiagnostics ( cancellationToken ) ,
574
583
getConfigFileParsingDiagnostics : ( ) => configFileParsingDiagnostics ,
575
- getSyntacticDiagnostics : ( sourceFile , cancellationToken ) => state . program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
576
- getDeclarationDiagnostics : ( sourceFile , cancellationToken ) => state . program . getDeclarationDiagnostics ( sourceFile , cancellationToken ) ,
577
- getSemanticDiagnostics : ( sourceFile , cancellationToken ) => state . program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ,
578
- emit : ( sourceFile , writeFile , cancellationToken , emitOnlyDts , customTransformers ) => state . program . emit ( sourceFile , writeFile , cancellationToken , emitOnlyDts , customTransformers ) ,
584
+ getSyntacticDiagnostics : ( sourceFile , cancellationToken ) => Debug . assertDefined ( state . program ) . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
585
+ getDeclarationDiagnostics : ( sourceFile , cancellationToken ) => Debug . assertDefined ( state . program ) . getDeclarationDiagnostics ( sourceFile , cancellationToken ) ,
586
+ getSemanticDiagnostics : ( sourceFile , cancellationToken ) => Debug . assertDefined ( state . program ) . getSemanticDiagnostics ( sourceFile , cancellationToken ) ,
587
+ emit : ( sourceFile , writeFile , cancellationToken , emitOnlyDts , customTransformers ) => Debug . assertDefined ( state . program ) . emit ( sourceFile , writeFile , cancellationToken , emitOnlyDts , customTransformers ) ,
579
588
getAllDependencies : notImplemented ,
580
- getCurrentDirectory : ( ) => state . program . getCurrentDirectory ( )
589
+ getCurrentDirectory : ( ) => Debug . assertDefined ( state . program ) . getCurrentDirectory ( )
581
590
} ;
582
591
}
583
592
}
@@ -611,6 +620,16 @@ namespace ts {
611
620
* Returns current program
612
621
*/
613
622
getProgram ( ) : Program ;
623
+ /**
624
+ * Returns current program that could be undefined if the program was released
625
+ */
626
+ /*@internal */
627
+ getProgramOrUndefined ( ) : Program | undefined ;
628
+ /**
629
+ * Releases reference to the program, making all the other operations that need program to fail.
630
+ */
631
+ /*@internal */
632
+ releaseProgram ( ) : void ;
614
633
/**
615
634
* Get compiler options of the program
616
635
*/
@@ -725,6 +744,6 @@ namespace ts {
725
744
export function createAbstractBuilder ( rootNames : ReadonlyArray < string > | undefined , options : CompilerOptions | undefined , host ?: CompilerHost , oldProgram ?: BuilderProgram , configFileParsingDiagnostics ?: ReadonlyArray < Diagnostic > , projectReferences ?: ReadonlyArray < ProjectReference > ) : BuilderProgram ;
726
745
export function createAbstractBuilder ( newProgramOrRootNames : Program | ReadonlyArray < string > | undefined , hostOrOptions : BuilderProgramHost | CompilerOptions | undefined , oldProgramOrHost ?: CompilerHost | BuilderProgram , configFileParsingDiagnosticsOrOldProgram ?: ReadonlyArray < Diagnostic > | BuilderProgram , configFileParsingDiagnostics ?: ReadonlyArray < Diagnostic > , projectReferences ?: ReadonlyArray < ProjectReference > ) : BuilderProgram {
727
746
const { newProgram, configFileParsingDiagnostics : newConfigFileParsingDiagnostics } = getBuilderCreationParameters ( newProgramOrRootNames , hostOrOptions , oldProgramOrHost , configFileParsingDiagnosticsOrOldProgram , configFileParsingDiagnostics , projectReferences ) ;
728
- return createRedirectedBuilderProgram ( { program : newProgram } , newConfigFileParsingDiagnostics ) ;
747
+ return createRedirectedBuilderProgram ( { program : newProgram , compilerOptions : newProgram . getCompilerOptions ( ) } , newConfigFileParsingDiagnostics ) ;
729
748
}
730
749
}
0 commit comments