diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 2ed4a903133..f7d220b7894 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1533,6 +1533,14 @@ namespace ts.server { return undefined; } + /*@internal*/ + findDefaultConfiguredProject(info: ScriptInfo) { + if (!info.isScriptOpen()) return undefined; + const configFileName = this.getConfigFileNameForFile(info); + return configFileName && + this.findConfiguredProjectByProjectName(configFileName); + } + /** * This function tries to search for a tsconfig.json for the given file. * This is different from the method the compiler uses because diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index f602d18ae70..86d76711d4a 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -491,21 +491,40 @@ namespace ts.server { 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. + // If this file belongs to multiple projects, below is the order in which default project is used + // - for open script info, its default configured project during opening is default if info is part of it + // - first configured project of which script info is not a source of project reference redirect + // - first configured project + // - first external project + // - first inferred project let firstExternalProject; let firstConfiguredProject; - for (const project of this.containingProjects) { + let firstNonSourceOfProjectReferenceRedirect; + let defaultConfiguredProject: ConfiguredProject | false | undefined; + for (let index = 0; index < this.containingProjects.length; index++) { + const project = this.containingProjects[index]; if (project.projectKind === ProjectKind.Configured) { - if (!project.isSourceOfProjectReferenceRedirect(this.fileName)) return project; + if (!project.isSourceOfProjectReferenceRedirect(this.fileName)) { + // If we havent found default configuredProject and + // its not the last one, find it and use that one if there + if (defaultConfiguredProject === undefined && + index !== this.containingProjects.length - 1) { + defaultConfiguredProject = project.projectService.findDefaultConfiguredProject(this) || false; + } + if (defaultConfiguredProject === project) return project; + if (!firstNonSourceOfProjectReferenceRedirect) firstNonSourceOfProjectReferenceRedirect = project; + } if (!firstConfiguredProject) firstConfiguredProject = project; } else if (project.projectKind === ProjectKind.External && !firstExternalProject) { firstExternalProject = project; } } - return firstConfiguredProject || firstExternalProject || this.containingProjects[0]; + return defaultConfiguredProject || + firstNonSourceOfProjectReferenceRedirect || + firstConfiguredProject || + firstExternalProject || + this.containingProjects[0]; } } diff --git a/src/testRunner/unittests/tsserver/configuredProjects.ts b/src/testRunner/unittests/tsserver/configuredProjects.ts index fd0990c8345..5d2a8730492 100644 --- a/src/testRunner/unittests/tsserver/configuredProjects.ts +++ b/src/testRunner/unittests/tsserver/configuredProjects.ts @@ -846,7 +846,6 @@ namespace ts.projectSystem { }); it("when multiple projects are open, detects correct default project", () => { - //const projectLocation: `/user/username/projects/myproject`; const barConfig: File = { path: `${projectRoot}/bar/tsconfig.json`, content: JSON.stringify({