diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 75ac31a7744..eb2249f85df 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -613,18 +613,23 @@ namespace ts.server { // when creation inferred project for some file has added other open files into this project (i.e. as referenced files) // we definitely don't want to delete the project that was just created for (const f of this.openFiles) { - if (f.containingProjects.length === 0) { + if (f.containingProjects.length === 0 || !inferredProject.containsScriptInfo(f)) { // this is orphaned file that we have not processed yet - skip it continue; } - const defaultProject = f.getDefaultProject(); - if (isRootFileInInferredProject(info) && defaultProject !== inferredProject && inferredProject.containsScriptInfo(f)) { - // open file used to be root in inferred project, - // this inferred project is different from the one we've just created for current file - // and new inferred project references this open file. - // We should delete old inferred project and attach open file to the new one - this.removeProject(defaultProject); - f.attachToProject(inferredProject); + + for (const fContainingProject of f.containingProjects) { + if (fContainingProject.projectKind === ProjectKind.Inferred && + fContainingProject.isRoot(f) && + fContainingProject !== inferredProject) { + + // open file used to be root in inferred project, + // this inferred project is different from the one we've just created for current file + // and new inferred project references this open file. + // We should delete old inferred project and attach open file to the new one + this.removeProject(fContainingProject); + f.attachToProject(inferredProject); + } } } } diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index be3ef34ce3a..617b5a74999 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -261,10 +261,26 @@ namespace ts.server { } getDefaultProject() { - if (this.containingProjects.length === 0) { - return Errors.ThrowNoProject(); + switch (this.containingProjects.length) { + case 0: + return Errors.ThrowNoProject(); + case 1: + return this.containingProjects[0]; + default: + // if this file belongs to multiple projects, the first configured project should be + // the default project; if no configured projects, the first external project should + // be the default project; otherwise the first inferred project should be the default. + let firstExternalProject; + for (const project of this.containingProjects) { + if (project.projectKind === ProjectKind.Configured) { + return project; + } + else if (project.projectKind === ProjectKind.External && !firstExternalProject) { + firstExternalProject = project; + } + } + return firstExternalProject || this.containingProjects[0]; } - return this.containingProjects[0]; } registerFileUpdate(): void { diff --git a/src/server/session.ts b/src/server/session.ts index fd2e554d131..1ececa022b7 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -751,6 +751,17 @@ namespace ts.server { return projects; } + private getDefaultProject(args: protocol.FileRequestArgs) { + if (args.projectFileName) { + const project = this.getProject(args.projectFileName); + if (project) { + return project; + } + } + const info = this.projectService.getScriptInfo(args.file); + return info.getDefaultProject(); + } + private getRenameLocations(args: protocol.RenameRequestArgs, simplifiedResult: boolean): protocol.RenameResponseBody | RenameLocation[] { const file = toNormalizedPath(args.file); const info = this.projectService.getScriptInfoForNormalizedPath(file); @@ -758,7 +769,7 @@ namespace ts.server { const projects = this.getProjects(args); if (simplifiedResult) { - const defaultProject = projects[0]; + const defaultProject = this.getDefaultProject(args); // The rename info should be the same for every project const renameInfo = defaultProject.getLanguageService().getRenameInfo(file, position); if (!renameInfo) { @@ -857,7 +868,7 @@ namespace ts.server { const file = toNormalizedPath(args.file); const projects = this.getProjects(args); - const defaultProject = projects[0]; + const defaultProject = this.getDefaultProject(args); const scriptInfo = defaultProject.getScriptInfoForNormalizedPath(file); const position = this.getPosition(args, scriptInfo); if (simplifiedResult) {