@@ -241,10 +241,7 @@ namespace ts {
241
241
oldCompilerOptions . declarationDir !== compilerOptions . declarationDir ||
242
242
( oldCompilerOptions . outFile || oldCompilerOptions . out ) !== ( compilerOptions . outFile || compilerOptions . out ) ) ) {
243
243
// Add all files to affectedFilesPendingEmit since emit changed
244
- state . affectedFilesPendingEmit = concatenate ( state . affectedFilesPendingEmit , newProgram . getSourceFiles ( ) . map ( f => f . path ) ) ;
245
- if ( state . affectedFilesPendingEmitIndex === undefined ) {
246
- state . affectedFilesPendingEmitIndex = 0 ;
247
- }
244
+ addToAffectedFilesPendingEmit ( state , newProgram . getSourceFiles ( ) . map ( f => f . path ) ) ;
248
245
Debug . assert ( state . seenAffectedFiles === undefined ) ;
249
246
state . seenAffectedFiles = createMap < true > ( ) ;
250
247
}
@@ -343,6 +340,7 @@ namespace ts {
343
340
// Set the next affected file as seen and remove the cached semantic diagnostics
344
341
state . affectedFilesIndex = affectedFilesIndex ;
345
342
cleanSemanticDiagnosticsOfAffectedFile ( state , affectedFile ) ;
343
+ handleDtsMayChangeOfAffectedFile ( state , affectedFile )
346
344
return affectedFile ;
347
345
}
348
346
seenAffectedFiles . set ( affectedFile . path , true ) ;
@@ -433,7 +431,55 @@ namespace ts {
433
431
434
432
// If there was change in signature for the changed file,
435
433
// then delete the semantic diagnostics for files that are affected by using exports of this module
434
+ forEachReferencingModulesOfExportOfAffectedFile ( state , affectedFile , removeSemanticDiagnosticsOf ) ;
435
+ }
436
436
437
+ /**
438
+ * Removes semantic diagnostics for path and
439
+ * returns true if there are no more semantic diagnostics from the old state
440
+ */
441
+ function removeSemanticDiagnosticsOf ( state : BuilderProgramState , path : Path ) {
442
+ if ( ! state . semanticDiagnosticsFromOldState ) {
443
+ return true ;
444
+ }
445
+ state . semanticDiagnosticsFromOldState . delete ( path ) ;
446
+ state . semanticDiagnosticsPerFile ! . delete ( path ) ;
447
+ return ! state . semanticDiagnosticsFromOldState . size ;
448
+ }
449
+
450
+ /**
451
+ * Add files, that are referencing modules that export entities from affected file as pending emit since dts may change
452
+ * Similar to cleanSemanticDiagnosticsOfAffectedFile
453
+ */
454
+ function handleDtsMayChangeOfAffectedFile ( state : BuilderProgramState , affectedFile : SourceFile ) {
455
+ // If not dts emit, nothing more to do
456
+ if ( ! getEmitDeclarations ( state . compilerOptions ) ) {
457
+ return ;
458
+ }
459
+
460
+ // If affected files is everything except default librarry, then nothing more to do
461
+ if ( state . allFilesExcludingDefaultLibraryFile === state . affectedFiles ) {
462
+ return ;
463
+ }
464
+
465
+ // If there was change in signature (dts output) for the changed file,
466
+ // then only we need to handle pending file emit
467
+ if ( ! state . exportedModulesMap || state . affectedFiles ! . length === 1 || ! state . changedFilesSet . has ( affectedFile . path ) ) {
468
+ return ;
469
+ }
470
+
471
+ forEachReferencingModulesOfExportOfAffectedFile ( state , affectedFile , ( state , filePath ) => {
472
+ addToAffectedFilesPendingEmit ( state , [ filePath ] ) ;
473
+ return false ;
474
+ } ) ;
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
437
483
if ( ! state . exportedModulesMap || state . affectedFiles ! . length === 1 || ! state . changedFilesSet . has ( affectedFile . path ) ) {
438
484
return ;
439
485
}
@@ -445,7 +491,7 @@ namespace ts {
445
491
if ( forEachEntry ( state . currentAffectedFilesExportedModulesMap ! , ( exportedModules , exportedFromPath ) =>
446
492
exportedModules &&
447
493
exportedModules . has ( affectedFile . path ) &&
448
- removeSemanticDiagnosticsOfFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
494
+ forEachFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
449
495
) ) {
450
496
return ;
451
497
}
@@ -454,29 +500,28 @@ namespace ts {
454
500
forEachEntry ( state . exportedModulesMap , ( exportedModules , exportedFromPath ) =>
455
501
! state . currentAffectedFilesExportedModulesMap ! . has ( exportedFromPath ) && // If we already iterated this through cache, ignore it
456
502
exportedModules . has ( affectedFile . path ) &&
457
- removeSemanticDiagnosticsOfFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
503
+ forEachFilesReferencingPath ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
458
504
) ;
459
505
}
460
506
461
507
/**
462
- * removes the semantic diagnostics of files referencing referencedPath and
463
- * returns true if there are no more semantic diagnostics from old state
508
+ * Iterate on files referencing referencedPath
464
509
*/
465
- 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 ) {
466
511
return forEachEntry ( state . referencedMap ! , ( referencesInFile , filePath ) =>
467
- referencesInFile . has ( referencedPath ) && removeSemanticDiagnosticsOfFileAndExportsOfFile ( state , filePath as Path , seenFileAndExportsOfFile )
512
+ referencesInFile . has ( referencedPath ) && forEachFileAndExportsOfFile ( state , filePath as Path , seenFileAndExportsOfFile , fn )
468
513
) ;
469
514
}
470
515
471
516
/**
472
- * Removes semantic diagnostics of file and anything that exports this file
517
+ * fn on file and iterate on anything that exports this file
473
518
*/
474
- 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 {
475
520
if ( ! addToSeen ( seenFileAndExportsOfFile , filePath ) ) {
476
521
return false ;
477
522
}
478
523
479
- if ( removeSemanticDiagnosticsOf ( state , filePath ) ) {
524
+ if ( fn ( state , filePath ) ) {
480
525
// If there are no more diagnostics from old cache, done
481
526
return true ;
482
527
}
@@ -487,7 +532,7 @@ namespace ts {
487
532
if ( forEachEntry ( state . currentAffectedFilesExportedModulesMap ! , ( exportedModules , exportedFromPath ) =>
488
533
exportedModules &&
489
534
exportedModules . has ( filePath ) &&
490
- removeSemanticDiagnosticsOfFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
535
+ forEachFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
491
536
) ) {
492
537
return true ;
493
538
}
@@ -496,7 +541,7 @@ namespace ts {
496
541
if ( forEachEntry ( state . exportedModulesMap ! , ( exportedModules , exportedFromPath ) =>
497
542
! state . currentAffectedFilesExportedModulesMap ! . has ( exportedFromPath ) && // If we already iterated this through cache, ignore it
498
543
exportedModules . has ( filePath ) &&
499
- removeSemanticDiagnosticsOfFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile )
544
+ forEachFileAndExportsOfFile ( state , exportedFromPath as Path , seenFileAndExportsOfFile , fn )
500
545
) ) {
501
546
return true ;
502
547
}
@@ -505,22 +550,10 @@ namespace ts {
505
550
return ! ! forEachEntry ( state . referencedMap ! , ( referencesInFile , referencingFilePath ) =>
506
551
referencesInFile . has ( filePath ) &&
507
552
! seenFileAndExportsOfFile . has ( referencingFilePath ) && // Not already removed diagnostic file
508
- 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
509
554
) ;
510
555
}
511
556
512
- /**
513
- * Removes semantic diagnostics for path and
514
- * returns true if there are no more semantic diagnostics from the old state
515
- */
516
- function removeSemanticDiagnosticsOf ( state : BuilderProgramState , path : Path ) {
517
- if ( ! state . semanticDiagnosticsFromOldState ) {
518
- return true ;
519
- }
520
- state . semanticDiagnosticsFromOldState . delete ( path ) ;
521
- state . semanticDiagnosticsPerFile ! . delete ( path ) ;
522
- return ! state . semanticDiagnosticsFromOldState . size ;
523
- }
524
557
525
558
/**
526
559
* This is called after completing operation on the next affected file.
@@ -929,14 +962,7 @@ namespace ts {
929
962
930
963
// In case of emit builder, cache the files to be emitted
931
964
if ( affectedFilesPendingEmit ) {
932
- state . affectedFilesPendingEmit = concatenate ( state . affectedFilesPendingEmit , affectedFilesPendingEmit ) ;
933
- // affectedFilesPendingEmitIndex === undefined
934
- // - means the emit state.affectedFilesPendingEmit was undefined before adding current affected files
935
- // so start from 0 as array would be affectedFilesPendingEmit
936
- // else, continue to iterate from existing index, the current set is appended to existing files
937
- if ( state . affectedFilesPendingEmitIndex === undefined ) {
938
- state . affectedFilesPendingEmitIndex = 0 ;
939
- }
965
+ addToAffectedFilesPendingEmit ( state , affectedFilesPendingEmit ) ;
940
966
}
941
967
942
968
let diagnostics : Diagnostic [ ] | undefined ;
@@ -947,6 +973,17 @@ namespace ts {
947
973
}
948
974
}
949
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
+
950
987
function getMapOfReferencedSet ( mapLike : MapLike < ReadonlyArray < string > > | undefined ) : ReadonlyMap < BuilderState . ReferencedSet > | undefined {
951
988
if ( ! mapLike ) return undefined ;
952
989
const map = createMap < BuilderState . ReferencedSet > ( ) ;
0 commit comments