diff --git a/src/harness/unittests/tscWatchMode.ts b/src/harness/unittests/tscWatchMode.ts index 7b64e043eb6..82bfb7f4b89 100644 --- a/src/harness/unittests/tscWatchMode.ts +++ b/src/harness/unittests/tscWatchMode.ts @@ -2176,49 +2176,64 @@ declare module "fs" { } }); - it("watchingDirectories with watchFile", () => { - const projectFolder = "/a/username/project"; - const projectSrcFolder = `${projectFolder}/src`; - const configFile: FileOrFolder = { - path: `${projectFolder}/tsconfig.json`, - content: "{}" - }; - const file: FileOrFolder = { - path: `${projectSrcFolder}/file1.ts`, - content: "" - }; - const programFiles = [file, libFile]; - const files = [file, configFile, libFile]; - const environmentVariables = createMap(); - environmentVariables.set("TSC_WATCHDIRECTORY", "RecursiveDirectoryUsingFsWatchFile"); - const host = createWatchedSystem(files, { environmentVariables }); - const watch = createWatchModeWithConfigFile(configFile.path, host); - // Watching config file, file, lib file and directories - const expectedWatchedFiles = files.map(f => f.path).concat(projectFolder, projectSrcFolder, `${projectFolder}/node_modules/@types`); + describe("tsc-watch when watchDirectories implementation", () => { + function verifyRenamingFileInSubFolder(usesWatchFile: boolean) { + const projectFolder = "/a/username/project"; + const projectSrcFolder = `${projectFolder}/src`; + const configFile: FileOrFolder = { + path: `${projectFolder}/tsconfig.json`, + content: "{}" + }; + const file: FileOrFolder = { + path: `${projectSrcFolder}/file1.ts`, + content: "" + }; + const programFiles = [file, libFile]; + const files = [file, configFile, libFile]; + const environmentVariables = createMap(); + environmentVariables.set("TSC_WATCHDIRECTORY", usesWatchFile ? "RecursiveDirectoryUsingFsWatchFile" : "RecursiveDirectoryUsingNonRecursiveWatchDirectory"); + const host = createWatchedSystem(files, { environmentVariables }); + const watch = createWatchModeWithConfigFile(configFile.path, host); + const projectFolders = [projectFolder, projectSrcFolder, `${projectFolder}/node_modules/@types`]; + // Watching files config file, file, lib file + const expectedWatchedFiles = files.map(f => f.path); + const expectedWatchedDirectories = usesWatchFile ? [] : projectFolders; + if (usesWatchFile) { + expectedWatchedFiles.push(...projectFolders); + } - verifyProgram(checkOutputErrorsInitial); + verifyProgram(checkOutputErrorsInitial); - // Rename the file: - file.path = file.path.replace("file1.ts", "file2.ts"); - expectedWatchedFiles[0] = file.path; - host.reloadFS(files); - host.runQueuedTimeoutCallbacks(); - verifyProgram(checkOutputErrorsIncremental); + // Rename the file: + file.path = file.path.replace("file1.ts", "file2.ts"); + expectedWatchedFiles[0] = file.path; + host.reloadFS(files); + host.runQueuedTimeoutCallbacks(); + verifyProgram(checkOutputErrorsIncremental); - function verifyProgram(checkOutputErrors: (host: WatchedSystem, errors: ReadonlyArray) => void) { - checkWatchedDirectories(host, emptyArray, /*recursive*/ false); - checkWatchedDirectories(host, emptyArray, /*recursive*/ true); + function verifyProgram(checkOutputErrors: (host: WatchedSystem, errors: ReadonlyArray) => void) { + checkWatchedDirectories(host, emptyArray, /*recursive*/ true); - // Watching config file, file, lib file and directories - ts.TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedFiles", host.watchedFiles, expectedWatchedFiles, 1); + // Watching config file, file, lib file and directories + ts.TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedFiles", host.watchedFiles, expectedWatchedFiles, 1); + ts.TestFSWithWatch.checkMultiMapEachKeyWithCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories, 1); - checkProgramActualFiles(watch(), programFiles.map(f => f.path)); - checkOutputErrors(host, emptyArray); + checkProgramActualFiles(watch(), programFiles.map(f => f.path)); + checkOutputErrors(host, emptyArray); - const outputFile = changeExtension(file.path, ".js"); - assert(host.fileExists(outputFile)); - assert.equal(host.readFile(outputFile), file.content); + const outputFile = changeExtension(file.path, ".js"); + assert(host.fileExists(outputFile)); + assert.equal(host.readFile(outputFile), file.content); + } } + + it("uses watchFile when renaming file in subfolder", () => { + verifyRenamingFileInSubFolder(/*usesWatchFile*/ true); + }); + + it("uses non recursive watchDirectory when renaming file in subfolder", () => { + verifyRenamingFileInSubFolder(/*usesWatchFile*/ false); + }); }); }); } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index fdaebc4b054..b343a269c20 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -6580,8 +6580,8 @@ namespace ts.projectSystem { }); }); - describe("WatchingDirectories with polling", () => { - it("when file is added to subfolder, completion list has new file", () => { + describe("watchDirectories implementation", () => { + function verifyCompletionListWithNewFileInSubFolder(usesWatchFile: boolean) { const projectFolder = "/a/username/project"; const projectSrcFolder = `${projectFolder}/src`; const configFile: FileOrFolder = { @@ -6600,15 +6600,19 @@ namespace ts.projectSystem { const files = [index, file1, configFile, libFile]; const fileNames = files.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).concat(`${projectFolder}/${nodeModulesAtTypes}`), s => s, () => 1); + const expectedWatchedFiles = arrayToMap(fileNames.slice(1), s => s, () => 1); + const expectedWatchedDirectories = createMap(); + const mapOfDirectories = usesWatchFile ? expectedWatchedFiles : expectedWatchedDirectories; // For failed resolution lookup and tsconfig files - expectedWatchedFiles.set(projectFolder, 2); + mapOfDirectories.set(projectFolder, 2); // Through above recursive watches - expectedWatchedFiles.set(projectSrcFolder, 2); + mapOfDirectories.set(projectSrcFolder, 2); + // node_modules/@types folder + mapOfDirectories.set(`${projectFolder}/${nodeModulesAtTypes}`, 1); const expectedCompletions = ["file1"]; const completionPosition = index.content.lastIndexOf('"'); const environmentVariables = createMap(); - environmentVariables.set("TSC_WATCHDIRECTORY", "RecursiveDirectoryUsingFsWatchFile"); + environmentVariables.set("TSC_WATCHDIRECTORY", usesWatchFile ? "RecursiveDirectoryUsingFsWatchFile" : "RecursiveDirectoryUsingNonRecursiveWatchDirectory"); const host = createServerHost(files, { environmentVariables }); const projectService = createProjectService(host); projectService.openClientFile(index.path); @@ -6632,15 +6636,23 @@ namespace ts.projectSystem { verifyProjectAndCompletions(); function verifyProjectAndCompletions() { - checkWatchedDirectories(host, emptyArray, /*recursive*/ false); checkWatchedDirectories(host, emptyArray, /*recursive*/ true); ts.TestFSWithWatch.checkMultiMapKeyCount("watchedFiles", host.watchedFiles, expectedWatchedFiles); + ts.TestFSWithWatch.checkMultiMapKeyCount("watchedDirectories", host.watchedDirectories, expectedWatchedDirectories); checkProjectActualFiles(project, fileNames); const completions = project.getLanguageService().getCompletionsAtPosition(index.path, completionPosition, { includeExternalModuleExports: false, includeInsertTextCompletions: false }); checkArray("Completion Entries", completions.entries.map(e => e.name), expectedCompletions); } + } + + it("uses watchFile when file is added to subfolder, completion list has new file", () => { + verifyCompletionListWithNewFileInSubFolder(/*usesWatchFile*/ true); + }); + + it("uses non recursive watchDirectory when file is added to subfolder, completion list has new file", () => { + verifyCompletionListWithNewFileInSubFolder(/*usesWatchFile*/ false); }); }); }