In recursive directory watching ignore folders and files in node_modules starting with "."

Fixes #30004
This commit is contained in:
Sheetal Nandi
2019-03-06 14:46:14 -08:00
parent d2364f555f
commit 79a1f29727
2 changed files with 72 additions and 1 deletions

View File

@@ -371,6 +371,8 @@ namespace ts {
else {
directoryWatcher = {
watcher: host.watchDirectory(dirName, fileName => {
if (isInNodeModulesStartingWithDot(fileName)) return;
// Call the actual callback
callbackCache.forEach((callbacks, rootDirName) => {
if (rootDirName === dirPath || (startsWith(dirPath, rootDirName) && dirPath[rootDirName.length] === directorySeparator)) {
@@ -426,7 +428,7 @@ namespace ts {
const childFullName = getNormalizedAbsolutePath(child, parentDir);
// Filter our the symbolic link directories since those arent included in recursive watch
// which is same behaviour when recursive: true is passed to fs.watch
return filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
return !isInNodeModulesStartingWithDot(childFullName) && filePathComparer(childFullName, normalizePath(host.realpath(childFullName))) === Comparison.EqualTo ? childFullName : undefined;
}) : emptyArray,
existingChildWatches,
(child, childWatcher) => filePathComparer(child, childWatcher.dirName),
@@ -452,6 +454,16 @@ namespace ts {
(newChildWatches || (newChildWatches = [])).push(childWatcher);
}
}
function isInNodeModulesStartingWithDot(path: string) {
return isInPath(path, "/node_modules/.");
}
function isInPath(path: string, searchPath: string) {
if (stringContains(path, searchPath)) return true;
if (host.useCaseSensitiveFileNames) return false;
return stringContains(toCanonicalFilePath(path), searchPath);
}
}
// TODO: GH#18217 Methods on System are often used as if they are certainly defined

View File

@@ -132,4 +132,63 @@ namespace ts.projectSystem {
verifyRootedDirectoryWatch("c:/users/username/");
});
});
it(`unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem recursive watch directory implementation does not watch files/directories in node_modules starting with "."`, () => {
const projectFolder = "/a/username/project";
const projectSrcFolder = `${projectFolder}/src`;
const configFile: File = {
path: `${projectFolder}/tsconfig.json`,
content: "{}"
};
const index: File = {
path: `${projectSrcFolder}/index.ts`,
content: `import {} from "file"`
};
const file1: File = {
path: `${projectSrcFolder}/file1.ts`,
content: ""
};
const nodeModulesExistingUnusedFile: File = {
path: `${projectFolder}/node_modules/someFile.d.ts`,
content: ""
};
const fileNames = [index, file1, configFile, libFile].map(file => file.path);
// All closed files(files other than index), project folder, project/src folder and project/node_modules/@types folder
const expectedWatchedFiles = arrayToMap(fileNames.slice(1), identity, () => 1);
const expectedWatchedDirectories = arrayToMap([projectFolder, projectSrcFolder, `${projectFolder}/${nodeModules}`, `${projectFolder}/${nodeModulesAtTypes}`], identity, () => 1);
const environmentVariables = createMap<string>();
environmentVariables.set("TSC_WATCHDIRECTORY", Tsc_WatchDirectory.NonRecursiveWatchDirectory);
const host = createServerHost([index, file1, configFile, libFile, nodeModulesExistingUnusedFile], { environmentVariables });
const projectService = createProjectService(host);
projectService.openClientFile(index.path);
const project = Debug.assertDefined(projectService.configuredProjects.get(configFile.path));
verifyProject();
const nodeModulesIgnoredFileFromIgnoreDirectory: File = {
path: `${projectFolder}/node_modules/.cache/someFile.d.ts`,
content: ""
};
host.ensureFileOrFolder(nodeModulesIgnoredFileFromIgnoreDirectory);
host.checkTimeoutQueueLength(0);
verifyProject();
const nodeModulesIgnoredFile: File = {
path: `${projectFolder}/node_modules/.cacheFile.ts`,
content: ""
};
host.ensureFileOrFolder(nodeModulesIgnoredFile);
host.checkTimeoutQueueLength(0);
verifyProject();
function verifyProject() {
checkWatchedDirectories(host, emptyArray, /*recursive*/ true);
checkWatchedFilesDetailed(host, expectedWatchedFiles);
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, /*recursive*/ false);
checkProjectActualFiles(project, fileNames);
}
});
}