Skip to content

Commit c1cbf58

Browse files
committed
Update the project graph before checking if opened file is present in the existing project
Fixes #20017
1 parent c2fc5ea commit c1cbf58

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

src/harness/unittests/tsserverProjectSystem.ts

+32
Original file line numberDiff line numberDiff line change
@@ -3468,6 +3468,38 @@ namespace ts.projectSystem {
34683468
it("works when project root is used with case-insensitive system", () => {
34693469
verifyOpenFileWorks(/*useCaseSensitiveFileNames*/ false);
34703470
});
3471+
3472+
it("uses existing project even if project refresh is pending", () => {
3473+
const projectFolder = "/user/someuser/projects/myproject";
3474+
const aFile: FileOrFolder = {
3475+
path: `${projectFolder}/src/a.ts`,
3476+
content: "export const x = 0;"
3477+
};
3478+
const configFile: FileOrFolder = {
3479+
path: `${projectFolder}/tsconfig.json`,
3480+
content: "{}"
3481+
};
3482+
const files = [aFile, configFile, libFile];
3483+
const host = createServerHost(files);
3484+
const service = createProjectService(host);
3485+
service.openClientFile(aFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder);
3486+
verifyProject();
3487+
3488+
const bFile: FileOrFolder = {
3489+
path: `${projectFolder}/src/b.ts`,
3490+
content: `export {}; declare module "./a" { export const y: number; }`
3491+
};
3492+
files.push(bFile);
3493+
host.reloadFS(files);
3494+
service.openClientFile(bFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder);
3495+
verifyProject();
3496+
3497+
function verifyProject() {
3498+
assert.isDefined(service.configuredProjects.get(configFile.path));
3499+
const project = service.configuredProjects.get(configFile.path);
3500+
checkProjectActualFiles(project, files.map(f => f.path));
3501+
}
3502+
});
34713503
});
34723504

34733505
describe("tsserverProjectSystem Language service", () => {

src/server/editorServices.ts

+16-10
Original file line numberDiff line numberDiff line change
@@ -725,15 +725,6 @@ namespace ts.server {
725725
}
726726
}
727727

728-
private findContainingExternalProject(fileName: NormalizedPath): ExternalProject {
729-
for (const proj of this.externalProjects) {
730-
if (proj.containsFile(fileName)) {
731-
return proj;
732-
}
733-
}
734-
return undefined;
735-
}
736-
737728
getFormatCodeOptions(file?: NormalizedPath) {
738729
let formatCodeSettings: FormatCodeSettings;
739730
if (file) {
@@ -1991,13 +1982,24 @@ namespace ts.server {
19911982
return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined);
19921983
}
19931984

1985+
private findExternalProjetContainingOpenScriptInfo(info: ScriptInfo): ExternalProject {
1986+
for (const proj of this.externalProjects) {
1987+
// Ensure project structure is uptodate to check if info is present in external project
1988+
proj.updateGraph();
1989+
if (proj.containsScriptInfo(info)) {
1990+
return proj;
1991+
}
1992+
}
1993+
return undefined;
1994+
}
1995+
19941996
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
19951997
let configFileName: NormalizedPath;
19961998
let sendConfigFileDiagEvent = false;
19971999
let configFileErrors: ReadonlyArray<Diagnostic>;
19982000

19992001
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent);
2000-
let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName);
2002+
let project: ConfiguredProject | ExternalProject = this.findExternalProjetContainingOpenScriptInfo(info);
20012003
if (!project) {
20022004
configFileName = this.getConfigFileNameForFile(info, projectRootPath);
20032005
if (configFileName) {
@@ -2007,6 +2009,10 @@ namespace ts.server {
20072009
// Send the event only if the project got created as part of this open request
20082010
sendConfigFileDiagEvent = true;
20092011
}
2012+
else {
2013+
// Ensure project is ready to check if it contains opened script info
2014+
project.updateGraph();
2015+
}
20102016
}
20112017
}
20122018
if (project && !project.languageServiceEnabled) {

tests/baselines/reference/api/tsserverlibrary.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7605,7 +7605,6 @@ declare namespace ts.server {
76057605
* @param forceInferredProjectsRefresh when true updates the inferred projects even if there is no pending work to update the files/project structures
76067606
*/
76077607
private ensureProjectStructuresUptoDate(forceInferredProjectsRefresh?);
7608-
private findContainingExternalProject(fileName);
76097608
getFormatCodeOptions(file?: NormalizedPath): FormatCodeSettings;
76107609
private updateProjectGraphs(projects);
76117610
private onSourceFileChanged(fileName, eventKind);
@@ -7723,6 +7722,7 @@ declare namespace ts.server {
77237722
* @param fileContent is a known version of the file content that is more up to date than the one on disk
77247723
*/
77257724
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult;
7725+
private findExternalProjetContainingOpenScriptInfo(info);
77267726
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult;
77277727
/**
77287728
* Close file whose contents is managed by the client

0 commit comments

Comments
 (0)