Do not watch root folders for failed lookup locations and effective type roots
Fixes #19170
This commit is contained in:
parent
3c452057c2
commit
50628e73c5
3 changed files with 148 additions and 70 deletions
|
@ -64,6 +64,7 @@ namespace ts {
|
|||
interface DirectoryOfFailedLookupWatch {
|
||||
dir: string;
|
||||
dirPath: Path;
|
||||
ignore?: true;
|
||||
}
|
||||
|
||||
export const maxNumberOfFilesToIterateForInvalidation = 256;
|
||||
|
@ -319,6 +320,33 @@ namespace ts {
|
|||
return endsWith(dirPath, "/node_modules");
|
||||
}
|
||||
|
||||
function isDirectoryAtleastAtLevelFromFSRoot(dirPath: Path, minLevels: number) {
|
||||
for (let searchIndex = getRootLength(dirPath); minLevels > 0; minLevels--) {
|
||||
searchIndex = dirPath.indexOf(directorySeparator, searchIndex) + 1;
|
||||
if (searchIndex === 0) {
|
||||
// Folder isnt at expected minimun levels
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function canWatchDirectory(dirPath: Path) {
|
||||
return isDirectoryAtleastAtLevelFromFSRoot(dirPath,
|
||||
// When root is "/" do not watch directories like:
|
||||
// "/", "/user", "/user/username", "/user/username/folderAtRoot"
|
||||
// When root is "c:/" do not watch directories like:
|
||||
// "c:/", "c:/folderAtRoot"
|
||||
dirPath.charCodeAt(0) === CharacterCodes.slash ? 3 : 1);
|
||||
}
|
||||
|
||||
function filterFSRootDirectoriesToWatch(watchPath: DirectoryOfFailedLookupWatch, dirPath: Path): DirectoryOfFailedLookupWatch {
|
||||
if (!canWatchDirectory(dirPath)) {
|
||||
watchPath.ignore = true;
|
||||
}
|
||||
return watchPath;
|
||||
}
|
||||
|
||||
function getDirectoryToWatchFailedLookupLocation(failedLookupLocation: string, failedLookupLocationPath: Path): DirectoryOfFailedLookupWatch {
|
||||
if (isInDirectoryPath(rootPath, failedLookupLocationPath)) {
|
||||
return { dir: rootDir, dirPath: rootPath };
|
||||
|
@ -335,7 +363,7 @@ namespace ts {
|
|||
|
||||
// If the directory is node_modules use it to watch
|
||||
if (isNodeModulesDirectory(dirPath)) {
|
||||
return { dir, dirPath };
|
||||
return filterFSRootDirectoriesToWatch({ dir, dirPath }, getDirectoryPath(dirPath));
|
||||
}
|
||||
|
||||
// Use some ancestor of the root directory
|
||||
|
@ -350,7 +378,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
return { dir, dirPath };
|
||||
return filterFSRootDirectoriesToWatch({ dir, dirPath }, dirPath);
|
||||
}
|
||||
|
||||
function isPathWithDefaultFailedLookupExtension(path: Path) {
|
||||
|
@ -391,13 +419,15 @@ namespace ts {
|
|||
const refCount = customFailedLookupPaths.get(failedLookupLocationPath) || 0;
|
||||
customFailedLookupPaths.set(failedLookupLocationPath, refCount + 1);
|
||||
}
|
||||
const { dir, dirPath } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
if (dirWatcher) {
|
||||
dirWatcher.refCount++;
|
||||
}
|
||||
else {
|
||||
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
|
||||
const { dir, dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
if (!ignore) {
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
if (dirWatcher) {
|
||||
dirWatcher.refCount++;
|
||||
}
|
||||
else {
|
||||
directoryWatchesOfFailedLookups.set(dirPath, { watcher: createDirectoryWatcher(dir, dirPath), refCount: 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -422,10 +452,12 @@ namespace ts {
|
|||
customFailedLookupPaths.set(failedLookupLocationPath, refCount - 1);
|
||||
}
|
||||
}
|
||||
const { dirPath } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
// Do not close the watcher yet since it might be needed by other failed lookup locations.
|
||||
dirWatcher.refCount--;
|
||||
const { dirPath, ignore } = getDirectoryToWatchFailedLookupLocation(failedLookupLocation, failedLookupLocationPath);
|
||||
if (!ignore) {
|
||||
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
|
||||
// Do not close the watcher yet since it might be needed by other failed lookup locations.
|
||||
dirWatcher.refCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,7 +609,8 @@ namespace ts {
|
|||
}
|
||||
|
||||
// we need to assume the directories exist to ensure that we can get all the type root directories that get included
|
||||
const typeRoots = getEffectiveTypeRoots(options, { directoryExists: returnTrue, getCurrentDirectory });
|
||||
// But filter directories that are at root level to say directory doesnt exist, so that we arent watching them
|
||||
const typeRoots = getEffectiveTypeRoots(options, { directoryExists: directoryExistsForTypeRootWatch, getCurrentDirectory });
|
||||
if (typeRoots) {
|
||||
mutateMap(
|
||||
typeRootsWatches,
|
||||
|
@ -592,5 +625,16 @@ namespace ts {
|
|||
closeTypeRootsWatch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this function to return if directory exists to get type roots to watch
|
||||
* If we return directory exists then only the paths will be added to type roots
|
||||
* Hence return true for all directories except root directories which are filtered from watching
|
||||
*/
|
||||
function directoryExistsForTypeRootWatch(nodeTypesDirectory: string) {
|
||||
const dir = getDirectoryPath(getDirectoryPath(nodeTypesDirectory));
|
||||
const dirPath = resolutionHost.toPath(dir);
|
||||
return dirPath === rootPath || canWatchDirectory(dirPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,7 +254,7 @@ namespace ts.tscWatch {
|
|||
checkProgramRootFiles(watch(), [file1.path, file2.path]);
|
||||
checkWatchedFiles(host, [configFile.path, file1.path, file2.path, libFile.path]);
|
||||
const configDir = getDirectoryPath(configFile.path);
|
||||
checkWatchedDirectories(host, projectSystem.getTypeRootsFromLocation(configDir).concat(configDir), /*recursive*/ true);
|
||||
checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true);
|
||||
});
|
||||
|
||||
// TODO: if watching for config file creation
|
||||
|
@ -269,7 +269,7 @@ namespace ts.tscWatch {
|
|||
const host = createWatchedSystem([commonFile1, libFile, configFile]);
|
||||
const watch = createWatchModeWithConfigFile(configFile.path, host);
|
||||
const configDir = getDirectoryPath(configFile.path);
|
||||
checkWatchedDirectories(host, projectSystem.getTypeRootsFromLocation(configDir).concat(configDir), /*recursive*/ true);
|
||||
checkWatchedDirectories(host, [configDir, combinePaths(configDir, projectSystem.nodeModulesAtTypes)], /*recursive*/ true);
|
||||
|
||||
checkProgramRootFiles(watch(), [commonFile1.path]);
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue