Revert "Revert "VIM-547 Add timestamps to UndoManager""

This reverts commit 6a64d7fef4f38d5e5dc86916e63d0c4886bc505b.

GitOrigin-RevId: bbb2d9de24615a9d99458f7afc797098fb37f8c9
This commit is contained in:
Filipp Vakhitov
2024-01-17 01:50:15 +00:00
committed by intellij-monorepo-bot
parent f44ac9d622
commit 87694ae89c
12 changed files with 160 additions and 12 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
public abstract class BasicUndoableAction implements UndoableAction {
private final DocumentReference[] myRefs;
private long myPerformedTimestamp = -1L;
public BasicUndoableAction() {
myRefs = null;
@@ -41,4 +42,14 @@ public abstract class BasicUndoableAction implements UndoableAction {
public boolean isGlobal() {
return false;
}
@Override
public long getPerformedNanoTime() {
return myPerformedTimestamp;
}
@Override
public void setPerformedNanoTime(long l) {
myPerformedTimestamp = l;
}
}
@@ -8,6 +8,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NlsActions;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,4 +49,16 @@ public abstract class UndoManager {
public abstract @NotNull Pair<@NlsActions.ActionText String, @NlsActions.ActionDescription String> getUndoActionNameAndDescription(FileEditor editor);
public abstract @NotNull Pair<@NlsActions.ActionText String, @NlsActions.ActionDescription String> getRedoActionNameAndDescription(FileEditor editor);
@ApiStatus.Experimental
public abstract long getNextUndoNanoTime(@NotNull FileEditor editor);
@ApiStatus.Experimental
public abstract long getNextRedoNanoTime(@NotNull FileEditor editor);
@ApiStatus.Experimental
public abstract boolean isNextUndoAskConfirmation(@NotNull FileEditor editor);
@ApiStatus.Experimental
public abstract boolean isNextRedoAskConfirmation(@NotNull FileEditor editor);
}
@@ -1,14 +1,21 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.command.undo;
package com.intellij.openapi.command.undo
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ApiStatus
/**
* @see UndoManager#undoableActionPerformed(UndoableAction)
* @see UndoManager.undoableActionPerformed
*/
public interface UndoableAction {
void undo() throws UnexpectedUndoException;
void redo() throws UnexpectedUndoException;
interface UndoableAction {
@get:ApiStatus.Experimental
@set:ApiStatus.Experimental
var performedNanoTime: Long
@Throws(UnexpectedUndoException::class)
fun undo()
@Throws(UnexpectedUndoException::class)
fun redo()
/**
* Returns the documents, affected by this action.
@@ -16,10 +23,10 @@ public interface UndoableAction {
* The action can be undone if all of its affected documents are either
* not affected by any of further actions or all of such actions are undone.
*/
DocumentReference @Nullable [] getAffectedDocuments();
val affectedDocuments: Array<DocumentReference>?
/**
* Global actions are those, that can be undone not only from the document of the file, but also from the project tree view.
*/
boolean isGlobal();
val isGlobal: Boolean
}
@@ -33,9 +33,11 @@ class SuggestedRefactoringUndoableAction private constructor(
private val documentReference = DocumentReferenceManager.getInstance().create(document)
override fun getAffectedDocuments(): Array<DocumentReference> = arrayOf(documentReference)
override var performedNanoTime: Long = -1
override fun isGlobal(): Boolean = false
override val affectedDocuments: Array<DocumentReference> = arrayOf(documentReference)
override val isGlobal: Boolean = false
override fun undo() {
val document = documentReference.document ?: return
@@ -178,6 +178,26 @@ public abstract class UndoRedoAction extends DumbAwareAction implements LightEdi
return getUndoOrRedoActionNameAndDescription( false);
}
@Override
public long getNextUndoNanoTime(@NotNull FileEditor editor) {
return -1L;
}
@Override
public long getNextRedoNanoTime(@NotNull FileEditor editor) {
return -1L;
}
@Override
public boolean isNextUndoAskConfirmation(@NotNull FileEditor editor) {
return false;
}
@Override
public boolean isNextRedoAskConfirmation(@NotNull FileEditor editor) {
return false;
}
private static @NotNull Pair<String, String> getUndoOrRedoActionNameAndDescription(boolean undo) {
if (undo) {
return Pair.create(
@@ -16,6 +16,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.concurrency.ThreadingAssertions;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
* Undo action can be available even if this Document is ReadOnly.
*/
final class MentionOnlyUndoableAction implements UndoableAction {
private long myPerformedTimestamp = -1L;
private final DocumentReference[] myRefs;
MentionOnlyUndoableAction(DocumentReference @NotNull [] refs) {
@@ -33,4 +34,14 @@ final class MentionOnlyUndoableAction implements UndoableAction {
public boolean isGlobal() {
return false;
}
@Override
public long getPerformedNanoTime() {
return myPerformedTimestamp;
}
@Override
public void setPerformedNanoTime(long l) {
myPerformedTimestamp = l;
}
}
@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull;
final class NonUndoableAction implements UndoableAction {
private static final Logger LOG = Logger.getInstance(NonUndoableAction.class);
private long myPerformedTimestamp = -1;
private final DocumentReference[] myRefs;
private final boolean myGlobal;
@@ -39,4 +39,14 @@ final class NonUndoableAction implements UndoableAction {
public boolean isGlobal() {
return myGlobal;
}
@Override
public long getPerformedNanoTime() {
return myPerformedTimestamp;
}
@Override
public void setPerformedNanoTime(long l) {
myPerformedTimestamp = l;
}
}
@@ -332,6 +332,7 @@ public final class UndoManagerImpl extends UndoManager {
return;
}
action.setPerformedNanoTime(System.nanoTime());
if (state.myCommandLevel == 0) {
LOG.assertTrue(action instanceof NonUndoableAction,
"Undoable actions allowed inside commands only (see com.intellij.openapi.command.CommandProcessor.executeCommand())");
@@ -631,6 +632,58 @@ public final class UndoManagerImpl extends UndoManager {
return getUndoOrRedoActionNameAndDescription(editor, false);
}
@Override
public long getNextUndoNanoTime(@NotNull FileEditor editor) {
return getNextNanoTime(editor, true);
}
@Override
public long getNextRedoNanoTime(@NotNull FileEditor editor) {
return getNextNanoTime(editor, false);
}
@Override
public boolean isNextUndoAskConfirmation(@NotNull FileEditor editor) {
return isNextAskConfirmation(editor, true);
}
@Override
public boolean isNextRedoAskConfirmation(@NotNull FileEditor editor) {
return isNextAskConfirmation(editor, false);
}
private long getNextNanoTime(@NotNull FileEditor editor, boolean isUndo) {
ClientState clientState = getClientState(editor);
Collection<DocumentReference> references = getDocRefs(editor);
if (clientState == null || references == null) {
return -1L;
}
if (isUndo) {
clientState.myMerger.flushCurrentCommand();
}
@NotNull UndoRedoStacksHolder stack = getStackHolder(clientState, isUndo);
UndoableGroup lastAction = stack.getLastAction(references);
return lastAction == null ? -1L : lastAction.getGroupStartPerformedTimestamp();
}
private boolean isNextAskConfirmation(@NotNull FileEditor editor, boolean isUndo) {
ClientState clientState = getClientState(editor);
Collection<DocumentReference> references = getDocRefs(editor);
if (clientState == null || references == null) {
return false;
}
if (isUndo) {
clientState.myMerger.flushCurrentCommand();
}
@NotNull UndoRedoStacksHolder stack = getStackHolder(clientState, isUndo);
UndoableGroup lastAction = stack.getLastAction(references);
return lastAction != null && lastAction.shouldAskConfirmation(!isUndo);
}
private @NotNull Pair<@NlsActions.ActionText String, @NlsActions.ActionDescription String> getUndoOrRedoActionNameAndDescription(@Nullable FileEditor editor, boolean undo) {
String desc = isUndoOrRedoAvailable(editor, undo) ? doFormatAvailableUndoRedoAction(editor, undo) : null;
if (desc == null) desc = "";
@@ -7,6 +7,7 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.util.*;
@@ -26,7 +27,7 @@ final class UndoRedoStacksHolder extends UndoRedoStacksHolderBase<UndoableGroup>
return false;
}
@NotNull
@Nullable
UndoableGroup getLastAction(@NotNull Collection<? extends DocumentReference> refs) {
if (refs.isEmpty()) return myGlobalStack.getLast();
@@ -18,6 +18,7 @@ import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -352,12 +353,18 @@ final class UndoableGroup implements Dumpable {
return null;
}
@ApiStatus.Experimental
boolean shouldAskConfirmation(boolean redo) {
if (shouldAskConfirmationForStartFinishGroup(redo)) return true;
return myConfirmationPolicy == UndoConfirmationPolicy.REQUEST_CONFIRMATION ||
myConfirmationPolicy != UndoConfirmationPolicy.DO_NOT_REQUEST_CONFIRMATION && myGlobal;
}
long getGroupStartPerformedTimestamp() {
if (myActions.isEmpty()) return -1L;
return Math.min(myActions.get(0).getPerformedNanoTime(), myActions.get(myActions.size() - 1).getPerformedNanoTime());
}
void invalidateChangeRanges() {
for (UndoableAction action : myActions) {
if (action instanceof AdjustableUndoableAction) {
@@ -338,6 +338,8 @@ public final class EditPropertyValueAction extends BaseRefactoringAction {
new VisualPosition(regionStartPosition.line, regionStartPosition.column + placeholderColumn));
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
UndoManager.getInstance(project).undoableActionPerformed(new UndoableAction() {
private long myPerformedTimestamp = -1L;
@Override
public void undo() {
if (foldRegion.isValid()) {
@@ -361,6 +363,16 @@ public final class EditPropertyValueAction extends BaseRefactoringAction {
public boolean isGlobal() {
return false;
}
@Override
public long getPerformedNanoTime() {
return myPerformedTimestamp;
}
@Override
public void setPerformedNanoTime(long performedTimestamp) {
myPerformedTimestamp = performedTimestamp;
}
});
}, targetPsiFile);
editorComponent.paintImmediately(new Rectangle(editorComponent.getSize()));