@@ -64,6 +64,7 @@ namespace ts {
64
64
interface DirectoryOfFailedLookupWatch {
65
65
dir : string ;
66
66
dirPath : Path ;
67
+ ignore ?: true ;
67
68
}
68
69
69
70
export const maxNumberOfFilesToIterateForInvalidation = 256 ;
@@ -319,6 +320,33 @@ namespace ts {
319
320
return endsWith ( dirPath , "/node_modules" ) ;
320
321
}
321
322
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
+
322
350
function getDirectoryToWatchFailedLookupLocation ( failedLookupLocation : string , failedLookupLocationPath : Path ) : DirectoryOfFailedLookupWatch {
323
351
if ( isInDirectoryPath ( rootPath , failedLookupLocationPath ) ) {
324
352
return { dir : rootDir , dirPath : rootPath } ;
@@ -335,7 +363,7 @@ namespace ts {
335
363
336
364
// If the directory is node_modules use it to watch
337
365
if ( isNodeModulesDirectory ( dirPath ) ) {
338
- return { dir, dirPath } ;
366
+ return filterFSRootDirectoriesToWatch ( { dir, dirPath } , getDirectoryPath ( dirPath ) ) ;
339
367
}
340
368
341
369
// Use some ancestor of the root directory
@@ -350,7 +378,7 @@ namespace ts {
350
378
}
351
379
}
352
380
353
- return { dir, dirPath } ;
381
+ return filterFSRootDirectoriesToWatch ( { dir, dirPath } , dirPath ) ;
354
382
}
355
383
356
384
function isPathWithDefaultFailedLookupExtension ( path : Path ) {
@@ -391,13 +419,15 @@ namespace ts {
391
419
const refCount = customFailedLookupPaths . get ( failedLookupLocationPath ) || 0 ;
392
420
customFailedLookupPaths . set ( failedLookupLocationPath , refCount + 1 ) ;
393
421
}
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
+ }
401
431
}
402
432
}
403
433
}
@@ -422,10 +452,12 @@ namespace ts {
422
452
customFailedLookupPaths . set ( failedLookupLocationPath , refCount - 1 ) ;
423
453
}
424
454
}
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
+ }
429
461
}
430
462
}
431
463
@@ -577,7 +609,8 @@ namespace ts {
577
609
}
578
610
579
611
// 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 } ) ;
581
614
if ( typeRoots ) {
582
615
mutateMap (
583
616
typeRootsWatches ,
@@ -592,5 +625,16 @@ namespace ts {
592
625
closeTypeRootsWatch ( ) ;
593
626
}
594
627
}
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
+ }
595
639
}
596
640
}
0 commit comments