Skip to content

Commit ec19733

Browse files
authored
Merge pull request #22072 from Microsoft/configFileWithIncorrectProjectRoot
Search till root just like tsc when the projectRootPath specified doesnt contain the info.path
2 parents 1a320fc + 92d0873 commit ec19733

File tree

2 files changed

+90
-5
lines changed

2 files changed

+90
-5
lines changed

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4074,11 +4074,11 @@ namespace ts.projectSystem {
40744074
// Open file1 -> configFile
40754075
verifyConfigFileName(file1, "/a", configFile);
40764076
verifyConfigFileName(file1, "/a/b", configFile);
4077-
verifyConfigFileName(file1, "/a/B", useCaseSensitiveFileNames ? undefined : configFile);
4077+
verifyConfigFileName(file1, "/a/B", configFile);
40784078

40794079
// Open file2 use root "/a/b"
40804080
verifyConfigFileName(file2, "/a", useCaseSensitiveFileNames ? configFile2 : configFile);
4081-
verifyConfigFileName(file2, "/a/b", useCaseSensitiveFileNames ? undefined : configFile);
4081+
verifyConfigFileName(file2, "/a/b", useCaseSensitiveFileNames ? configFile2 : configFile);
40824082
verifyConfigFileName(file2, "/a/B", useCaseSensitiveFileNames ? undefined : configFile);
40834083

40844084
function verifyConfigFileName(file: FileOrFolder, projectRoot: string, expectedConfigFile: FileOrFolder | undefined) {
@@ -5607,6 +5607,88 @@ namespace ts.projectSystem {
56075607
checkWatchedDirectories(host, [], /*recursive*/ false);
56085608
checkWatchedDirectories(host, getTypeRootsFromLocation(projectDir), /*recursive*/ true);
56095609
});
5610+
5611+
describe("when the opened file is not from project root", () => {
5612+
const projectRoot = "/a/b/projects/project";
5613+
const file: FileOrFolder = {
5614+
path: `${projectRoot}/src/index.ts`,
5615+
content: "let y = 10"
5616+
};
5617+
const tsconfig: FileOrFolder = {
5618+
path: `${projectRoot}/tsconfig.json`,
5619+
content: "{}"
5620+
};
5621+
const files = [file, libFile];
5622+
const filesWithConfig = files.concat(tsconfig);
5623+
const dirOfFile = getDirectoryPath(file.path);
5624+
5625+
function openClientFile(files: FileOrFolder[]) {
5626+
const host = createServerHost(files);
5627+
const projectService = createProjectService(host);
5628+
5629+
projectService.openClientFile(file.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a/b/projects/proj");
5630+
return { host, projectService };
5631+
}
5632+
5633+
function verifyConfiguredProject(host: TestServerHost, projectService: TestProjectService, orphanInferredProject?: boolean) {
5634+
projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: orphanInferredProject ? 1 : 0 });
5635+
const project = projectService.configuredProjects.get(tsconfig.path);
5636+
assert.isDefined(project);
5637+
5638+
if (orphanInferredProject) {
5639+
const inferredProject = projectService.inferredProjects[0];
5640+
assert.isTrue(inferredProject.isOrphan());
5641+
}
5642+
5643+
checkProjectActualFiles(project, [file.path, libFile.path, tsconfig.path]);
5644+
checkWatchedFiles(host, [libFile.path, tsconfig.path]);
5645+
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
5646+
checkWatchedDirectories(host, (orphanInferredProject ? [projectRoot, `${dirOfFile}/node_modules/@types`] : [projectRoot]).concat(getTypeRootsFromLocation(projectRoot)), /*recursive*/ true);
5647+
}
5648+
5649+
function verifyInferredProject(host: TestServerHost, projectService: TestProjectService) {
5650+
projectService.checkNumberOfProjects({ inferredProjects: 1 });
5651+
const project = projectService.inferredProjects[0];
5652+
assert.isDefined(project);
5653+
5654+
const filesToWatch = [libFile.path];
5655+
forEachAncestorDirectory(dirOfFile, ancestor => {
5656+
filesToWatch.push(combinePaths(ancestor, "tsconfig.json"));
5657+
filesToWatch.push(combinePaths(ancestor, "jsconfig.json"));
5658+
});
5659+
5660+
checkProjectActualFiles(project, [file.path, libFile.path]);
5661+
checkWatchedFiles(host, filesToWatch);
5662+
checkWatchedDirectories(host, emptyArray, /*recursive*/ false);
5663+
checkWatchedDirectories(host, getTypeRootsFromLocation(dirOfFile), /*recursive*/ true);
5664+
}
5665+
5666+
it("tsconfig for the file exists", () => {
5667+
const { host, projectService } = openClientFile(filesWithConfig);
5668+
verifyConfiguredProject(host, projectService);
5669+
5670+
host.reloadFS(files);
5671+
host.runQueuedTimeoutCallbacks();
5672+
verifyInferredProject(host, projectService);
5673+
5674+
host.reloadFS(filesWithConfig);
5675+
host.runQueuedTimeoutCallbacks();
5676+
verifyConfiguredProject(host, projectService, /*orphanInferredProject*/ true);
5677+
});
5678+
5679+
it("tsconfig for the file does not exist", () => {
5680+
const { host, projectService } = openClientFile(files);
5681+
verifyInferredProject(host, projectService);
5682+
5683+
host.reloadFS(filesWithConfig);
5684+
host.runQueuedTimeoutCallbacks();
5685+
verifyConfiguredProject(host, projectService, /*orphanInferredProject*/ true);
5686+
5687+
host.reloadFS(files);
5688+
host.runQueuedTimeoutCallbacks();
5689+
verifyInferredProject(host, projectService);
5690+
});
5691+
});
56105692
});
56115693

