From 49c6d25e6880e001d7f23fa764f10c559460ff55 Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Fri, 20 Dec 2019 14:25:04 +0100 Subject: [PATCH] IDEA-229351 Undo doesn't work for "copy file" action GitOrigin-RevId: 99b2657aac81bff23564daf37954fe88e448ce1e --- .../openapi/command/undo/GlobalUndoTest.java | 15 +++++++++++++++ .../openapi/vfs/newvfs/events/VFileCopyEvent.java | 6 ++++++ .../integration/LocalHistoryEventDispatcher.java | 12 +++++++----- .../openapi/command/impl/FileUndoProvider.java | 13 +++++++------ 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java b/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java index f59aa28e0520..e9c765db01fa 100644 --- a/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java +++ b/java/java-tests/testSrc/com/intellij/openapi/command/undo/GlobalUndoTest.java @@ -22,6 +22,7 @@ import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TestDialog; import com.intellij.openapi.util.EmptyRunnable; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; @@ -125,6 +126,20 @@ public class GlobalUndoTest extends UndoTestCase implements TestDialog { checkAllFilesDeleted(); } + public void testUndoFileCopy() throws Exception { + VirtualFile file = createFile("a.txt", "").getVirtualFile(); + + VirtualFile dir = file.getParent(); + VirtualFile copy = WriteCommandAction.runWriteCommandAction(myProject, (ThrowableComputable)() -> { + return file.copy(this, dir, "b.txt"); + }); + + globalUndo(); + + assertTrue(file.isValid()); + assertFalse(copy.isValid()); + } + public void testUndoRenameClass() { String firstClassName = "Class1"; String secondClassName = "Class223467234678234678236478263478"; diff --git a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileCopyEvent.java b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileCopyEvent.java index b192d532c4b9..db51ac1bb13f 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileCopyEvent.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFileCopyEvent.java @@ -19,6 +19,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileSystem; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author max @@ -51,6 +52,11 @@ public class VFileCopyEvent extends VFileEvent { return myNewChildName; } + @Nullable + public VirtualFile findCreatedFile() { + return myNewParent.isValid() ? myNewParent.findChild(myNewChildName) : null; + } + @Override @NonNls public String toString() { diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java index ea53ae5a1a5a..f2137faba05b 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryEventDispatcher.java @@ -31,6 +31,7 @@ import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.*; import com.intellij.util.containers.DisposableWrapperList; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Objects; @@ -86,7 +87,8 @@ class LocalHistoryEventDispatcher implements VirtualFileManagerListener, Command myVcs.endChangeSet(name); } - private void fileCreated(@NotNull VirtualFile file) { + private void fileCreated(@Nullable VirtualFile file) { + if (file == null) return; beginChangeSet(); createRecursively(file); endChangeSet(null); @@ -212,10 +214,10 @@ class LocalHistoryEventDispatcher implements VirtualFileManagerListener, Command private void handleAfterEvent(VFileEvent event) { if (event instanceof VFileCreateEvent) { - VirtualFile file = event.getFile(); - if (file != null) { - fileCreated(file); - } + fileCreated(event.getFile()); + } + else if (event instanceof VFileCopyEvent) { + fileCreated(((VFileCopyEvent)event).findCreatedFile()); } else if (event instanceof VFilePropertyChangeEvent) { propertyChanged((VFilePropertyChangeEvent)event); diff --git a/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java b/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java index 99065fcb1dcf..077013d8ff48 100644 --- a/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java +++ b/platform/lvcs-impl/src/com/intellij/openapi/command/impl/FileUndoProvider.java @@ -18,6 +18,7 @@ import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.*; import com.intellij.util.FileContentUtilCore; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.List; @@ -89,10 +90,10 @@ public final class FileUndoProvider implements UndoProvider, BulkFileListener { if (e instanceof VFileCreateEvent || e instanceof VFileMoveEvent || e instanceof VFilePropertyChangeEvent && ((VFilePropertyChangeEvent)e).isRename()) { - VirtualFile file = e.getFile(); - if (file != null) { - processEvent(e, file); - } + processEvent(e, e.getFile()); + } + else if (e instanceof VFileCopyEvent) { + processEvent(e, ((VFileCopyEvent)e).findCreatedFile()); } else if (e instanceof VFileDeleteEvent) { fileDeleted((VFileDeleteEvent)e); @@ -100,8 +101,8 @@ public final class FileUndoProvider implements UndoProvider, BulkFileListener { } } - private void processEvent(@NotNull VFileEvent e, @NotNull VirtualFile file) { - if (!shouldProcess(e, file)) return; + private void processEvent(@NotNull VFileEvent e, @Nullable VirtualFile file) { + if (file == null || !shouldProcess(e, file)) return; if (isUndoable(e, file)) { registerUndoableAction(file); }