@@ -212,7 +212,7 @@ namespace ts {
212
212
const copyLibFileDiagnostics = copyDeclarationFileDiagnostics && ! compilerOptions . skipDefaultLibCheck === ! oldCompilerOptions ! . skipDefaultLibCheck ;
213
213
state . fileInfos . forEach ( ( info , sourceFilePath ) => {
214
214
let oldInfo : Readonly < BuilderState . FileInfo > | undefined ;
215
- let newReferences : BuilderState . ReferencedSet | undefined ;
215
+ let newReferences : ReadonlySet < Path > | undefined ;
216
216
217
217
// if not using old state, every file is changed
218
218
if ( ! useOldState ||
@@ -311,7 +311,7 @@ namespace ts {
311
311
newState . affectedFilesIndex = state . affectedFilesIndex ;
312
312
newState . currentChangedFilePath = state . currentChangedFilePath ;
313
313
newState . currentAffectedFilesSignatures = state . currentAffectedFilesSignatures && new Map ( state . currentAffectedFilesSignatures ) ;
314
- newState . currentAffectedFilesExportedModulesMap = state . currentAffectedFilesExportedModulesMap && new Map ( state . currentAffectedFilesExportedModulesMap ) ;
314
+ newState . currentAffectedFilesExportedModulesMap = state . currentAffectedFilesExportedModulesMap && { exporting : state . currentAffectedFilesExportedModulesMap . exporting . clone ( ) , nonExporting : new Set ( state . currentAffectedFilesExportedModulesMap . nonExporting ) } ;
315
315
newState . seenAffectedFiles = state . seenAffectedFiles && new Set ( state . seenAffectedFiles ) ;
316
316
newState . cleanedDiagnosticsOfLibFiles = state . cleanedDiagnosticsOfLibFiles ;
317
317
newState . semanticDiagnosticsFromOldState = state . semanticDiagnosticsFromOldState && new Set ( state . semanticDiagnosticsFromOldState ) ;
@@ -384,7 +384,12 @@ namespace ts {
384
384
// Get next batch of affected files
385
385
if ( ! state . currentAffectedFilesSignatures ) state . currentAffectedFilesSignatures = new Map ( ) ;
386
386
if ( state . exportedModulesMap ) {
387
- if ( ! state . currentAffectedFilesExportedModulesMap ) state . currentAffectedFilesExportedModulesMap = new Map ( ) ;
387
+ if ( ! state . currentAffectedFilesExportedModulesMap ) {
388
+ state . currentAffectedFilesExportedModulesMap = {
389
+ exporting : BuilderState . createTwoWayMap < Path , Path > ( ) ,
390
+ nonExporting : new Set < Path > ( ) ,
391
+ } ;
392
+ }
388
393
}
389
394
state . affectedFiles = BuilderState . getFilesAffectedBy ( state , program , nextKey . value , cancellationToken , computeHash , state . currentAffectedFilesSignatures , state . currentAffectedFilesExportedModulesMap ) ;
390
395
state . currentChangedFilePath = nextKey . value ;
@@ -465,7 +470,7 @@ namespace ts {
465
470
* Handle the dts may change, so they need to be added to pending emit if dts emit is enabled,
466
471
* Also we need to make sure signature is updated for these files
467
472
*/
468
- function handleDtsMayChangeOf ( state : BuilderProgramState , path : Path , cancellationToken : CancellationToken | undefined , computeHash : BuilderState . ComputeHash ) {
473
+ function handleDtsMayChangeOf ( state : BuilderProgramState , path : Path , cancellationToken : CancellationToken | undefined , computeHash : BuilderState . ComputeHash ) : void {
469
474
removeSemanticDiagnosticsOf ( state , path ) ;
470
475
471
476
if ( ! state . changedFilesSet . has ( path ) ) {
@@ -491,8 +496,6 @@ namespace ts {
491
496
}
492
497
}
493
498
}
494
-
495
- return false ;
496
499
}
497
500
498
501
/**
@@ -517,7 +520,7 @@ namespace ts {
517
520
/**
518
521
* Iterate on referencing modules that export entities from affected file
519
522
*/
520
- function forEachReferencingModulesOfExportOfAffectedFile ( state : BuilderProgramState , affectedFile : SourceFile , fn : ( state : BuilderProgramState , filePath : Path ) => boolean ) {
523
+ function forEachReferencingModulesOfExportOfAffectedFile ( state : BuilderProgramState , affectedFile : SourceFile , fn : ( state : BuilderProgramState , filePath : Path ) => void ) {
521
524
// If there was change in signature (dts output) for the changed file,
522
525
// then only we need to handle pending file emit
523
526
if ( ! state . exportedModulesMap || ! state . changedFilesSet . has ( affectedFile . resolvedPath ) ) {
@@ -536,8 +539,8 @@ namespace ts {
536
539
const currentPath = queue . pop ( ) ! ;
537
540
if ( ! seenFileNamesMap . has ( currentPath ) ) {
538
541
seenFileNamesMap . set ( currentPath , true ) ;
539
- const result = fn ( state , currentPath ) ;
540
- if ( result && isChangedSignature ( state , currentPath ) ) {
542
+ fn ( state , currentPath ) ;
543
+ if ( isChangedSignature ( state , currentPath ) ) {
541
544
const currentSourceFile = Debug . checkDefined ( state . program ) . getSourceFileByPath ( currentPath ) ! ;
542
545
queue . push ( ...BuilderState . getReferencedByPaths ( state , currentSourceFile . resolvedPath ) ) ;
543
546
}
@@ -546,70 +549,59 @@ namespace ts {
546
549
}
547
550
548
551
Debug . assert ( ! ! state . currentAffectedFilesExportedModulesMap ) ;
552
+
549
553
const seenFileAndExportsOfFile = new Set < string > ( ) ;
550
554
// Go through exported modules from cache first
551
555
// If exported modules has path, all files referencing file exported from are affected
552
- if ( forEachEntry ( state . currentAffectedFilesExportedModulesMap , ( exportedModules , exportedFromPath ) =>
553
- exportedModules &&
554
- exportedModules . has ( affectedFile . resolvedPath ) &&
556
+ state . currentAffectedFilesExportedModulesMap . exporting . getKeys ( affectedFile . resolvedPath ) ?. forEach ( exportedFromPath =>
555
557
forEachFilesReferencingPath ( state , exportedFromPath , seenFileAndExportsOfFile , fn )
556
- ) ) {
557
- return ;
558
- }
558
+ ) ;
559
559
560
560
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
561
- forEachEntry ( state . exportedModulesMap , ( exportedModules , exportedFromPath ) =>
562
- ! state . currentAffectedFilesExportedModulesMap ! . has ( exportedFromPath ) && // If we already iterated this through cache, ignore it
563
- exportedModules . has ( affectedFile . resolvedPath ) &&
561
+ state . exportedModulesMap . getKeys ( affectedFile . resolvedPath ) ?. forEach ( exportedFromPath =>
562
+ // If the cache had an updated value, skip
563
+ ! state . currentAffectedFilesExportedModulesMap ! . exporting . has ( exportedFromPath ) &&
564
+ ! state . currentAffectedFilesExportedModulesMap ! . nonExporting . has ( exportedFromPath ) &&
564
565
forEachFilesReferencingPath ( state , exportedFromPath , seenFileAndExportsOfFile , fn )
565
566
) ;
566
567
}
567
568
568
569
/**
569
570
* Iterate on files referencing referencedPath
570
571
*/
571
- function forEachFilesReferencingPath ( state : BuilderProgramState , referencedPath : Path , seenFileAndExportsOfFile : Set < string > , fn : ( state : BuilderProgramState , filePath : Path ) => boolean ) {
572
- return forEachEntry ( state . referencedMap ! , ( referencesInFile , filePath ) =>
573
- referencesInFile . has ( referencedPath ) && forEachFileAndExportsOfFile ( state , filePath , seenFileAndExportsOfFile , fn )
572
+ function forEachFilesReferencingPath ( state : BuilderProgramState , referencedPath : Path , seenFileAndExportsOfFile : Set < string > , fn : ( state : BuilderProgramState , filePath : Path ) => void ) : void {
573
+ state . referencedMap ! . getKeys ( referencedPath ) ?. forEach ( filePath =>
574
+ forEachFileAndExportsOfFile ( state , filePath , seenFileAndExportsOfFile , fn )
574
575
) ;
575
576
}
576
577
577
578
/**
578
579
* fn on file and iterate on anything that exports this file
579
580
*/
580
- function forEachFileAndExportsOfFile ( state : BuilderProgramState , filePath : Path , seenFileAndExportsOfFile : Set < string > , fn : ( state : BuilderProgramState , filePath : Path ) => boolean ) : boolean {
581
+ function forEachFileAndExportsOfFile ( state : BuilderProgramState , filePath : Path , seenFileAndExportsOfFile : Set < string > , fn : ( state : BuilderProgramState , filePath : Path ) => void ) : void {
581
582
if ( ! tryAddToSet ( seenFileAndExportsOfFile , filePath ) ) {
582
- return false ;
583
+ return ;
583
584
}
584
585
585
- if ( fn ( state , filePath ) ) {
586
- // If there are no more diagnostics from old cache, done
587
- return true ;
588
- }
586
+ fn ( state , filePath ) ;
589
587
590
588
Debug . assert ( ! ! state . currentAffectedFilesExportedModulesMap ) ;
591
589
// Go through exported modules from cache first
592
590
// If exported modules has path, all files referencing file exported from are affected
593
- if ( forEachEntry ( state . currentAffectedFilesExportedModulesMap , ( exportedModules , exportedFromPath ) =>
594
- exportedModules &&
595
- exportedModules . has ( filePath ) &&
591
+ state . currentAffectedFilesExportedModulesMap . exporting . getKeys ( filePath ) ?. forEach ( exportedFromPath =>
596
592
forEachFileAndExportsOfFile ( state , exportedFromPath , seenFileAndExportsOfFile , fn )
597
- ) ) {
598
- return true ;
599
- }
593
+ ) ;
600
594
601
595
// If exported from path is not from cache and exported modules has path, all files referencing file exported from are affected
602
- if ( forEachEntry ( state . exportedModulesMap ! , ( exportedModules , exportedFromPath ) =>
603
- ! state . currentAffectedFilesExportedModulesMap ! . has ( exportedFromPath ) && // If we already iterated this through cache, ignore it
604
- exportedModules . has ( filePath ) &&
596
+ state . exportedModulesMap ! . getKeys ( filePath ) ?. forEach ( exportedFromPath =>
597
+ // If the cache had an updated value, skip
598
+ ! state . currentAffectedFilesExportedModulesMap ! . exporting . has ( exportedFromPath ) &&
599
+ ! state . currentAffectedFilesExportedModulesMap ! . nonExporting . has ( exportedFromPath ) &&
605
600
forEachFileAndExportsOfFile ( state , exportedFromPath , seenFileAndExportsOfFile , fn )
606
- ) ) {
607
- return true ;
608
- }
601
+ ) ;
609
602
610
603
// Remove diagnostics of files that import this file (without going to exports of referencing files)
611
- return ! ! forEachEntry ( state . referencedMap ! , ( referencesInFile , referencingFilePath ) =>
612
- referencesInFile . has ( filePath ) &&
604
+ state . referencedMap ! . getKeys ( filePath ) ?. forEach ( referencingFilePath =>
613
605
! seenFileAndExportsOfFile . has ( referencingFilePath ) && // Not already removed diagnostic file
614
606
fn ( state , referencingFilePath ) // Dont add to seen since this is not yet done with the export removal
615
607
) ;
@@ -771,11 +763,19 @@ namespace ts {
771
763
let exportedModulesMap : ProgramBuildInfoReferencedMap | undefined ;
772
764
if ( state . exportedModulesMap ) {
773
765
exportedModulesMap = mapDefined ( arrayFrom ( state . exportedModulesMap . keys ( ) ) . sort ( compareStringsCaseSensitive ) , key => {
774
- const newValue = state . currentAffectedFilesExportedModulesMap && state . currentAffectedFilesExportedModulesMap . get ( key ) ;
766
+ if ( state . currentAffectedFilesExportedModulesMap ) {
767
+ if ( state . currentAffectedFilesExportedModulesMap . nonExporting . has ( key ) ) {
768
+ return undefined ;
769
+ }
770
+
771
+ const newValue = state . currentAffectedFilesExportedModulesMap . exporting . get ( key ) ;
772
+ if ( newValue ) {
773
+ return [ toFileId ( key ) , toFileIdListId ( newValue ) ] ;
774
+ }
775
+ }
776
+
775
777
// Not in temporary cache, use existing value
776
- if ( newValue === undefined ) return [ toFileId ( key ) , toFileIdListId ( state . exportedModulesMap ! . get ( key ) ! ) ] ;
777
- // Value in cache and has updated value map, use that
778
- else if ( newValue ) return [ toFileId ( key ) , toFileIdListId ( newValue ) ] ;
778
+ return [ toFileId ( key ) , toFileIdListId ( state . exportedModulesMap ! . get ( key ) ! ) ] ;
779
779
} ) ;
780
780
}
781
781
@@ -1253,8 +1253,8 @@ namespace ts {
1253
1253
const state : ReusableBuilderProgramState = {
1254
1254
fileInfos,
1255
1255
compilerOptions : program . options ? convertToOptionsWithAbsolutePaths ( program . options , toAbsolutePath ) : { } ,
1256
- referencedMap : toMapOfReferencedSet ( program . referencedMap ) ,
1257
- exportedModulesMap : toMapOfReferencedSet ( program . exportedModulesMap ) ,
1256
+ referencedMap : toTwoWayMap ( program . referencedMap ) ,
1257
+ exportedModulesMap : toTwoWayMap ( program . exportedModulesMap ) ,
1258
1258
semanticDiagnosticsPerFile : program . semanticDiagnosticsPerFile && arrayToMap ( program . semanticDiagnosticsPerFile , value => toFilePath ( isNumber ( value ) ? value : value [ 0 ] ) , value => isNumber ( value ) ? emptyArray : value [ 1 ] ) ,
1259
1259
hasReusableDiagnostic : true ,
1260
1260
affectedFilesPendingEmit : map ( program . affectedFilesPendingEmit , value => toFilePath ( value [ 0 ] ) ) ,
@@ -1302,8 +1302,16 @@ namespace ts {
1302
1302
return filePathsSetList ! [ fileIdsListId - 1 ] ;
1303
1303
}
1304
1304
1305
- function toMapOfReferencedSet ( referenceMap : ProgramBuildInfoReferencedMap | undefined ) : ReadonlyESMap < Path , BuilderState . ReferencedSet > | undefined {
1306
- return referenceMap && arrayToMap ( referenceMap , value => toFilePath ( value [ 0 ] ) , value => toFilePathsSet ( value [ 1 ] ) ) ;
1305
+ function toTwoWayMap ( referenceMap : ProgramBuildInfoReferencedMap | undefined ) : BuilderState . TwoWayMap < Path , Path > | undefined {
1306
+ if ( ! referenceMap ) {
1307
+ return undefined ;
1308
+ }
1309
+
1310
+ const map = BuilderState . createTwoWayMap < Path , Path > ( ) ;
1311
+ referenceMap . forEach ( ( [ fileId , fileIdListId ] ) =>
1312
+ map . set ( toFilePath ( fileId ) , toFilePathsSet ( fileIdListId ) )
1313
+ ) ;
1314
+ return map ;
1307
1315
}
1308
1316
}
1309
1317
0 commit comments