55namespace ts {
66 /** This is the cache of module/typedirectives resolution that can be retained across program */
77 export interface ResolutionCache {
8- setModuleResolutionHost ( host : ModuleResolutionHost ) : void ;
9-
108 startRecordingFilesWithChangedResolutions ( ) : void ;
119 finishRecordingFilesWithChangedResolutions ( ) : Path [ ] ;
1210
1311 resolveModuleNames ( moduleNames : string [ ] , containingFile : string , logChanges : boolean ) : ResolvedModuleFull [ ] ;
1412 resolveTypeReferenceDirectives ( typeDirectiveNames : string [ ] , containingFile : string ) : ResolvedTypeReferenceDirective [ ] ;
1513
1614 invalidateResolutionOfFile ( filePath : Path ) : void ;
17- onFileAddOrRemoveInDirectoryOfFailedLookup ( fileOrFolder : Path ) : boolean ;
18-
1915 createHasInvalidatedResolution ( ) : HasInvalidatedResolution ;
2016
2117 clear ( ) : void ;
@@ -33,15 +29,17 @@ namespace ts {
3329 mapLocations : MultiMap < string > ;
3430 }
3531
36- export function createResolutionCache (
37- toPath : ( fileName : string ) => Path ,
38- getCompilerOptions : ( ) => CompilerOptions ,
39- watchDirectoryOfFailedLookupLocation : ( directory : string ) => FileWatcher ,
40- log : ( s : string ) => void ,
41- projectName ?: string ,
42- getGlobalCache ?: ( ) => string | undefined ) : ResolutionCache {
32+ export interface ResolutionCacheHost extends ModuleResolutionHost {
33+ toPath ( fileName : string ) : Path ;
34+ getCompilationSettings ( ) : CompilerOptions ;
35+ watchDirectoryOfFailedLookupLocation ( directory : string , cb : DirectoryWatcherCallback ) : FileWatcher ;
36+ onInvalidatedResolution ( ) : void ;
37+ getCachedPartialSystem ?( ) : CachedPartialSystem ;
38+ projectName ?: string ;
39+ getGlobalCache ?( ) : string | undefined ;
40+ }
4341
44- let host : ModuleResolutionHost ;
42+ export function createResolutionCache ( resolutionHost : ResolutionCacheHost ) : ResolutionCache {
4543 let filesWithChangedSetOfUnresolvedImports : Path [ ] | undefined ;
4644 let filesWithInvalidatedResolutions : Map < true > | undefined ;
4745
@@ -52,23 +50,16 @@ namespace ts {
5250 const resolvedTypeReferenceDirectives = createMap < Map < ResolvedTypeReferenceDirectiveWithFailedLookupLocations > > ( ) ;
5351
5452 const directoryWatchesOfFailedLookups = createMap < DirectoryWatchesOfFailedLookup > ( ) ;
55-
5653 return {
57- setModuleResolutionHost,
5854 startRecordingFilesWithChangedResolutions,
5955 finishRecordingFilesWithChangedResolutions,
6056 resolveModuleNames,
6157 resolveTypeReferenceDirectives,
6258 invalidateResolutionOfFile,
63- onFileAddOrRemoveInDirectoryOfFailedLookup,
6459 createHasInvalidatedResolution,
6560 clear
6661 } ;
6762
68- function setModuleResolutionHost ( updatedHost : ModuleResolutionHost ) {
69- host = updatedHost ;
70- }
71-
7263 function clear ( ) {
7364 // Close all the watches for failed lookup locations, irrespective of refcounts for them since this is to clear the cache
7465 clearMap ( directoryWatchesOfFailedLookups , closeFileWatcherOf ) ;
@@ -95,16 +86,16 @@ namespace ts {
9586 function resolveModuleName ( moduleName : string , containingFile : string , compilerOptions : CompilerOptions , host : ModuleResolutionHost ) : ResolvedModuleWithFailedLookupLocations {
9687 const primaryResult = ts . resolveModuleName ( moduleName , containingFile , compilerOptions , host ) ;
9788 // return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts
98- if ( ! getGlobalCache ) {
89+ if ( ! resolutionHost . getGlobalCache ) {
9990 return primaryResult ;
10091 }
10192
10293 // otherwise try to load typings from @types
103- const globalCache = getGlobalCache ( ) ;
94+ const globalCache = resolutionHost . getGlobalCache ( ) ;
10495 if ( globalCache !== undefined && ! isExternalModuleNameRelative ( moduleName ) && ! ( primaryResult . resolvedModule && extensionIsTypeScript ( primaryResult . resolvedModule . extension ) ) ) {
10596 // create different collection of failed lookup locations for second pass
10697 // if it will fail and we've already found something during the first pass - we don't want to pollute its results
107- const { resolvedModule, failedLookupLocations } = loadModuleFromGlobalCache ( moduleName , projectName , compilerOptions , host , globalCache ) ;
98+ const { resolvedModule, failedLookupLocations } = loadModuleFromGlobalCache ( moduleName , resolutionHost . projectName , compilerOptions , host , globalCache ) ;
10899 if ( resolvedModule ) {
109100 return { resolvedModule, failedLookupLocations : addRange ( primaryResult . failedLookupLocations as Array < string > , failedLookupLocations ) } ;
110101 }
@@ -123,12 +114,12 @@ namespace ts {
123114 getResultFileName : ( result : R ) => string | undefined ,
124115 logChanges : boolean ) : R [ ] {
125116
126- const path = toPath ( containingFile ) ;
117+ const path = resolutionHost . toPath ( containingFile ) ;
127118 const currentResolutionsInFile = cache . get ( path ) ;
128119
129120 const newResolutions : Map < T > = createMap < T > ( ) ;
130121 const resolvedModules : R [ ] = [ ] ;
131- const compilerOptions = getCompilerOptions ( ) ;
122+ const compilerOptions = resolutionHost . getCompilationSettings ( ) ;
132123
133124 for ( const name of names ) {
134125 // check if this is a duplicate entry in the list
@@ -140,7 +131,7 @@ namespace ts {
140131 resolution = existingResolution ;
141132 }
142133 else {
143- resolution = loader ( name , containingFile , compilerOptions , host ) ;
134+ resolution = loader ( name , containingFile , compilerOptions , resolutionHost ) ;
144135 updateFailedLookupLocationWatches ( resolution . failedLookupLocations , existingResolution && existingResolution . failedLookupLocations ) ;
145136 }
146137 newResolutions . set ( name , resolution ) ;
@@ -214,12 +205,31 @@ namespace ts {
214205 const mapLocations = createMultiMap < string > ( ) ;
215206 mapLocations . add ( failedLookupLocationPath , failedLookupLocation ) ;
216207 directoryWatchesOfFailedLookups . set ( dirPath , {
217- watcher : watchDirectoryOfFailedLookupLocation ( getDirectoryPath ( failedLookupLocation ) ) ,
208+ watcher : createDirectoryWatcher ( getDirectoryPath ( failedLookupLocation ) , dirPath ) ,
218209 mapLocations
219210 } ) ;
220211 }
221212 }
222213
214+ function createDirectoryWatcher ( directory : string , dirPath : Path ) {
215+ return resolutionHost . watchDirectoryOfFailedLookupLocation ( directory , fileOrFolder => {
216+ const fileOrFolderPath = resolutionHost . toPath ( fileOrFolder ) ;
217+ if ( resolutionHost . getCachedPartialSystem ) {
218+ // Since the file existance changed, update the sourceFiles cache
219+ resolutionHost . getCachedPartialSystem ( ) . addOrDeleteFileOrFolder ( fileOrFolder , fileOrFolderPath ) ;
220+ }
221+
222+ // If the location results in update to failed lookup, schedule program update
223+ if ( dirPath === fileOrFolderPath ) {
224+ onAddOrRemoveDirectoryOfFailedLookup ( dirPath ) ;
225+ resolutionHost . onInvalidatedResolution ( ) ;
226+ }
227+ else if ( onFileAddOrRemoveInDirectoryOfFailedLookup ( fileOrFolderPath ) ) {
228+ resolutionHost . onInvalidatedResolution ( ) ;
229+ }
230+ } ) ;
231+ }
232+
223233 function closeFailedLookupLocationWatcher ( failedLookupLocation : string , failedLookupLocationPath : Path ) {
224234 const dirPath = getDirectoryPath ( failedLookupLocationPath ) ;
225235 const watches = directoryWatchesOfFailedLookups . get ( dirPath ) ;
@@ -234,13 +244,12 @@ namespace ts {
234244 function withFailedLookupLocations ( failedLookupLocations : ReadonlyArray < string > | undefined , fn : FailedLookupLocationAction , startIndex ?: number ) {
235245 if ( failedLookupLocations ) {
236246 for ( let i = startIndex || 0 ; i < failedLookupLocations . length ; i ++ ) {
237- fn ( failedLookupLocations [ i ] , toPath ( failedLookupLocations [ i ] ) ) ;
247+ fn ( failedLookupLocations [ i ] , resolutionHost . toPath ( failedLookupLocations [ i ] ) ) ;
238248 }
239249 }
240250 }
241251
242252 function updateFailedLookupLocationWatches ( failedLookupLocations : ReadonlyArray < string > | undefined , existingFailedLookupLocations : ReadonlyArray < string > | undefined ) {
243- log ( `Resolution cache: Updating...` ) ;
244253 const index = existingFailedLookupLocations && failedLookupLocations ?
245254 findDiffIndex ( failedLookupLocations , existingFailedLookupLocations ) :
246255 0 ;
@@ -269,7 +278,7 @@ namespace ts {
269278 if ( resolution && ! resolution . isInvalidated ) {
270279 const result = getResult ( resolution ) ;
271280 if ( result ) {
272- if ( toPath ( getResultFileName ( result ) ) === deletedFilePath ) {
281+ if ( resolutionHost . toPath ( getResultFileName ( result ) ) === deletedFilePath ) {
273282 resolution . isInvalidated = true ;
274283 ( filesWithInvalidatedResolutions || ( filesWithInvalidatedResolutions = createMap < true > ( ) ) ) . set ( path , true ) ;
275284 }
@@ -281,12 +290,13 @@ namespace ts {
281290 }
282291
283292 function invalidateResolutionCacheOfChangedFailedLookupLocation < T extends NameResolutionWithFailedLookupLocations > (
284- failedLookupLocationPath : Path ,
285- cache : Map < Map < T > > ) {
293+ cache : Map < Map < T > > ,
294+ isChangedFailedLookupLocation : ( location : string ) => boolean
295+ ) {
286296 cache . forEach ( ( value , containingFile ) => {
287297 if ( value ) {
288298 value . forEach ( resolution => {
289- if ( resolution && ! resolution . isInvalidated && some ( resolution . failedLookupLocations , location => toPath ( location ) === failedLookupLocationPath ) ) {
299+ if ( resolution && ! resolution . isInvalidated && some ( resolution . failedLookupLocations , isChangedFailedLookupLocation ) ) {
290300 // Mark the file as needing re-evaluation of module resolution instead of using it blindly.
291301 resolution . isInvalidated = true ;
292302 ( filesWithInvalidatedResolutions || ( filesWithInvalidatedResolutions = createMap < true > ( ) ) ) . set ( containingFile , true ) ;
@@ -306,10 +316,17 @@ namespace ts {
306316 const watches = directoryWatchesOfFailedLookups . get ( dirPath ) ;
307317 const isFailedLookupFile = watches . mapLocations . has ( fileOrFolder ) ;
308318 if ( isFailedLookupFile ) {
309- invalidateResolutionCacheOfChangedFailedLookupLocation ( fileOrFolder , resolvedModuleNames ) ;
310- invalidateResolutionCacheOfChangedFailedLookupLocation ( fileOrFolder , resolvedTypeReferenceDirectives ) ;
319+ const isFileOrFolder : ( location : string ) => boolean = location => resolutionHost . toPath ( location ) === fileOrFolder ;
320+ invalidateResolutionCacheOfChangedFailedLookupLocation ( resolvedModuleNames , isFileOrFolder ) ;
321+ invalidateResolutionCacheOfChangedFailedLookupLocation ( resolvedTypeReferenceDirectives , isFileOrFolder ) ;
311322 }
312323 return isFailedLookupFile ;
313324 }
325+
326+ function onAddOrRemoveDirectoryOfFailedLookup ( dirPath : Path ) {
327+ const isInDirPath : ( location : string ) => boolean = location => getDirectoryPath ( resolutionHost . toPath ( location ) ) === dirPath ;
328+ invalidateResolutionCacheOfChangedFailedLookupLocation ( resolvedModuleNames , isInDirPath ) ;
329+ invalidateResolutionCacheOfChangedFailedLookupLocation ( resolvedTypeReferenceDirectives , isInDirPath ) ;
330+ }
314331 }
315332}
0 commit comments