@@ -594,7 +594,7 @@ namespace ts {
594594 let diagnosticsProducingTypeChecker : TypeChecker ;
595595 let noDiagnosticsTypeChecker : TypeChecker ;
596596 let classifiableNames : UnderscoreEscapedMap < true > ;
597- let modifiedFilePaths : Path [ ] | undefined ;
597+ const ambientModuleNameToUnmodifiedFileName = createMap < string > ( ) ;
598598
599599 const cachedSemanticDiagnosticsForFile : DiagnosticCache < Diagnostic > = { } ;
600600 const cachedDeclarationDiagnosticsForFile : DiagnosticCache < DiagnosticWithLocation > = { } ;
@@ -880,21 +880,14 @@ namespace ts {
880880 return classifiableNames ;
881881 }
882882
883- interface OldProgramState {
884- program : Program | undefined ;
885- oldSourceFile : SourceFile | undefined ;
886- /** The collection of paths modified *since* the old program. */
887- modifiedFilePaths : Path [ ] | undefined ;
888- }
889-
890- function resolveModuleNamesReusingOldState ( moduleNames : string [ ] , containingFile : string , file : SourceFile , oldProgramState : OldProgramState ) {
883+ function resolveModuleNamesReusingOldState ( moduleNames : string [ ] , containingFile : string , file : SourceFile ) {
891884 if ( structuralIsReused === StructureIsReused . Not && ! file . ambientModuleNames . length ) {
892885 // If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
893886 // the best we can do is fallback to the default logic.
894887 return resolveModuleNamesWorker ( moduleNames , containingFile , /*reusedNames*/ undefined , getResolvedProjectReferenceToRedirect ( file . originalFileName ) ) ;
895888 }
896889
897- const oldSourceFile = oldProgramState . program && oldProgramState . program . getSourceFile ( containingFile ) ;
890+ const oldSourceFile = oldProgram && oldProgram . getSourceFile ( containingFile ) ;
898891 if ( oldSourceFile !== file && file . resolvedModules ) {
899892 // `file` was created for the new program.
900893 //
@@ -958,7 +951,7 @@ namespace ts {
958951 }
959952 }
960953 else {
961- resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile ( moduleName , oldProgramState ) ;
954+ resolvesToAmbientModuleInNonModifiedFile = moduleNameResolvesToAmbientModuleInNonModifiedFile ( moduleName ) ;
962955 }
963956
964957 if ( resolvesToAmbientModuleInNonModifiedFile ) {
@@ -1001,12 +994,9 @@ namespace ts {
1001994
1002995 // If we change our policy of rechecking failed lookups on each program create,
1003996 // we should adjust the value returned here.
1004- function moduleNameResolvesToAmbientModuleInNonModifiedFile ( moduleName : string , oldProgramState : OldProgramState ) : boolean {
1005- if ( ! oldProgramState . program ) {
1006- return false ;
1007- }
1008- const resolutionToFile = getResolvedModule ( oldProgramState . oldSourceFile ! , moduleName ) ; // TODO: GH#18217
1009- const resolvedFile = resolutionToFile && oldProgramState . program . getSourceFile ( resolutionToFile . resolvedFileName ) ;
997+ function moduleNameResolvesToAmbientModuleInNonModifiedFile ( moduleName : string ) : boolean {
998+ const resolutionToFile = getResolvedModule ( oldSourceFile ! , moduleName ) ;
999+ const resolvedFile = resolutionToFile && oldProgram ! . getSourceFile ( resolutionToFile . resolvedFileName ) ;
10101000 if ( resolutionToFile && resolvedFile && ! resolvedFile . externalModuleIndicator ) {
10111001 // In the old program, we resolved to an ambient module that was in the same
10121002 // place as we expected to find an actual module file.
@@ -1016,16 +1006,14 @@ namespace ts {
10161006 }
10171007
10181008 // at least one of declarations should come from non-modified source file
1019- const firstUnmodifiedFile = oldProgramState . program . getSourceFiles ( ) . find (
1020- f => ! contains ( oldProgramState . modifiedFilePaths , f . path ) && contains ( f . ambientModuleNames , moduleName )
1021- ) ;
1009+ const unmodifiedFile = ambientModuleNameToUnmodifiedFileName . get ( moduleName ) ;
10221010
1023- if ( ! firstUnmodifiedFile ) {
1011+ if ( ! unmodifiedFile ) {
10241012 return false ;
10251013 }
10261014
10271015 if ( isTraceEnabled ( options , host ) ) {
1028- trace ( host , Diagnostics . Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified , moduleName , firstUnmodifiedFile . fileName ) ;
1016+ trace ( host , Diagnostics . Module_0_was_resolved_as_ambient_module_declared_in_1_since_this_file_was_not_modified , moduleName , unmodifiedFile ) ;
10291017 }
10301018 return true ;
10311019 }
@@ -1213,14 +1201,20 @@ namespace ts {
12131201 return oldProgram . structureIsReused ;
12141202 }
12151203
1216- modifiedFilePaths = modifiedSourceFiles . map ( f => f . newFile . path ) ;
1204+ const modifiedFiles = modifiedSourceFiles . map ( f => f . oldFile ) ;
1205+ for ( const oldFile of oldSourceFiles ) {
1206+ if ( ! contains ( modifiedFiles , oldFile ) ) {
1207+ for ( const moduleName of oldFile . ambientModuleNames ) {
1208+ ambientModuleNameToUnmodifiedFileName . set ( moduleName , oldFile . fileName ) ;
1209+ }
1210+ }
1211+ }
12171212 // try to verify results of module resolution
12181213 for ( const { oldFile : oldSourceFile , newFile : newSourceFile } of modifiedSourceFiles ) {
12191214 const newSourceFilePath = getNormalizedAbsolutePath ( newSourceFile . originalFileName , currentDirectory ) ;
12201215 if ( resolveModuleNamesWorker ) {
12211216 const moduleNames = getModuleNames ( newSourceFile ) ;
1222- const oldProgramState : OldProgramState = { program : oldProgram , oldSourceFile, modifiedFilePaths } ;
1223- const resolutions = resolveModuleNamesReusingOldState ( moduleNames , newSourceFilePath , newSourceFile , oldProgramState ) ;
1217+ const resolutions = resolveModuleNamesReusingOldState ( moduleNames , newSourceFilePath , newSourceFile ) ;
12241218 // ensure that module resolution results are still correct
12251219 const resolutionsChanged = hasChangesInResolutions ( moduleNames , resolutions , oldSourceFile . resolvedModules , moduleResolutionIsEqualTo ) ;
12261220 if ( resolutionsChanged ) {
@@ -2432,8 +2426,7 @@ namespace ts {
24322426 if ( file . imports . length || file . moduleAugmentations . length ) {
24332427 // Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
24342428 const moduleNames = getModuleNames ( file ) ;
2435- const oldProgramState : OldProgramState = { program : oldProgram , oldSourceFile : oldProgram && oldProgram . getSourceFile ( file . fileName ) , modifiedFilePaths } ;
2436- const resolutions = resolveModuleNamesReusingOldState ( moduleNames , getNormalizedAbsolutePath ( file . originalFileName , currentDirectory ) , file , oldProgramState ) ;
2429+ const resolutions = resolveModuleNamesReusingOldState ( moduleNames , getNormalizedAbsolutePath ( file . originalFileName , currentDirectory ) , file ) ;
24372430 Debug . assert ( resolutions . length === moduleNames . length ) ;
24382431 for ( let i = 0 ; i < moduleNames . length ; i ++ ) {
24392432 const resolution = resolutions [ i ] ;
0 commit comments