Implement isolated Build and Refresh with immutable leased snapshots

This commit is contained in:
2026-11-12 09:28:25 +01:00
parent 85a75383a0
commit e97af99412
27 changed files with 2066 additions and 15 deletions
@@ -90,6 +90,26 @@ public final class IntellijDocuments implements HostServices.Documents, AutoClos
});
}
public CompletionStage<List<DocumentSnapshot>> unsaved() {
return edt(
() -> {
var result = new ArrayList<DocumentSnapshot>();
var manager = FileDocumentManager.getInstance();
for (var document : manager.getUnsavedDocuments()) {
var file = manager.getFile(document);
if (file == null || !file.isInLocalFileSystem()) continue;
var handle =
(Handle) open(Path.of(file.getPath()).toUri()).toCompletableFuture().join();
try {
result.add(snapshot(handle.s));
} finally {
handle.release();
}
}
return List.copyOf(result);
});
}
private DocumentSnapshot snapshot(State s) {
return new DocumentSnapshot(
Path.of(s.file.getPath()).toUri(),
@@ -171,7 +191,13 @@ public final class IntellijDocuments implements HostServices.Documents, AutoClos
if (!s.document.isWritable() || !s.file.isWritable())
throw new IllegalStateException("Read-only document");
Path file = Path.of(s.file.getPath());
if (!Files.readString(file).equals(s.disk))
String onDisk = Files.readString(file);
if (!FileDocumentManager.getInstance().isDocumentUnsaved(s.document)
&& onDisk.equals(s.document.getText())) {
s.disk = onDisk;
return IntellijDocuments.this.snapshot(s);
}
if (!onDisk.equals(s.disk))
throw new ConcurrentModificationException("External change; draft retained");
FileDocumentManager.getInstance().saveDocument(s.document);
if (FileDocumentManager.getInstance().isDocumentUnsaved(s.document))
@@ -0,0 +1,35 @@
package de.neitzel.fxdesigner.intellij;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import com.intellij.testFramework.fixtures.BasePlatformTestCase;
import java.nio.file.*;
public final class BuildInputInventoryTest extends BasePlatformTestCase {
public void testNativeJavaDraftInventoryAndAutosaveBeforeExplicitSave() throws Exception {
Path file = Files.createTempFile("designer-build-input-", ".java").toRealPath();
Files.writeString(file, "class Original {}");
VfsRootAccess.allowRootAccess(getTestRootDisposable(), file.toString());
try (var documents = new IntellijDocuments(getProject())) {
var virtual = LocalFileSystem.getInstance().refreshAndFindFileByNioFile(file);
var nativeDocument = FileDocumentManager.getInstance().getDocument(virtual);
WriteCommandAction.runWriteCommandAction(
getProject(), () -> nativeDocument.setText("class Edited {}"));
var draft =
documents.unsaved().toCompletableFuture().get().stream()
.filter(d -> d.document().equals(file.toUri()))
.findFirst()
.orElseThrow();
assertTrue(draft.dirty());
FileDocumentManager.getInstance().saveDocument(nativeDocument);
try (var handle = documents.open(file.toUri()).toCompletableFuture().get()) {
assertFalse(handle.save(draft.revision()).toCompletableFuture().get().dirty());
}
assertEquals("class Edited {}", Files.readString(file));
} finally {
Files.deleteIfExists(file);
}
}
}