diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 175b579103f..bc88a4b3837 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -5760,4 +5760,44 @@ namespace ts.projectSystem { } }); }); + + describe("Watched recursive directories with windows style file system", () => { + function verifyWatchedDirectories(useProjectAtRoot: boolean) { + const root = useProjectAtRoot ? "c:/" : "c:/myfolder/allproject/"; + const configFile: FileOrFolder = { + path: root + "project/tsconfig.json", + content: "{}" + }; + const file1: FileOrFolder = { + path: root + "project/file1.ts", + content: "let x = 10;" + }; + const file2: FileOrFolder = { + path: root + "project/file2.ts", + content: "let y = 10;" + }; + const files = [configFile, file1, file2, libFile]; + const host = createServerHost(files, { useWindowsStylePaths: true }); + const projectService = createProjectService(host); + projectService.openClientFile(file1.path); + const project = projectService.configuredProjects.get(configFile.path); + assert.isDefined(project); + const winsowsStyleLibFilePath = "c:/" + libFile.path.substring(1); + checkProjectActualFiles(project, files.map(f => f === libFile ? winsowsStyleLibFilePath : f.path)); + checkWatchedFiles(host, mapDefined(files, f => f === libFile ? winsowsStyleLibFilePath : f === file1 ? undefined : f.path)); + checkWatchedDirectories(host, [], /*recursive*/ false); + checkWatchedDirectories(host, [ + root + "project", + root + "project/node_modules/@types" + ].concat(useProjectAtRoot ? [] : [root + nodeModulesAtTypes]), /*recursive*/ true); + } + + it("When project is in rootFolder", () => { + verifyWatchedDirectories(/*useProjectAtRoot*/ true); + }); + + it("When files at some folder other than root", () => { + verifyWatchedDirectories(/*useProjectAtRoot*/ false); + }); + }); } diff --git a/src/harness/virtualFileSystemWithWatch.ts b/src/harness/virtualFileSystemWithWatch.ts index 67b3e264db4..4463bbac7a5 100644 --- a/src/harness/virtualFileSystemWithWatch.ts +++ b/src/harness/virtualFileSystemWithWatch.ts @@ -28,6 +28,7 @@ namespace ts.TestFSWithWatch { executingFilePath?: string; currentDirectory?: string; newLine?: string; + useWindowsStylePaths?: boolean; } export function createWatchedSystem(fileOrFolderList: ReadonlyArray, params?: TestServerHostCreationParameters): TestServerHost { @@ -39,7 +40,8 @@ namespace ts.TestFSWithWatch { params.executingFilePath || getExecutingFilePathFromLibFile(), params.currentDirectory || "/", fileOrFolderList, - params.newLine); + params.newLine, + params.useWindowsStylePaths); return host; } @@ -52,7 +54,8 @@ namespace ts.TestFSWithWatch { params.executingFilePath || getExecutingFilePathFromLibFile(), params.currentDirectory || "/", fileOrFolderList, - params.newLine); + params.newLine, + params.useWindowsStylePaths); return host; } @@ -230,11 +233,14 @@ namespace ts.TestFSWithWatch { readonly watchedDirectories = createMultiMap(); readonly watchedDirectoriesRecursive = createMultiMap(); readonly watchedFiles = createMultiMap(); + private readonly executingFilePath: string; + private readonly currentDirectory: string; - constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, private executingFilePath: string, private currentDirectory: string, fileOrFolderList: ReadonlyArray, public readonly newLine = "\n") { + constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderList: ReadonlyArray, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean) { this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames); this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName); - + this.executingFilePath = this.getHostSpecificPath(executingFilePath); + this.currentDirectory = this.getHostSpecificPath(currentDirectory); this.reloadFS(fileOrFolderList); } @@ -250,11 +256,24 @@ namespace ts.TestFSWithWatch { return this.toPath(this.toNormalizedAbsolutePath(s)); } + getHostSpecificPath(s: string) { + if (this.useWindowsStylePath && s.startsWith(directorySeparator)) { + return "c:/" + s.substring(1); + } + return s; + } + reloadFS(fileOrFolderList: ReadonlyArray) { const mapNewLeaves = createMap(); const isNewFs = this.fs.size === 0; - // always inject safelist file in the list of files - for (const fileOrDirectory of fileOrFolderList.concat(this.withSafeList ? safeList : [])) { + fileOrFolderList = fileOrFolderList.concat(this.withSafeList ? safeList : []); + const filesOrFoldersToLoad: ReadonlyArray = !this.useWindowsStylePath ? fileOrFolderList : + fileOrFolderList.map(f => { + const result = clone(f); + result.path = this.getHostSpecificPath(f.path); + return result; + }); + for (const fileOrDirectory of filesOrFoldersToLoad) { const path = this.toFullPath(fileOrDirectory.path); mapNewLeaves.set(path, true); // If its a change