Skip to content

Commit b0a3f9d

Browse files
authored
Merge pull request microsoft#19479 from Microsoft/reloadScriptsWithoutProject
On "reload" command, reload contents of file from disk irrespective of project presence and even if file already containing its own text
2 parents 97a2e42 + f9003b3 commit b0a3f9d

File tree

5 files changed

+119
-36
lines changed

5 files changed

+119
-36
lines changed

src/harness/unittests/tsserverProjectSystem.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3893,6 +3893,96 @@ namespace ts.projectSystem {
38933893
assert.equal(snap2.getText(0, snap2.getLength()), f1.content, "content should be equal to the content of original file");
38943894

38953895
});
3896+
3897+
it("should work when script info doesnt have any project open", () => {
3898+
const f1 = {
3899+
path: "/a/b/app.ts",
3900+
content: "let x = 1"
3901+
};
3902+
const tmp = {
3903+
path: "/a/b/app.tmp",
3904+
content: "const y = 42"
3905+
};
3906+
const host = createServerHost([f1, tmp, libFile]);
3907+
const session = createSession(host);
3908+
const openContent = "let z = 1";
3909+
// send open request
3910+
session.executeCommandSeq(<server.protocol.OpenRequest>{
3911+
command: server.protocol.CommandTypes.Open,
3912+
arguments: { file: f1.path, fileContent: openContent }
3913+
});
3914+
3915+
const projectService = session.getProjectService();
3916+
checkNumberOfProjects(projectService, { inferredProjects: 1 });
3917+
const info = projectService.getScriptInfo(f1.path);
3918+
assert.isDefined(info);
3919+
checkScriptInfoContents(openContent, "contents set during open request");
3920+
3921+
// send close request
3922+
session.executeCommandSeq(<server.protocol.CloseRequest>{
3923+
command: server.protocol.CommandTypes.Close,
3924+
arguments: { file: f1.path }
3925+
});
3926+
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
3927+
3928+
// Can reload contents of the file when its not open and has no project
3929+
// reload from temp file
3930+
session.executeCommandSeq(<server.protocol.ReloadRequest>{
3931+
command: server.protocol.CommandTypes.Reload,
3932+
arguments: { file: f1.path, tmpfile: tmp.path }
3933+
});
3934+
checkScriptInfoAndProjects(0, tmp.content, "contents of temp file");
3935+
3936+
// reload from own file
3937+
session.executeCommandSeq(<server.protocol.ReloadRequest>{
3938+
command: server.protocol.CommandTypes.Reload,
3939+
arguments: { file: f1.path }
3940+
});
3941+
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
3942+
3943+
// Open file again without setting its content
3944+
session.executeCommandSeq(<server.protocol.OpenRequest>{
3945+
command: server.protocol.CommandTypes.Open,
3946+
arguments: { file: f1.path }
3947+
});
3948+
checkScriptInfoAndProjects(1, f1.content, "contents of file when opened without specifying contents");
3949+
const snap = info.getSnapshot();
3950+
3951+
// send close request
3952+
session.executeCommandSeq(<server.protocol.CloseRequest>{
3953+
command: server.protocol.CommandTypes.Close,
3954+
arguments: { file: f1.path }
3955+
});
3956+
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
3957+
assert.strictEqual(info.getSnapshot(), snap);
3958+
3959+
// reload from temp file
3960+
session.executeCommandSeq(<server.protocol.ReloadRequest>{
3961+
command: server.protocol.CommandTypes.Reload,
3962+
arguments: { file: f1.path, tmpfile: tmp.path }
3963+
});
3964+
checkScriptInfoAndProjects(0, tmp.content, "contents of temp file");
3965+
assert.notStrictEqual(info.getSnapshot(), snap);
3966+
3967+
// reload from own file
3968+
session.executeCommandSeq(<server.protocol.ReloadRequest>{
3969+
command: server.protocol.CommandTypes.Reload,
3970+
arguments: { file: f1.path }
3971+
});
3972+
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
3973+
assert.notStrictEqual(info.getSnapshot(), snap);
3974+
3975+
function checkScriptInfoAndProjects(inferredProjects: number, contentsOfInfo: string, captionForContents: string) {
3976+
checkNumberOfProjects(projectService, { inferredProjects });
3977+
assert.strictEqual(projectService.getScriptInfo(f1.path), info);
3978+
checkScriptInfoContents(contentsOfInfo, captionForContents);
3979+
}
3980+
3981+
function checkScriptInfoContents(contentsOfInfo: string, captionForContents: string) {
3982+
const snap = info.getSnapshot();
3983+
assert.equal(snap.getText(0, snap.getLength()), contentsOfInfo, "content should be equal to " + captionForContents);
3984+
}
3985+
});
38963986
});
38973987

