diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 2d761ae33c2..f7d082128cd 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -2917,6 +2917,52 @@ namespace ts.projectSystem { function checkSnapLength(snap: IScriptSnapshot, expectedLength: number) { assert.equal(snap.getLength(), expectedLength, "Incorrect snapshot size"); } + + function verifyOpenFileWorks(useCaseSensitiveFileNames: boolean) { + const file1: FileOrFolder = { + path: "/a/b/src/app.ts", + content: "let x = 10;" + }; + const file2: FileOrFolder = { + path: "/a/B/lib/module2.ts", + content: "let z = 10;" + }; + const configFile: FileOrFolder = { + path: "/a/b/tsconfig.json", + content: "" + }; + const configFile2: FileOrFolder = { + path: "/a/tsconfig.json", + content: "" + }; + const host = createServerHost([file1, file2, configFile, configFile2], { + useCaseSensitiveFileNames + }); + const service = createProjectService(host); + + // Open file1 -> configFile + verifyConfigFileName(file1, "/a", configFile); + verifyConfigFileName(file1, "/a/b", configFile); + verifyConfigFileName(file1, "/a/B", useCaseSensitiveFileNames ? undefined : configFile); + + // Open file2 use root "/a/b" + verifyConfigFileName(file2, "/a", useCaseSensitiveFileNames ? configFile2 : configFile); + verifyConfigFileName(file2, "/a/b", useCaseSensitiveFileNames ? undefined : configFile); + verifyConfigFileName(file2, "/a/B", useCaseSensitiveFileNames ? undefined : configFile); + + function verifyConfigFileName(file: FileOrFolder, projectRoot: string, expectedConfigFile: FileOrFolder | undefined) { + const { configFileName } = service.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, projectRoot); + assert.equal(configFileName, expectedConfigFile && expectedConfigFile.path); + service.closeClientFile(file.path); + } + } + it("works when project root is used with case-sensitive system", () => { + verifyOpenFileWorks(/*useCaseSensitiveFileNames*/ true); + }); + + it("works when project root is used with case-insensitive system", () => { + verifyOpenFileWorks(/*useCaseSensitiveFileNames*/ false); + }); }); describe("Language service", () => { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 173fd86afe4..379a5fbfe7e 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1218,7 +1218,7 @@ namespace ts.server { projectRootPath?: NormalizedPath) { let searchPath = asNormalizedPath(getDirectoryPath(info.fileName)); - while (!projectRootPath || stringContains(searchPath, projectRootPath)) { + while (!projectRootPath || containsPath(projectRootPath, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames)) { const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName); const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json")); let result = action(tsconfigFileName, combinePaths(canonicalSearchPath, "tsconfig.json"));