Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/harness/unittests/tsserverProjectSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3493,6 +3493,30 @@ namespace ts.projectSystem {
});
});

describe("searching for config file", () => {
it("should stop at projectRootPath if given", () => {
const f1 = {
path: "/a/file1.ts",
content: ""
};
const configFile = {
path: "/tsconfig.json",
content: "{}"
};
const host = createServerHost([f1, configFile]);
const service = createProjectService(host);
service.openClientFile(f1.path, /*fileContent*/ undefined, /*scriptKind*/ undefined, "/a");

checkNumberOfConfiguredProjects(service, 0);
checkNumberOfInferredProjects(service, 1);

service.closeClientFile(f1.path);
service.openClientFile(f1.path);
checkNumberOfConfiguredProjects(service, 1);
checkNumberOfInferredProjects(service, 0);
});
});

describe("cancellationToken", () => {
it("is attached to request", () => {
const f1 = {
Expand Down
16 changes: 8 additions & 8 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -787,12 +787,12 @@ namespace ts.server {
* we first detect if there is already a configured project created for it: if so, we re-read
* the tsconfig file content and update the project; otherwise we create a new one.
*/
private openOrUpdateConfiguredProjectForFile(fileName: NormalizedPath): OpenConfiguredProjectResult {
private openOrUpdateConfiguredProjectForFile(fileName: NormalizedPath, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
const searchPath = getDirectoryPath(fileName);
this.logger.info(`Search path: ${searchPath}`);

// check if this file is already included in one of external projects
const configFileName = this.findConfigFile(asNormalizedPath(searchPath));
const configFileName = this.findConfigFile(asNormalizedPath(searchPath), projectRootPath);
if (!configFileName) {
this.logger.info("No config files found.");
return {};
Expand Down Expand Up @@ -826,8 +826,8 @@ namespace ts.server {
// current directory (the directory in which tsc was invoked).
// The server must start searching from the directory containing
// the newly opened file.
private findConfigFile(searchPath: NormalizedPath): NormalizedPath {
while (true) {
private findConfigFile(searchPath: NormalizedPath, projectRootPath?: NormalizedPath): NormalizedPath {
while (!projectRootPath || searchPath.indexOf(projectRootPath) >= 0) {
const tsconfigFileName = asNormalizedPath(combinePaths(searchPath, "tsconfig.json"));
if (this.host.fileExists(tsconfigFileName)) {
return tsconfigFileName;
Expand Down Expand Up @@ -1326,17 +1326,17 @@ namespace ts.server {
* @param filename is absolute pathname
* @param fileContent is a known version of the file content that is more up to date than the one on disk
*/
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind): OpenConfiguredProjectResult {
return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind);
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult {
return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined);
}

openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean): OpenConfiguredProjectResult {
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
let configFileName: NormalizedPath;
let configFileErrors: Diagnostic[];

let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName);
if (!project) {
({ configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName));
({ configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName, projectRootPath));
if (configFileName) {
project = this.findConfiguredProjectByProjectName(configFileName);
}
Expand Down
5 changes: 5 additions & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,11 @@ namespace ts.server.protocol {
* "TS", "JS", "TSX", "JSX"
*/
scriptKindName?: ScriptKindName;
/**
* Used to limit the searching for project config file. If given the searching will stop at this
* root path; otherwise it will go all the way up to the dist root path.
*/
projectRootPath?: string;
}

export type ScriptKindName = "TS" | "JS" | "TSX" | "JSX";
Expand Down
10 changes: 7 additions & 3 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -979,8 +979,8 @@ namespace ts.server {
* @param fileName is the name of the file to be opened
* @param fileContent is a version of the file content that is known to be more up to date than the one on disk
*/
private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind) {
const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind);
private openClientFile(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: NormalizedPath) {
const { configFileName, configFileErrors } = this.projectService.openClientFileWithNormalizedPath(fileName, fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath);
if (this.eventHandler) {
this.eventHandler({
eventName: "configFileDiag",
Expand Down Expand Up @@ -1659,7 +1659,11 @@ namespace ts.server {
return this.requiredResponse(this.getRenameInfo(request.arguments));
},
[CommandNames.Open]: (request: protocol.OpenRequest) => {
this.openClientFile(toNormalizedPath(request.arguments.file), request.arguments.fileContent, convertScriptKindName(request.arguments.scriptKindName));
this.openClientFile(
toNormalizedPath(request.arguments.file),
request.arguments.fileContent,
convertScriptKindName(request.arguments.scriptKindName),
request.arguments.projectRootPath ? toNormalizedPath(request.arguments.projectRootPath) : undefined);
return this.notRequired();
},
[CommandNames.Quickinfo]: (request: protocol.QuickInfoRequest) => {
Expand Down