38983988
describe("Inferred projects", () => {

src/server/project.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -946,16 +946,6 @@ namespace ts.server {
946946
}
947947
}
948948

949-
reloadScript(filename: NormalizedPath, tempFileName?: NormalizedPath): boolean {
950-
const script = this.projectService.getScriptInfoForNormalizedPath(filename);
951-
if (script) {
952-
Debug.assert(script.isAttached(this));
953-
script.reloadFromFile(tempFileName);
954-
return true;
955-
}
956-
return false;
957-
}
958-
959949
/* @internal */
960950
getChangesSinceVersion(lastKnownVersion?: number): ProjectFilesWithTSDiagnostics {
961951
this.updateGraph();

src/server/scriptInfo.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ namespace ts.server {
6767
this.lineMap = undefined;
6868
}
6969

70-
/** returns true if text changed */
70+
/**
71+
* Set the contents as newText
72+
* returns true if text changed
73+
*/
7174
public reload(newText: string) {
7275
Debug.assert(newText !== undefined);
7376

@@ -87,31 +90,31 @@ namespace ts.server {
8790
}
8891
}
8992

90-
/** returns true if text changed */
93+
/**
94+
* Reads the contents from tempFile(if supplied) or own file and sets it as contents
95+
* returns true if text changed
96+
*/
97+
public reloadWithFileText(tempFileName?: string) {
98+
const reloaded = this.reload(this.getFileText(tempFileName));
99+
this.ownFileText = !tempFileName || tempFileName === this.fileName;
100+
return reloaded;
101+
}
102+
103+
/**
104+
* Reloads the contents from the file if there is no pending reload from disk or the contents of file are same as file text
105+
* returns true if text changed
106+
*/
91107
public reloadFromDisk() {
92-
let reloaded = false;
93108
if (!this.pendingReloadFromDisk && !this.ownFileText) {
94-
reloaded = this.reload(this.getFileText());
95-
this.ownFileText = true;
109+
return this.reloadWithFileText();
96110
}
97-
return reloaded;
111+
return false;
98112
}
99113

100114
public delayReloadFromFileIntoText() {
101115
this.pendingReloadFromDisk = true;
102116
}
103117

104-
/** returns true if text changed */
105-
public reloadFromFile(tempFileName: string) {
106-
let reloaded = false;
107-
// Reload if different file or we dont know if we are working with own file text
108-
if (tempFileName !== this.fileName || !this.ownFileText) {
109-
reloaded = this.reload(this.getFileText(tempFileName));
110-
this.ownFileText = !tempFileName || tempFileName === this.fileName;
111-
}
112-
return reloaded;
113-
}
114-
115118
public getSnapshot(): IScriptSnapshot {
116119
return this.useScriptVersionCacheIfValidOrOpen()
117120
? this.svc.getSnapshot()
@@ -180,8 +183,7 @@ namespace ts.server {
180183
private getOrLoadText() {
181184
if (this.text === undefined || this.pendingReloadFromDisk) {
182185
Debug.assert(!this.svc || this.pendingReloadFromDisk, "ScriptVersionCache should not be set when reloading from disk");
183-
this.reload(this.getFileText());
184-
this.ownFileText = true;
186+
this.reloadWithFileText();
185187
}
186188
return this.text;
187189
}
@@ -385,7 +387,7 @@ namespace ts.server {
385387
this.markContainingProjectsAsDirty();
386388
}
387389
else {
388-
if (this.textStorage.reloadFromFile(tempFileName)) {
390+
if (this.textStorage.reloadWithFileText(tempFileName)) {
389391
this.markContainingProjectsAsDirty();
390392
}
391393
}

src/server/session.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,11 +1311,13 @@ namespace ts.server {
13111311
private reload(args: protocol.ReloadRequestArgs, reqSeq: number) {
13121312
const file = toNormalizedPath(args.file);
13131313
const tempFileName = args.tmpfile && toNormalizedPath(args.tmpfile);
1314-
const project = this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ true);
1315-
this.changeSeq++;
1316-
// make sure no changes happen before this one is finished
1317-
if (project.reloadScript(file, tempFileName)) {
1318-
this.doOutput(/*info*/ undefined, CommandNames.Reload, reqSeq, /*success*/ true);
1314+
const info = this.projectService.getScriptInfoForNormalizedPath(file);
1315+
if (info) {
1316+
this.changeSeq++;
1317+
// make sure no changes happen before this one is finished
1318+
if (info.reloadFromFile(tempFileName)) {
1319+
this.doOutput(/*info*/ undefined, CommandNames.Reload, reqSeq, /*success*/ true);
1320+
}
13191321
}
13201322
}
13211323

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7227,7 +7227,6 @@ declare namespace ts.server {
72277227
getScriptInfo(uncheckedFileName: string): ScriptInfo;
72287228
filesToString(writeProjectFileNames: boolean): string;
72297229
setCompilerOptions(compilerOptions: CompilerOptions): void;
7230-
reloadScript(filename: NormalizedPath, tempFileName?: NormalizedPath): boolean;
72317230
protected removeRoot(info: ScriptInfo): void;
72327231
}
72337232
/**

0 commit comments

Comments
 (0)