@@ -64,6 +64,7 @@ namespace ts {
6464 interface DirectoryOfFailedLookupWatch {
6565 dir : string ;
6666 dirPath : Path ;
67+ ignore ?: true ;
6768 }
6869
6970 export const maxNumberOfFilesToIterateForInvalidation = 256 ;
@@ -319,6 +320,33 @@ namespace ts {
319320 return endsWith ( dirPath , "/node_modules" ) ;
320321 }
321322
323+ function isDirectoryAtleastAtLevelFromFSRoot ( dirPath : Path , minLevels : number ) {
324+ for ( let searchIndex = getRootLength ( dirPath ) ; minLevels > 0 ; minLevels -- ) {
325+ searchIndex = dirPath . indexOf ( directorySeparator , searchIndex ) + 1 ;
326+ if ( searchIndex === 0 ) {
327+ // Folder isnt at expected minimun levels
328+ return false ;
329+ }
330+ }
331+ return true ;
332+ }
333+
334+ function canWatchDirectory ( dirPath : Path ) {
335+ return isDirectoryAtleastAtLevelFromFSRoot ( dirPath ,
336+ // When root is "/" do not watch directories like:
337+ // "/", "/user", "/user/username", "/user/username/folderAtRoot"
338+ // When root is "c:/" do not watch directories like:
339+ // "c:/", "c:/folderAtRoot"
340+ dirPath . charCodeAt ( 0 ) === CharacterCodes . slash ? 3 : 1 ) ;
341+ }
342+
343+ function filterFSRootDirectoriesToWatch ( watchPath : DirectoryOfFailedLookupWatch , dirPath : Path ) : DirectoryOfFailedLookupWatch {
344+ if ( ! canWatchDirectory ( dirPath ) ) {
345+ watchPath . ignore = true ;
346+ }
347+ return watchPath ;
348+ }
349+
322350 function getDirectoryToWatchFailedLookupLocation ( failedLookupLocation : string , failedLookupLocationPath : Path ) : DirectoryOfFailedLookupWatch {
323351 if ( isInDirectoryPath ( rootPath , failedLookupLocationPath ) ) {
324352 return { dir : rootDir , dirPath : rootPath } ;
@@ -335,7 +363,7 @@ namespace ts {
335363
336364 // If the directory is node_modules use it to watch
337365 if ( isNodeModulesDirectory ( dirPath ) ) {
338- return { dir, dirPath } ;
366+ return filterFSRootDirectoriesToWatch ( { dir, dirPath } , getDirectoryPath ( dirPath ) ) ;
339367 }
340368
341369 // Use some ancestor of the root directory
@@ -350,7 +378,7 @@ namespace ts {
350378 }
351379 }
352380
353- return { dir, dirPath } ;
381+ return filterFSRootDirectoriesToWatch ( { dir, dirPath } , dirPath ) ;
354382 }
355383
356384 function isPathWithDefaultFailedLookupExtension ( path : Path ) {
@@ -391,13 +419,15 @@ namespace ts {
391419 const refCount = customFailedLookupPaths . get ( failedLookupLocationPath ) || 0 ;
392420 customFailedLookupPaths . set ( failedLookupLocationPath , refCount + 1 ) ;
393421 }
394- const { dir, dirPath } = getDirectoryToWatchFailedLookupLocation ( failedLookupLocation , failedLookupLocationPath ) ;
395- const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
396- if ( dirWatcher ) {
397- dirWatcher . refCount ++ ;
398- }
399- else {
400- directoryWatchesOfFailedLookups . set ( dirPath , { watcher : createDirectoryWatcher ( dir , dirPath ) , refCount : 1 } ) ;
422+ const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation ( failedLookupLocation , failedLookupLocationPath ) ;
423+ if ( ! ignore ) {
424+ const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
425+ if ( dirWatcher ) {
426+ dirWatcher . refCount ++ ;
427+ }
428+ else {
429+ directoryWatchesOfFailedLookups . set ( dirPath , { watcher : createDirectoryWatcher ( dir , dirPath ) , refCount : 1 } ) ;
430+ }
401431 }
402432 }
403433 }
@@ -422,10 +452,12 @@ namespace ts {
422452 customFailedLookupPaths . set ( failedLookupLocationPath , refCount - 1 ) ;
423453 }
424454 }
425- const { dirPath } = getDirectoryToWatchFailedLookupLocation ( failedLookupLocation , failedLookupLocationPath ) ;
426- const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
427- // Do not close the watcher yet since it might be needed by other failed lookup locations.
428- dirWatcher . refCount -- ;
455+ const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation ( failedLookupLocation , failedLookupLocationPath ) ;
456+ if ( ! ignore ) {
457+ const dirWatcher = directoryWatchesOfFailedLookups . get ( dirPath ) ;
458+ // Do not close the watcher yet since it might be needed by other failed lookup locations.
459+ dirWatcher . refCount -- ;
460+ }
429461 }
430462 }
431463
@@ -577,7 +609,8 @@ namespace ts {
577609 }
578610
579611 // we need to assume the directories exist to ensure that we can get all the type root directories that get included
580- const typeRoots = getEffectiveTypeRoots ( options , { directoryExists : returnTrue , getCurrentDirectory } ) ;
612+ // But filter directories that are at root level to say directory doesnt exist, so that we arent watching them
613+ const typeRoots = getEffectiveTypeRoots ( options , { directoryExists : directoryExistsForTypeRootWatch , getCurrentDirectory } ) ;
581614 if ( typeRoots ) {
582615 mutateMap (
583616 typeRootsWatches ,
@@ -592,5 +625,16 @@ namespace ts {
592625 closeTypeRootsWatch ( ) ;
593626 }
594627 }
628+
629+ /**
630+ * Use this function to return if directory exists to get type roots to watch
631+ * If we return directory exists then only the paths will be added to type roots
632+ * Hence return true for all directories except root directories which are filtered from watching
633+ */
634+ function directoryExistsForTypeRootWatch ( nodeTypesDirectory : string ) {
635+ const dir = getDirectoryPath ( getDirectoryPath ( nodeTypesDirectory ) ) ;
636+ const dirPath = resolutionHost . toPath ( dir ) ;
637+ return dirPath === rootPath || canWatchDirectory ( dirPath ) ;
638+ }
595639 }
596640}
0 commit comments