@@ -238,10 +238,7 @@ namespace ts {
238
238
239
239
if ( oldCompilerOptions && compilerOptionsAffectEmit ( compilerOptions , oldCompilerOptions ) ) {
240
240
// Add all files to affectedFilesPendingEmit since emit changed
241
- state . affectedFilesPendingEmit = concatenate ( state . affectedFilesPendingEmit , newProgram . getSourceFiles ( ) . map ( f => f . path ) ) ;
242
- if ( state . affectedFilesPendingEmitIndex === undefined ) {
243
- state . affectedFilesPendingEmitIndex = 0 ;
244
- }
241
+ addToAffectedFilesPendingEmit ( state , newProgram . getSourceFiles ( ) . map ( f => f . path ) ) ;
245
242
Debug . assert ( state . seenAffectedFiles === undefined ) ;
246
243
state . seenAffectedFiles = createMap < true > ( ) ;
247
244
}
@@ -339,7 +336,7 @@ namespace ts {
339
336
if ( ! seenAffectedFiles . has ( affectedFile . path ) ) {
340
337
// Set the next affected file as seen and remove the cached semantic diagnostics
341
338
state . affectedFilesIndex = affectedFilesIndex ;
342
- cleanSemanticDiagnosticsOfAffectedFile ( state , affectedFile ) ;
339
+ handleDtsMayChangeOfAffectedFile ( state , affectedFile , cancellationToken , computeHash ) ;
343
340
return affectedFile ;
344
341
}
345
342
seenAffectedFiles . set ( affectedFile . path , true ) ;
@@ -406,31 +403,83 @@ namespace ts {
406
403
}
407
404
408
405
/**
409
- * Remove the semantic diagnostics cached from old state for affected File and the files that are referencing modules that export entities from affected file
406
+ * Handles semantic diagnostics and dts emit for affectedFile and files, that are referencing modules that export entities from affected file
407
+ * This is because even though js emit doesnt change, dts emit / type used can change resulting in need for dts emit and js change
410
408
*/
411
- function cleanSemanticDiagnosticsOfAffectedFile ( state : BuilderProgramState , affectedFile : SourceFile ) {
412
- if ( removeSemanticDiagnosticsOf ( state , affectedFile . path ) ) {
413
- // If there are no more diagnostics from old cache, done
409
+ function handleDtsMayChangeOfAffectedFile ( state : BuilderProgramState , affectedFile : SourceFile , cancellationToken : CancellationToken | undefined , computeHash : BuilderState . ComputeHash ) {
410
+ removeSemanticDiagnosticsOf ( state , affectedFile . path ) ;
411
+
412
+ // If affected files is everything except default library, then nothing more to do
413
+ if ( state . allFilesExcludingDefaultLibraryFile === state . affectedFiles ) {
414
+ if ( ! state . cleanedDiagnosticsOfLibFiles ) {
415
+ state . cleanedDiagnosticsOfLibFiles = true ;
416
+ const program = Debug . assertDefined ( state . program ) ;
417
+ const options = program . getCompilerOptions ( ) ;
418
+ forEach ( program . getSourceFiles ( ) , f =>
419
+ program . isSourceFileDefaultLibrary ( f ) &&
420
+ ! skipTypeChecking ( f , options ) &&
421
+ removeSemanticDiagnosticsOf ( state , f . path )
422
+ ) ;
423
+ }
414
424
return ;
415
425
}
416
426
417
- // Clean lib file diagnostics if its all files excluding default files to emit
418
- if ( state . allFilesExcludingDefaultLibraryFile === state . affectedFiles && ! state . cleanedDiagnosticsOfLibFiles ) {
419
- state . cleanedDiagnosticsOfLibFiles = true ;
427
+ forEachReferencingModulesOfExportOfAffectedFile ( state , affectedFile , ( state , path ) => handleDtsMayChangeOf ( state , path , cancellationToken , computeHash ) ) ;
428
+ }
429
+
430
+ /**
431
+ * Handle the dts may change, so they need to be added to pending emit if dts emit is enabled,
432
+ * Also we need to make sure signature is updated for these files
433
+ */
434
+ function handleDtsMayChangeOf ( state : BuilderProgramState , path : Path , cancellationToken : CancellationToken | undefined , computeHash : BuilderState . ComputeHash ) {
435
+ removeSemanticDiagnosticsOf ( state , path ) ;
436
+
437
+ if ( ! state . changedFilesSet . has ( path ) ) {
420
438
const program = Debug . assertDefined ( state . program ) ;
421
- const options = program . getCompilerOptions ( ) ;
422
- if ( forEach ( program . getSourceFiles ( ) , f =>
423
- program . isSourceFileDefaultLibrary ( f ) &&
424
- ! skipTypeChecking ( f , options ) &&
425
- removeSemanticDiagnosticsOf ( state , f . path )
426
- ) ) {
427
- return ;
439
+ const sourceFile = program . getSourceFileByPath ( path ) ;
440
+ if ( sourceFile ) {
441
+ // Even though the js emit doesnt change and we are already handling dts emit and semantic diagnostics
442
+ // we need to update the signature to reflect correctness of the signature(which is output d.ts emit) of this file
443
+ // This ensures that we dont later during incremental builds considering wrong signature.
444
+ // Eg where this also is needed to ensure that .tsbuildinfo generated by incremental build should be same as if it was first fresh build
445
+ BuilderState . updateShapeSignature (
446
+ state ,
447
+ program ,
448
+ sourceFile ,
449
+ Debug . assertDefined ( state . currentAffectedFilesSignatures ) ,
450
+ cancellationToken ,
451
+ computeHash ,
452
+ state . currentAffectedFilesExportedModulesMap
453
+ ) ;
454
+ // If not dts emit, nothing more to do
455
+ if ( getEmitDeclarations ( state . compilerOptions ) ) {
456
+ addToAffectedFilesPendingEmit ( state , [ path ] ) ;
457
+ }
428
458
}
429
459
}
430
460
431
- // If there was change in signature for the changed file,
432
- // then delete the semantic diagnostics for files that are affected by using exports of this module
461
+ return false ;
462
+ }
433
463
464
+ /**
465
+ * Removes semantic diagnostics for path and
466
+ * returns true if there are no more semantic diagnostics from the old state
467
+ */
468
+ function removeSemanticDiagnosticsOf ( state : BuilderProgramState , path : Path ) {
469
+ if ( ! state . semanticDiagnosticsFromOldState ) {
470
+ return true ;
471
+ }
472
+ state . semanticDiagnosticsFromOldState . delete ( path ) ;
473
+ state . semanticDiagnosticsPerFile ! . delete ( path ) ;
474
+ return ! state . semanticDiagnosticsFromOldState . size ;
475
+ }
476
+
477
+ /**
478
+ * Iterate on referencing modules that export entities from affected file
479
+ */
480
+ function forEachReferencingModulesOfExportOfAffectedFile ( state : BuilderProgramState , affectedFile : SourceFile , fn : ( state : BuilderProgramState , filePath : Path ) => boolean ) {
481
+ // If there was change in signature (dts output) for the changed file,
482
+ // then only we need to handle pending file emit
434
483
if ( ! state . exportedModulesMap || state . affectedFiles ! . length === 1 || ! state . changedFilesSet . has ( affectedFile . path ) ) {
435
484
return ;
436
485
}
@@ -442,7 +491,7 @@ namespace ts {
442
491
if ( forEachEntry ( state . currentAffectedFilesExportedModulesMap ! , ( exportedModules , exportedFromPath ) =>
443
492
exportedModules &&
444
493
exportedModules . has ( affectedFile . path ) &&
445
- removeSemanticDiagnosticsOfFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
494
+ forEachFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
446
495
) ) {
447
496
return ;
448
497
}
@@ -451,29 +500,28 @@ namespace ts {
451
500
forEachEntry ( state . exportedModulesMap , ( exportedModules , exportedFromPath ) =>
452
501
! state . currentAffectedFilesExportedModulesMap ! . has ( exportedFromPath ) && // If we already iterated this through cache, ignore it
453
502
exportedModules . has ( affectedFile . path ) &&
454
- removeSemanticDiagnosticsOfFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
503
+ forEachFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
455
504
) ;
456
505
}
457
506
458
507
/**
459
- * removes the semantic diagnostics of files referencing referencedPath and
460
- * returns true if there are no more semantic diagnostics from old state
508
+ * Iterate on files referencing referencedPath
461
509
*/
462
- function removeSemanticDiagnosticsOfFilesReferencingPath ( state : BuilderProgramState , referencedPath : Path , seenFileAndExportsOfFile : Map < true > ) {
510
+ function forEachFilesReferencingPath ( state : BuilderProgramState , referencedPath : Path , seenFileAndExportsOfFile : Map < true > , fn : ( state : BuilderProgramState , filePath : Path ) => boolean ) {
463
511
return forEachEntry ( state . referencedMap ! , ( referencesInFile , filePath ) =>
464
- referencesInFile . has ( referencedPath ) && removeSemanticDiagnosticsOfFileAndExportsOfFile ( state , filePath as Path , seenFileAndExportsOfFile )
512
+ referencesInFile . has ( referencedPath ) && forEachFileAndExportsOfFile ( state , filePath as Path , seenFileAndExportsOfFile , fn )
465
513
) ;
466
514
}
467
515
468
516
/**
469
- * Removes semantic diagnostics of file and anything that exports this file
517
+ * fn on file and iterate on anything that exports this file
470
518
*/
471
- function removeSemanticDiagnosticsOfFileAndExportsOfFile ( state : BuilderProgramState , filePath : Path , seenFileAndExportsOfFile : Map < true > ) : boolean {
519
+ function forEachFileAndExportsOfFile ( state : BuilderProgramState , filePath : Path , seenFileAndExportsOfFile : Map < true > , fn : ( state : BuilderProgramState , filePath : Path ) => boolean ) : boolean {
472
520
if ( ! addToSeen ( seenFileAndExportsOfFile , filePath ) ) {
473
521
return false ;
474
522
}
475
523
476
- if ( removeSemanticDiagnosticsOf ( state , filePath ) ) {
524
+ if ( fn ( state , filePath ) ) {
477
525
// If there are no more diagnostics from old cache, done
478
526
return true ;
479
527
}
@@ -484,7 +532,7 @@ namespace ts {
484
532
if ( forEachEntry ( state . currentAffectedFilesExportedModulesMap ! , ( exportedModules , exportedFromPath ) =>
485
533
exportedModules &&
486
534
exportedModules . has ( filePath ) &&
487
- removeSemanticDiagnosticsOfFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
535
+ forEachFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
488
536
) ) {
489
537
return true ;
490
538
}
@@ -493,7 +541,7 @@ namespace ts {
493
541
if ( forEachEntry ( state . exportedModulesMap ! , ( exportedModules , exportedFromPath ) =>
494
542
! state . currentAffectedFilesExportedModulesMap ! . has ( exportedFromPath ) && // If we already iterated this through cache, ignore it
495
543
exportedModules . has ( filePath ) &&
496
- removeSemanticDiagnosticsOfFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
544
+ forEachFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
497
545
) ) {
498
546
return true ;
499
547
}
@@ -502,22 +550,10 @@ namespace ts {
502
550
return ! ! forEachEntry ( state . referencedMap ! , ( referencesInFile , referencingFilePath ) =>
503
551
referencesInFile . has ( filePath ) &&
504
552
! seenFileAndExportsOfFile . has ( referencingFilePath ) && // Not already removed diagnostic file
505
- removeSemanticDiagnosticsOf ( state , referencingFilePath as Path ) // Dont add to seen since this is not yet done with the export removal
553
+ fn ( state , referencingFilePath as Path ) // Dont add to seen since this is not yet done with the export removal
506
554
) ;
507
555
}
508
556
509
- /**
510
- * Removes semantic diagnostics for path and
511
- * returns true if there are no more semantic diagnostics from the old state
512
- */
513
- function removeSemanticDiagnosticsOf ( state : BuilderProgramState , path : Path ) {
514
- if ( ! state . semanticDiagnosticsFromOldState ) {
515
- return true ;
516
- }
517
- state . semanticDiagnosticsFromOldState . delete ( path ) ;
518
- state . semanticDiagnosticsPerFile ! . delete ( path ) ;
519
- return ! state . semanticDiagnosticsFromOldState . size ;
520
- }
521
557
522
558
/**
523
559
* This is called after completing operation on the next affected file.
@@ -808,11 +844,6 @@ namespace ts {
808
844
}
809
845
}
810
846
811
- // Mark seen emitted files if there are pending files to be emitted
812
- if ( state . affectedFilesPendingEmit && state . program !== affected ) {
813
- ( state . seenEmittedFiles || ( state . seenEmittedFiles = createMap ( ) ) ) . set ( ( affected as SourceFile ) . path , true ) ;
814
- }
815
-
816
847
return toAffectedFileResult (
817
848
state ,
818
849
// When whole program is affected, do emit only once (eg when --out or --outFile is specified)
@@ -931,14 +962,7 @@ namespace ts {
931
962
932
963
// In case of emit builder, cache the files to be emitted
933
964
if ( affectedFilesPendingEmit ) {
934
- state . affectedFilesPendingEmit = concatenate ( state . affectedFilesPendingEmit , affectedFilesPendingEmit ) ;
935
- // affectedFilesPendingEmitIndex === undefined
936
- // - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
937
- // so start from 0 as array would be affectedFilesPendingEmit
938
- // else, continue to iterate from existing index, the current set is appended to existing files
939
- if ( state . affectedFilesPendingEmitIndex === undefined ) {
940
- state . affectedFilesPendingEmitIndex = 0 ;
941
- }
965
+ addToAffectedFilesPendingEmit ( state , affectedFilesPendingEmit ) ;
942
966
}
943
967
944
968
let diagnostics : Diagnostic [ ] | undefined ;
@@ -949,6 +973,17 @@ namespace ts {
949
973
}
950
974
}
951
975
976
+ function addToAffectedFilesPendingEmit ( state : BuilderProgramState , affectedFilesPendingEmit : readonly Path [ ] ) {
977
+ state . affectedFilesPendingEmit = concatenate ( state . affectedFilesPendingEmit , affectedFilesPendingEmit ) ;
978
+ // affectedFilesPendingEmitIndex === undefined
979
+ // - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
980
+ // so start from 0 as array would be affectedFilesPendingEmit
981
+ // else, continue to iterate from existing index, the current set is appended to existing files
982
+ if ( state . affectedFilesPendingEmitIndex === undefined ) {
983
+ state . affectedFilesPendingEmitIndex = 0 ;
984
+ }
985
+ }
986
+
952
987
function getMapOfReferencedSet ( mapLike : MapLike < ReadonlyArray < string > > | undefined ) : ReadonlyMap < BuilderState . ReferencedSet > | undefined {
953
988
if ( ! mapLike ) return undefined ;
954
989
const map = createMap < BuilderState . ReferencedSet > ( ) ;
0 commit comments