Skip to content

Commit 55edbdb

Browse files
authored
Fix automatic refresh of server-side documents after save and compile (#1678)
1 parent 798aad8 commit 55edbdb

File tree

2 files changed

+66
-29
lines changed

2 files changed

+66
-29
lines changed

src/extension.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,6 +1897,20 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
18971897
sendCommandTelemetryEvent("showAllClassMembers");
18981898
if (uri instanceof vscode.Uri) showAllClassMembers(uri);
18991899
}),
1900+
vscode.workspace.onDidSaveTextDocument((d) => {
1901+
// If the document just saved is a server-side document that needs to be updated in the UI,
1902+
// then force VS Code to update the document's contents. This is needed if the document has
1903+
// been changed during a save, for example by adding or changing the Storage definition.
1904+
if (notIsfs(d.uri)) return;
1905+
const uriString = d.uri.toString();
1906+
if (fileSystemProvider.needsUpdate(uriString)) {
1907+
const activeDoc = vscode.window.activeTextEditor?.document;
1908+
if (activeDoc && !activeDoc.isDirty && !activeDoc.isClosed && activeDoc.uri.toString() == uriString) {
1909+
// Force VS Code to refresh the file's contents in the editor tab
1910+
vscode.commands.executeCommand("workbench.action.files.revert");
1911+
}
1912+
}
1913+
}),
19001914
// These three listeners are needed to keep track of which file events were caused by VS Code
19011915
// to support the "vscodeOnly" option for the objectscript.syncLocalChanges setting.
19021916
// They store the URIs of files that are about to be changed by VS Code.

src/providers/FileSystemProvider/FileSystemProvider.ts

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,29 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
268268
private _bufferedEvents: vscode.FileChangeEvent[] = [];
269269
private _fireSoonHandle?: NodeJS.Timeout;
270270

271+
/**
272+
* The stringified URIs of all `isfs` documents that may have had
273+
* their contents changed during the last time they were saved
274+
*/
275+
private readonly _needsUpdate: Set<string> = new Set();
276+
271277
public constructor() {
272278
this.onDidChangeFile = this._emitter.event;
273279
}
274280

281+
/**
282+
* Check if this `isfs` document stringified URI was changed during
283+
* the last time it was saved. This is used to force VS Code to update
284+
* the editor tab containing the file.
285+
*/
286+
public needsUpdate(uriString: string): boolean {
287+
if (this._needsUpdate.has(uriString)) {
288+
this._needsUpdate.delete(uriString);
289+
return true;
290+
}
291+
return false;
292+
}
293+
275294
// Used by import and compile to make sure we notice its changes
276295
public fireFileChanged(uri: vscode.Uri): void {
277296
this._fireSoon({ type: vscode.FileChangeType.Changed, uri });
@@ -476,6 +495,9 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
476495
overwrite: boolean;
477496
}
478497
): void | Thenable<void> {
498+
const originalUriString = uri.toString();
499+
const originalUri = vscode.Uri.parse(originalUriString);
500+
this._needsUpdate.delete(originalUriString);
479501
uri = redirectDotvscodeRoot(uri, new vscode.FileSystemError("Server does not have a /_vscode web application"));
480502
if (uri.path.startsWith("/.")) {
481503
throw new vscode.FileSystemError("dot-folders are not supported by server");
@@ -616,38 +638,17 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
616638
// is part of the "write" operation from VS Code's point of view. This is required
617639
// to prevent concurreny issues when VS Code refreshs its internal representaton of
618640
// the file system while documents are being compiled.
619-
return this.compile(uri, entry, update);
641+
return this.compile(originalUri, entry, update);
620642
} else if (update) {
621643
// The file's contents may have changed as a result of the save,
622-
// so make sure we notify VS Code and any watchers of the change
623-
this._notifyOfFileChange(uri);
644+
// so make sure VS Code updates the editor tab contents if needed
645+
this._needsUpdate.add(originalUriString);
624646
} else if (!created) {
625-
this._fireSoon({ type: vscode.FileChangeType.Changed, uri });
647+
this._fireSoon({ type: vscode.FileChangeType.Changed, uri: originalUri });
626648
}
627649
});
628650
}
629651

630-
/**
631-
* Notify VS Code and any watchers that the contents of `uri` changed.
632-
* Use this function instead of firing the file change event directly
633-
* when we need to force the VS Code UI to show the change. For example,
634-
* if the server changed the document during a save.
635-
*/
636-
private _notifyOfFileChange(uri: vscode.Uri): void {
637-
// The file's contents may have changed as a result of the save,
638-
// so make sure we notify VS Code and any watchers of the change
639-
const uriString = uri.toString();
640-
if (vscode.window.activeTextEditor?.document.uri.toString() == uriString) {
641-
setTimeout(() => {
642-
const activeDoc = vscode.window.activeTextEditor?.document;
643-
if (activeDoc && !activeDoc.isDirty && !activeDoc.isClosed && activeDoc.uri.toString() == uriString) {
644-
// Force VS Code to refresh the file's contents in the editor UI
645-
vscode.commands.executeCommand("workbench.action.files.revert");
646-
}
647-
}, 75);
648-
}
649-
}
650-
651652
/** Process a Document object that was successfully deleted. */
652653
private async processDeletedDoc(doc: Document, uri: vscode.Uri, csp: boolean, project: boolean): Promise<void> {
653654
const events: vscode.FileChangeEvent[] = [];
@@ -867,6 +868,9 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
867868
*/
868869
public async compile(uri: vscode.Uri, file?: File, update?: boolean): Promise<void> {
869870
if (!uri || uri.scheme != FILESYSTEM_SCHEMA) return;
871+
const originalUriString = uri.toString();
872+
const originalUri = vscode.Uri.parse(originalUriString);
873+
this._needsUpdate.delete(originalUriString);
870874
uri = redirectDotvscodeRoot(uri, new vscode.FileSystemError("Server does not have a /_vscode web application"));
871875
const compileList: string[] = [];
872876
try {
@@ -914,17 +918,36 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
914918
})
915919
.catch(() => compileErrorMsg(conf))
916920
);
917-
if (update || (file && filesToUpdate.includes(file.fileName))) {
921+
if (file && (update || filesToUpdate.includes(file.fileName))) {
918922
// This file was just written and the write may have changed its contents or the
919923
// compilation changed its contents. Therefore, we must force VS Code to update it.
920-
this._notifyOfFileChange(uri);
924+
this._needsUpdate.add(originalUriString);
925+
}
926+
if (filesToUpdate.length) {
927+
// Force VS Code to refresh the active editor tab's contents if the file was changed
928+
// by compilation and is NOT the file that was saved if this is a post-save compilation
929+
const activeDoc = vscode.window.activeTextEditor?.document;
930+
if (activeDoc && !activeDoc.isDirty && !activeDoc.isClosed) {
931+
const activeDocUriString = activeDoc.uri.toString();
932+
if (
933+
!(file && activeDocUriString == originalUriString) &&
934+
filesToUpdate.some(
935+
(f) =>
936+
DocumentContentProvider.getUri(f, undefined, undefined, undefined, originalUri)?.toString() ==
937+
activeDocUriString
938+
)
939+
) {
940+
// Force VS Code to refresh the contents in the active editor tab
941+
vscode.commands.executeCommand("workbench.action.files.revert");
942+
}
943+
}
921944
}
922945
// Fire file changed events for all files changed by compilation
923946
this._fireSoon(
924947
...filesToUpdate.map((f) => {
925948
return {
926949
type: vscode.FileChangeType.Changed,
927-
uri: DocumentContentProvider.getUri(f, undefined, undefined, undefined, uri),
950+
uri: DocumentContentProvider.getUri(f, undefined, undefined, undefined, originalUri),
928951
};
929952
})
930953
);
@@ -942,7 +965,7 @@ export class FileSystemProvider implements vscode.FileSystemProvider {
942965
).map((f: string) => {
943966
return {
944967
type: vscode.FileChangeType.Changed,
945-
uri: DocumentContentProvider.getUri(f, undefined, undefined, undefined, uri),
968+
uri: DocumentContentProvider.getUri(f, undefined, undefined, undefined, originalUri),
946969
};
947970
})
948971
);

0 commit comments

Comments
 (0)