Skip to content

Commit 41c02e6

Browse files
authored
Merge pull request #20515 from Microsoft/fileAddedAfterProjectOpen
Update the project graph before checking if opened file is present in the existing project
2 parents 1dcc83e + c1cbf58 commit 41c02e6

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3510,6 +3510,38 @@ namespace ts.projectSystem {
35103510
it("works when project root is used with case-insensitive system", () => {
35113511
verifyOpenFileWorks(/*useCaseSensitiveFileNames*/ false);
35123512
});
3513+
3514+
it("uses existing project even if project refresh is pending", () => {
3515+
const projectFolder = "/user/someuser/projects/myproject";
3516+
const aFile: FileOrFolder = {
3517+
path: `${projectFolder}/src/a.ts`,
3518+
content: "export const x = 0;"
3519+
};
3520+
const configFile: FileOrFolder = {
3521+
path: `${projectFolder}/tsconfig.json`,
3522+
content: "{}"
3523+
};
3524+
const files = [aFile, configFile, libFile];
3525+
const host = createServerHost(files);
3526+
const service = createProjectService(host);
3527+
service.openClientFile(aFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder);
3528+
verifyProject();
3529+
3530+
const bFile: FileOrFolder = {
3531+
path: `${projectFolder}/src/b.ts`,
3532+
content: `export {}; declare module "./a" { export const y: number; }`
3533+
};
3534+
files.push(bFile);
3535+
host.reloadFS(files);
3536+
service.openClientFile(bFile.path, /*fileContent*/ undefined, ScriptKind.TS, projectFolder);
3537+
verifyProject();
3538+
3539+
function verifyProject() {
3540+
assert.isDefined(service.configuredProjects.get(configFile.path));
3541+
const project = service.configuredProjects.get(configFile.path);
3542+
checkProjectActualFiles(project, files.map(f => f.path));
3543+
}
3544+
});
35133545
});
35143546

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

src/server/editorServices.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -727,15 +727,6 @@ namespace ts.server {
727727
}
728728
}
729729

730-
private findContainingExternalProject(fileName: NormalizedPath): ExternalProject {
731-
for (const proj of this.externalProjects) {
732-
if (proj.containsFile(fileName)) {
733-
return proj;
734-
}
735-
}
736-
return undefined;
737-
}
738-
739730
getFormatCodeOptions(file?: NormalizedPath) {
740731
let formatCodeSettings: FormatCodeSettings;
741732
if (file) {
@@ -1994,13 +1985,24 @@ namespace ts.server {
19941985
return this.openClientFileWithNormalizedPath(toNormalizedPath(fileName), fileContent, scriptKind, /*hasMixedContent*/ false, projectRootPath ? toNormalizedPath(projectRootPath) : undefined);
19951986
}
19961987

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

20022004
const info = this.getOrCreateScriptInfoOpenedByClientForNormalizedPath(fileName, projectRootPath ? this.getNormalizedAbsolutePath(projectRootPath) : this.currentDirectory, fileContent, scriptKind, hasMixedContent);
2003-
let project: ConfiguredProject | ExternalProject = this.findContainingExternalProject(fileName);
2005+
let project: ConfiguredProject | ExternalProject = this.findExternalProjetContainingOpenScriptInfo(info);
20042006
if (!project) {
20052007
configFileName = this.getConfigFileNameForFile(info, projectRootPath);
20062008
if (configFileName) {
@@ -2010,6 +2012,10 @@ namespace ts.server {
20102012
// Send the event only if the project got created as part of this open request
20112013
sendConfigFileDiagEvent = true;
20122014
}
2015+
else {
2016+
// Ensure project is ready to check if it contains opened script info
2017+
project.updateGraph();
2018+
}
20132019
}
20142020
}
20152021
if (project && !project.languageServiceEnabled) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7789,7 +7789,6 @@ declare namespace ts.server {
77897789
* @param forceInferredProjectsRefresh when true updates the inferred projects even if there is no pending work to update the files/project structures
77907790
*/
77917791
private ensureProjectStructuresUptoDate(forceInferredProjectsRefresh?);
7792-
private findContainingExternalProject(fileName);
77937792
getFormatCodeOptions(file?: NormalizedPath): FormatCodeSettings;
77947793
private updateProjectGraphs(projects);
77957794
private onSourceFileChanged(fileName, eventKind);
@@ -7907,6 +7906,7 @@ declare namespace ts.server {
79077906
* @param fileContent is a known version of the file content that is more up to date than the one on disk
79087907
*/
79097908
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind, projectRootPath?: string): OpenConfiguredProjectResult;
7909+
private findExternalProjetContainingOpenScriptInfo(info);
79107910
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult;
79117911
/**
79127912
* Close file whose contents is managed by the client

0 commit comments

Comments
 (0)