@@ -28,6 +28,7 @@ namespace ts {
2828 interface ResolutionWithFailedLookupLocations {
2929 readonly failedLookupLocations : ReadonlyArray < string > ;
3030 isInvalidated ?: boolean ;
31+ refCount ?: number ;
3132 }
3233
3334 interface ResolutionWithResolvedFileName {
@@ -257,17 +258,11 @@ namespace ts {
257258 perDirectoryResolution . set ( name , resolution ) ;
258259 }
259260 resolutionsInFile . set ( name , resolution ) ;
260- if ( resolution . failedLookupLocations ) {
261- if ( existingResolution && existingResolution . failedLookupLocations ) {
262- watchAndStopWatchDiffFailedLookupLocations ( resolution , existingResolution ) ;
263- }
264- else {
265- watchFailedLookupLocationOfResolution ( resolution , 0 ) ;
266- }
267- }
268- else if ( existingResolution ) {
261+ watchFailedLookupLocationOfResolution ( resolution ) ;
262+ if ( existingResolution ) {
269263 stopWatchFailedLookupLocationOfResolution ( existingResolution ) ;
270264 }
265+
271266 if ( logChanges && filesWithChangedSetOfUnresolvedImports && ! resolutionIsEqualTo ( existingResolution , resolution ) ) {
272267 filesWithChangedSetOfUnresolvedImports . push ( path ) ;
273268 // reset log changes to avoid recording the same file multiple times
@@ -399,80 +394,98 @@ namespace ts {
399394 return fileExtensionIsOneOf ( path , failedLookupDefaultExtensions ) ;
400395 }
401396
402- function watchAndStopWatchDiffFailedLookupLocations ( resolution : ResolutionWithFailedLookupLocations , existingResolution : ResolutionWithFailedLookupLocations ) {
403- const failedLookupLocations = resolution . failedLookupLocations ;
404- const existingFailedLookupLocations = existingResolution . failedLookupLocations ;
405- for ( let index = 0 ; index < failedLookupLocations . length ; index ++ ) {
406- if ( index === existingFailedLookupLocations . length ) {
407- // Additional failed lookup locations, watch from this index
408- watchFailedLookupLocationOfResolution ( resolution , index ) ;
409- return ;
410- }
411- else if ( failedLookupLocations [ index ] !== existingFailedLookupLocations [ index ] ) {
412- // Different failed lookup locations,
413- // Watch new resolution failed lookup locations from this index and
414- // stop watching existing resolutions from this index
415- watchFailedLookupLocationOfResolution ( resolution , index ) ;
416- stopWatchFailedLookupLocationOfResolutionFrom ( existingResolution , index ) ;
417- return ;
418- }
397+ function watchFailedLookupLocationOfResolution ( resolution : ResolutionWithFailedLookupLocations ) {
398+ // No need to set the resolution refCount
399+ if ( ! resolution . failedLookupLocations || ! resolution . failedLookupLocations . length ) {
400+ return ;
419401 }
420402
421- // All new failed lookup locations are already watched (and are same),
422- // Stop watching failed lookup locations of existing resolution after failed lookup locations length
423- stopWatchFailedLookupLocationOfResolutionFrom ( existingResolution , failedLookupLocations . length ) ;
424- }
403+ if ( resolution . refCount !== undefined ) {
404+ resolution . refCount ++ ;
405+ return ;
406+ }
425407
426- function watchFailedLookupLocationOfResolution ( { failedLookupLocations } : ResolutionWithFailedLookupLocations , startIndex : number ) {
427- for ( let i = startIndex ; i < failedLookupLocations . length ; i ++ ) {
428- const failedLookupLocation = failedLookupLocations [ i ] ;
408+ resolution . refCount = 1 ;
409+ const { failedLookupLocations } = resolution ;
410+ let setAtRoot = false ;
411+ for ( const failedLookupLocation of failedLookupLocations ) {
429412 const failedLookupLocationPath = resolutionHost . toPath ( failedLookupLocation ) ;
430- // If the failed lookup location path is not one of the supported extensions,
431- // store it in the custom path
432- if ( ! isPathWithDefaultFailedLookupExtension ( failedLookupLocationPath ) ) {
433- const refCount = customFailedLookupPaths . get ( failedLookupLocationPath ) || 0 ;
434- customFailedLookupPaths . set ( failedLookupLocationPath , refCount + 1 ) ;
435- }
436413 const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation ( failedLookupLocation , failedLookupLocationPath ) ;
437414 if ( ! ignore ) {
438- const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
439- if ( dirWatcher ) {
440- dirWatcher . refCount ++ ;
415+ // If the failed lookup location path is not one of the supported extensions,
416+ // store it in the custom path
417+ if ( ! isPathWithDefaultFailedLookupExtension ( failedLookupLocationPath ) ) {
418+ const refCount = customFailedLookupPaths . get ( failedLookupLocationPath ) || 0 ;
419+ customFailedLookupPaths . set ( failedLookupLocationPath , refCount + 1 ) ;
420+ }
421+ if ( dirPath === rootPath ) {
422+ setAtRoot = true ;
441423 }
442424 else {
443- directoryWatchesOfFailedLookups . set ( dirPath , { watcher : createDirectoryWatcher ( dir , dirPath ) , refCount : 1 } ) ;
425+ setDirectoryWatcher ( dir , dirPath ) ;
444426 }
445427 }
446428 }
429+
430+ if ( setAtRoot ) {
431+ setDirectoryWatcher ( rootDir , rootPath ) ;
432+ }
447433 }
448434
449- function stopWatchFailedLookupLocationOfResolution ( resolution : ResolutionWithFailedLookupLocations ) {
450- if ( resolution . failedLookupLocations ) {
451- stopWatchFailedLookupLocationOfResolutionFrom ( resolution , 0 ) ;
435+ function setDirectoryWatcher ( dir : string , dirPath : Path ) {
436+ const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
437+ if ( dirWatcher ) {
438+ dirWatcher . refCount ++ ;
439+ }
440+ else {
441+ directoryWatchesOfFailedLookups . set ( dirPath , { watcher : createDirectoryWatcher ( dir , dirPath ) , refCount : 1 } ) ;
452442 }
453443 }
454444
455- function stopWatchFailedLookupLocationOfResolutionFrom ( { failedLookupLocations } : ResolutionWithFailedLookupLocations , startIndex : number ) {
456- for ( let i = startIndex ; i < failedLookupLocations . length ; i ++ ) {
457- const failedLookupLocation = failedLookupLocations [ i ] ;
445+ function stopWatchFailedLookupLocationOfResolution ( resolution : ResolutionWithFailedLookupLocations ) {
446+ if ( ! resolution . failedLookupLocations || ! resolution . failedLookupLocations . length ) {
447+ return ;
448+ }
449+
450+ resolution . refCount ! -- ;
451+ if ( resolution . refCount ) {
452+ return ;
453+ }
454+
455+ const { failedLookupLocations } = resolution ;
456+ let removeAtRoot = false ;
457+ for ( const failedLookupLocation of failedLookupLocations ) {
458458 const failedLookupLocationPath = resolutionHost . toPath ( failedLookupLocation ) ;
459- const refCount = customFailedLookupPaths . get ( failedLookupLocationPath ) ;
460- if ( refCount ) {
461- if ( refCount === 1 ) {
462- customFailedLookupPaths . delete ( failedLookupLocationPath ) ;
459+ const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation ( failedLookupLocation , failedLookupLocationPath ) ;
460+ if ( ! ignore ) {
461+ const refCount = customFailedLookupPaths . get ( failedLookupLocationPath ) ;
462+ if ( refCount ) {
463+ if ( refCount === 1 ) {
464+ customFailedLookupPaths . delete ( failedLookupLocationPath ) ;
465+ }
466+ else {
467+ Debug . assert ( refCount > 1 ) ;
468+ customFailedLookupPaths . set ( failedLookupLocationPath , refCount - 1 ) ;
469+ }
470+ }
471+
472+ if ( dirPath === rootPath ) {
473+ removeAtRoot = true ;
463474 }
464475 else {
465- Debug . assert ( refCount > 1 ) ;
466- customFailedLookupPaths . set ( failedLookupLocationPath , refCount - 1 ) ;
476+ removeDirectoryWatcher ( dirPath ) ;
467477 }
468478 }
469- const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation ( failedLookupLocation , failedLookupLocationPath ) ;
470- if ( ! ignore ) {
471- const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
472- // Do not close the watcher yet since it might be needed by other failed lookup locations.
473- dirWatcher . refCount -- ;
474- }
475479 }
480+ if ( removeAtRoot ) {
481+ removeDirectoryWatcher ( rootPath ) ;
482+ }
483+ }
484+
485+ function removeDirectoryWatcher ( dirPath : string ) {
486+ const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
487+ // Do not close the watcher yet since it might be needed by other failed lookup locations.
488+ dirWatcher . refCount -- ;
476489 }
477490
478491 function createDirectoryWatcher ( directory : string , dirPath : Path ) {
0 commit comments