Merge pull request #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
This commit is contained in:
commit
b0a3f9d4ec
5 changed files with 121 additions and 38 deletions
|
@ -3893,6 +3893,96 @@ namespace ts.projectSystem {
|
||||||
assert.equal(snap2.getText(0, snap2.getLength()), f1.content, "content should be equal to the content of original file");
|
assert.equal(snap2.getText(0, snap2.getLength()), f1.content, "content should be equal to the content of original file");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should work when script info doesnt have any project open", () => {
|
||||||
|
const f1 = {
|
||||||
|
path: "/a/b/app.ts",
|
||||||
|
content: "let x = 1"
|
||||||
|
};
|
||||||
|
const tmp = {
|
||||||
|
path: "/a/b/app.tmp",
|
||||||
|
content: "const y = 42"
|
||||||
|
};
|
||||||
|
const host = createServerHost([f1, tmp, libFile]);
|
||||||
|
const session = createSession(host);
|
||||||
|
const openContent = "let z = 1";
|
||||||
|
// send open request
|
||||||
|
session.executeCommandSeq(<server.protocol.OpenRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Open,
|
||||||
|
arguments: { file: f1.path, fileContent: openContent }
|
||||||
|
});
|
||||||
|
|
||||||
|
const projectService = session.getProjectService();
|
||||||
|
checkNumberOfProjects(projectService, { inferredProjects: 1 });
|
||||||
|
const info = projectService.getScriptInfo(f1.path);
|
||||||
|
assert.isDefined(info);
|
||||||
|
checkScriptInfoContents(openContent, "contents set during open request");
|
||||||
|
|
||||||
|
// send close request
|
||||||
|
session.executeCommandSeq(<server.protocol.CloseRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Close,
|
||||||
|
arguments: { file: f1.path }
|
||||||
|
});
|
||||||
|
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
|
||||||
|
|
||||||
|
// Can reload contents of the file when its not open and has no project
|
||||||
|
// reload from temp file
|
||||||
|
session.executeCommandSeq(<server.protocol.ReloadRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Reload,
|
||||||
|
arguments: { file: f1.path, tmpfile: tmp.path }
|
||||||
|
});
|
||||||
|
checkScriptInfoAndProjects(0, tmp.content, "contents of temp file");
|
||||||
|
|
||||||
|
// reload from own file
|
||||||
|
session.executeCommandSeq(<server.protocol.ReloadRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Reload,
|
||||||
|
arguments: { file: f1.path }
|
||||||
|
});
|
||||||
|
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
|
||||||
|
|
||||||
|
// Open file again without setting its content
|
||||||
|
session.executeCommandSeq(<server.protocol.OpenRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Open,
|
||||||
|
arguments: { file: f1.path }
|
||||||
|
});
|
||||||
|
checkScriptInfoAndProjects(1, f1.content, "contents of file when opened without specifying contents");
|
||||||
|
const snap = info.getSnapshot();
|
||||||
|
|
||||||
|
// send close request
|
||||||
|
session.executeCommandSeq(<server.protocol.CloseRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Close,
|
||||||
|
arguments: { file: f1.path }
|
||||||
|
});
|
||||||
|
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
|
||||||
|
assert.strictEqual(info.getSnapshot(), snap);
|
||||||
|
|
||||||
|
// reload from temp file
|
||||||
|
session.executeCommandSeq(<server.protocol.ReloadRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Reload,
|
||||||
|
arguments: { file: f1.path, tmpfile: tmp.path }
|
||||||
|
});
|
||||||
|
checkScriptInfoAndProjects(0, tmp.content, "contents of temp file");
|
||||||
|
assert.notStrictEqual(info.getSnapshot(), snap);
|
||||||
|
|
||||||
|
// reload from own file
|
||||||
|
session.executeCommandSeq(<server.protocol.ReloadRequest>{
|
||||||
|
command: server.protocol.CommandTypes.Reload,
|
||||||
|
arguments: { file: f1.path }
|
||||||
|
});
|
||||||
|
checkScriptInfoAndProjects(0, f1.content, "contents of closed file");
|
||||||
|
assert.notStrictEqual(info.getSnapshot(), snap);
|
||||||
|
|
||||||
|
function checkScriptInfoAndProjects(inferredProjects: number, contentsOfInfo: string, captionForContents: string) {
|
||||||
|
checkNumberOfProjects(projectService, { inferredProjects });
|
||||||
|
assert.strictEqual(projectService.getScriptInfo(f1.path), info);
|
||||||
|
checkScriptInfoContents(contentsOfInfo, captionForContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkScriptInfoContents(contentsOfInfo: string, captionForContents: string) {
|
||||||
|
const snap = info.getSnapshot();
|
||||||
|
assert.equal(snap.getText(0, snap.getLength()), contentsOfInfo, "content should be equal to " + captionForContents);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Inferred projects", () => {
|
describe("Inferred projects", () => {
|
||||||
|
|
|
@ -946,16 +946,6 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadScript(filename: NormalizedPath, tempFileName?: NormalizedPath): boolean {
|
|
||||||
const script = this.projectService.getScriptInfoForNormalizedPath(filename);
|
|
||||||
if (script) {
|
|
||||||
Debug.assert(script.isAttached(this));
|
|
||||||
script.reloadFromFile(tempFileName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* @internal */
|
/* @internal */
|
||||||
getChangesSinceVersion(lastKnownVersion?: number): ProjectFilesWithTSDiagnostics {
|
getChangesSinceVersion(lastKnownVersion?: number): ProjectFilesWithTSDiagnostics {
|
||||||
this.updateGraph();
|
this.updateGraph();
|
||||||
|
|
|
@ -67,7 +67,10 @@ namespace ts.server {
|
||||||
this.lineMap = undefined;
|
this.lineMap = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** returns true if text changed */
|
/**
|
||||||
|
* Set the contents as newText
|
||||||
|
* returns true if text changed
|
||||||
|
*/
|
||||||
public reload(newText: string) {
|
public reload(newText: string) {
|
||||||
Debug.assert(newText !== undefined);
|
Debug.assert(newText !== undefined);
|
||||||
|
|
||||||
|
@ -87,31 +90,31 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** returns true if text changed */
|
/**
|
||||||
public reloadFromDisk() {
|
* Reads the contents from tempFile(if supplied) or own file and sets it as contents
|
||||||
let reloaded = false;
|
* returns true if text changed
|
||||||
if (!this.pendingReloadFromDisk && !this.ownFileText) {
|
*/
|
||||||
reloaded = this.reload(this.getFileText());
|
public reloadWithFileText(tempFileName?: string) {
|
||||||
this.ownFileText = true;
|
const reloaded = this.reload(this.getFileText(tempFileName));
|
||||||
}
|
this.ownFileText = !tempFileName || tempFileName === this.fileName;
|
||||||
return reloaded;
|
return reloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reloads the contents from the file if there is no pending reload from disk or the contents of file are same as file text
|
||||||
|
* returns true if text changed
|
||||||
|
*/
|
||||||
|
public reloadFromDisk() {
|
||||||
|
if (!this.pendingReloadFromDisk && !this.ownFileText) {
|
||||||
|
return this.reloadWithFileText();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public delayReloadFromFileIntoText() {
|
public delayReloadFromFileIntoText() {
|
||||||
this.pendingReloadFromDisk = true;
|
this.pendingReloadFromDisk = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** returns true if text changed */
|
|
||||||
public reloadFromFile(tempFileName: string) {
|
|
||||||
let reloaded = false;
|
|
||||||
// Reload if different file or we dont know if we are working with own file text
|
|
||||||
if (tempFileName !== this.fileName || !this.ownFileText) {
|
|
||||||
reloaded = this.reload(this.getFileText(tempFileName));
|
|
||||||
this.ownFileText = !tempFileName || tempFileName === this.fileName;
|
|
||||||
}
|
|
||||||
return reloaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public getSnapshot(): IScriptSnapshot {
|
public getSnapshot(): IScriptSnapshot {
|
||||||
return this.useScriptVersionCacheIfValidOrOpen()
|
return this.useScriptVersionCacheIfValidOrOpen()
|
||||||
? this.svc.getSnapshot()
|
? this.svc.getSnapshot()
|
||||||
|
@ -180,8 +183,7 @@ namespace ts.server {
|
||||||
private getOrLoadText() {
|
private getOrLoadText() {
|
||||||
if (this.text === undefined || this.pendingReloadFromDisk) {
|
if (this.text === undefined || this.pendingReloadFromDisk) {
|
||||||
Debug.assert(!this.svc || this.pendingReloadFromDisk, "ScriptVersionCache should not be set when reloading from disk");
|
Debug.assert(!this.svc || this.pendingReloadFromDisk, "ScriptVersionCache should not be set when reloading from disk");
|
||||||
this.reload(this.getFileText());
|
this.reloadWithFileText();
|
||||||
this.ownFileText = true;
|
|
||||||
}
|
}
|
||||||
return this.text;
|
return this.text;
|
||||||
}
|
}
|
||||||
|
@ -385,7 +387,7 @@ namespace ts.server {
|
||||||
this.markContainingProjectsAsDirty();
|
this.markContainingProjectsAsDirty();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (this.textStorage.reloadFromFile(tempFileName)) {
|
if (this.textStorage.reloadWithFileText(tempFileName)) {
|
||||||
this.markContainingProjectsAsDirty();
|
this.markContainingProjectsAsDirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1311,11 +1311,13 @@ namespace ts.server {
|
||||||
private reload(args: protocol.ReloadRequestArgs, reqSeq: number) {
|
private reload(args: protocol.ReloadRequestArgs, reqSeq: number) {
|
||||||
const file = toNormalizedPath(args.file);
|
const file = toNormalizedPath(args.file);
|
||||||
const tempFileName = args.tmpfile && toNormalizedPath(args.tmpfile);
|
const tempFileName = args.tmpfile && toNormalizedPath(args.tmpfile);
|
||||||
const project = this.projectService.getDefaultProjectForFile(file, /*ensureProject*/ true);
|
const info = this.projectService.getScriptInfoForNormalizedPath(file);
|
||||||
this.changeSeq++;
|
if (info) {
|
||||||
// make sure no changes happen before this one is finished
|
this.changeSeq++;
|
||||||
if (project.reloadScript(file, tempFileName)) {
|
// make sure no changes happen before this one is finished
|
||||||
this.doOutput(/*info*/ undefined, CommandNames.Reload, reqSeq, /*success*/ true);
|
if (info.reloadFromFile(tempFileName)) {
|
||||||
|
this.doOutput(/*info*/ undefined, CommandNames.Reload, reqSeq, /*success*/ true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7227,7 +7227,6 @@ declare namespace ts.server {
|
||||||
getScriptInfo(uncheckedFileName: string): ScriptInfo;
|
getScriptInfo(uncheckedFileName: string): ScriptInfo;
|
||||||
filesToString(writeProjectFileNames: boolean): string;
|
filesToString(writeProjectFileNames: boolean): string;
|
||||||
setCompilerOptions(compilerOptions: CompilerOptions): void;
|
setCompilerOptions(compilerOptions: CompilerOptions): void;
|
||||||
reloadScript(filename: NormalizedPath, tempFileName?: NormalizedPath): boolean;
|
|
||||||
protected removeRoot(info: ScriptInfo): void;
|
protected removeRoot(info: ScriptInfo): void;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue