Порівняти коміти

...
Автор SHA1 Повідомлення Дата
l0ng-ai 6a1289e3db fix(editor): log why an edit was rejected before the editor drops it
When the backend rejects an edit for any reason but a stale version, the
editor replaces its unsaved text with the file's content. The reason was
only printed to the webview console, so a report of edits that roll back
had nothing to go on. The backend now logs the rejected edit with its path,
and the editor writes the sync error and the discarded edits to the log
file.
2026-11-05 22:04:20 +08:00
3 змінених файлів з 15 додано та 5 видалено

No files matched your search

+7 -1
Переглянути файл
@@ -537,9 +537,15 @@ impl Documents {
pub fn edit(&self, doc: DocId, base_version: u32, changes: ChangeSet) -> IdeResult<u32> {
self.with_doc(doc, |st| {
if st.read_only {
tracing::warn!("edit rejected: {} is read-only", st.path.display());
return Err(read_only_error(&st.path));
}
let (applied, edits) = st.doc.apply_detailed(base_version, &changes)?;
let (applied, edits) = st.doc.apply_detailed(base_version, &changes).inspect_err(|e| {
// A stale version is routine (the UI rebases); anything else makes the editor drop the edit.
if e.kind != ErrorKind::OutOfSync {
tracing::warn!("edit of {} rejected: {e}", st.path.display());
}
})?;
self.set_dirty(doc, st, true);
self.notify_changed(doc, st, &applied, &edits);
Ok(st.doc.version())
+6 -3
Переглянути файл
@@ -62,6 +62,7 @@ import {
import { setMethodLines, softWrapActive } from "../cm/prefs";
import type { EditorSlot } from "./slot";
import { tx } from "@/platform/i18n";
import { logError } from "@/platform/errorLog";
import { WorkspaceHistory } from "./workspaceHistory";
export type Banner = "binary" | "tooLarge" | "readOnly" | "library" | null;
@@ -263,13 +264,15 @@ export class DocModel {
},
{
applyRemote: (cs, grouped) => this.applyRemote(cs, grouped),
onDiscarded: () =>
onDiscarded: (reason) => {
logError(`document ${this.path}: unsaved edits replaced by the file's content`, reason);
manager.notify({
level: "warning",
title: "Editor resynchronised",
body: tx`Some unsaved edits to ${this.path} could not be applied and were replaced by the file's current content.`,
}),
onError: (e) => console.warn(`document ${this.path}: sync error`, e),
});
},
onError: (e) => logError(`document ${this.path}: sync error`, e),
},
manager.scheduler,
);
+2 -1
Переглянути файл
@@ -226,7 +226,8 @@ describe("DocSync", () => {
await server.processAll();
await flushMicrotasks();
expect(view.text.toString()).toBe("abc");
expect(host.onDiscarded).toHaveBeenCalled();
// The rejection reaches the host, which writes it to the log file.
expect(host.onDiscarded).toHaveBeenCalledWith(expect.objectContaining({ kind: "permissionDenied" }));
expect(sync.idle).toBe(true);
});