56125694
describe("tsserverProjectSystem cancellationToken", () => {

src/server/editorServices.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,8 +1197,11 @@ namespace ts.server {
11971197
const projectRootPath = this.openFiles.get(info.path);
11981198

11991199
let searchPath = asNormalizedPath(getDirectoryPath(info.fileName));
1200+
const isSearchPathInProjectRoot = () => containsPath(projectRootPath, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames);
12001201

1201-
while (!projectRootPath || containsPath(projectRootPath, searchPath, this.currentDirectory, !this.host.useCaseSensitiveFileNames)) {
1202+
// If projectRootPath doesnt contain info.path, then do normal search for config file
1203+
const anySearchPathOk = !projectRootPath || !isSearchPathInProjectRoot();
1204+
do {
12021205
const canonicalSearchPath = normalizedPathToPath(searchPath, this.currentDirectory, this.toCanonicalFileName);
12031206
const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json"));
12041207
let result = action(tsconfigFileName, combinePaths(canonicalSearchPath, "tsconfig.json"));
@@ -1217,7 +1220,7 @@ namespace ts.server {
12171220
break;
12181221
}
12191222
searchPath = parentPath;
1220-
}
1223+
} while (anySearchPathOk || isSearchPathInProjectRoot());
12211224

12221225
return undefined;
12231226
}
@@ -1235,7 +1238,7 @@ namespace ts.server {
12351238
this.logger.info(`Search path: ${getDirectoryPath(info.fileName)}`);
12361239
const configFileName = this.forEachConfigFileLocation(info,
12371240
(configFileName, canonicalConfigFilePath) =>
1238-
this.configFileExists(configFileName, canonicalConfigFilePath, info),
1241+
this.configFileExists(configFileName, canonicalConfigFilePath, info)
12391242
);
12401243
if (configFileName) {
12411244
this.logger.info(`For info: ${info.fileName} :: Config file name: ${configFileName}`);

0 commit comments

Comments
 (0)