From cf0b1ecfabcb0ae17badb802bc46ba940b692b67 Mon Sep 17 00:00:00 2001 From: Alexander Trushev Date: Wed, 17 Sep 2025 19:27:16 +0200 Subject: [PATCH] [rd-editor] IJPL-201535 Refactor `UndoManagerImpl` GitOrigin-RevId: 530cef1022a380370a101070ab70f85dcb3afb36 --- .../openapi/command/impl/UndoClientState.java | 10 +--- .../openapi/command/impl/UndoManagerImpl.java | 46 ++++++--------- .../command/impl/UndoRedoListSnapshot.kt | 11 ++-- .../openapi/command/impl/UndoSharedState.java | 57 +++++++++++++++++++ 4 files changed, 83 insertions(+), 41 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/command/impl/UndoSharedState.java diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoClientState.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoClientState.java index 9d1c0245b6c9..13058034b177 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoClientState.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoClientState.java @@ -73,13 +73,13 @@ final class UndoClientState implements Disposable { } private UndoClientState(@NotNull UndoManagerImpl undoManager, @NotNull ClientId clientId) { + this.clientId = clientId; this.project = undoManager.getProject(); this.undoSpy = undoManager.getUndoSpy(); this.isTransparentSupported = undoManager.isTransparentSupported(); this.isConfirmationSupported = undoManager.isConfirmationSupported(); this.isCompactSupported = undoManager.isCompactSupported(); this.isGlobalSplitSupported = undoManager.isGlobalSplitSupported(); - this.clientId = clientId; this.adjustableUndoableActionsHolder = undoManager.getAdjustableUndoableActionsHolder(); this.sharedUndoStacksHolder = undoManager.getSharedUndoStacksHolder(); this.sharedRedoStacksHolder = undoManager.getSharedRedoStacksHolder(); @@ -343,10 +343,7 @@ final class UndoClientState implements Disposable { commandMerger.clearDocumentReferences(document); } - @Nullable PerClientLocalUndoRedoSnapshot getUndoRedoSnapshotForDocument( - @NotNull DocumentReference reference, - @NotNull SharedAdjustableUndoableActionsHolder adjustableUndoableActionsHolder - ) { + @Nullable PerClientLocalUndoRedoSnapshot getUndoRedoSnapshotForDocument(@NotNull DocumentReference reference) { CommandMerger currentMerger = currentCommandMerger; if (currentMerger != null && currentMerger.hasActions()) { return null; @@ -358,8 +355,7 @@ final class UndoClientState implements Disposable { return new PerClientLocalUndoRedoSnapshot( mergerSnapshot, undoStacksHolder.getStack(reference).snapshot(), - redoStacksHolder.getStack(reference).snapshot(), - adjustableUndoableActionsHolder.getStack(reference).snapshot() + redoStacksHolder.getStack(reference).snapshot() ); } diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java index d5ae9ade13e6..2facbf70f57e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoManagerImpl.java @@ -60,9 +60,7 @@ public class UndoManagerImpl extends UndoManager { } private final @Nullable Project myProject; - private final @NotNull SharedAdjustableUndoableActionsHolder myAdjustableUndoableActionsHolder; - private final @NotNull SharedUndoRedoStacksHolder mySharedUndoStacksHolder; - private final @NotNull SharedUndoRedoStacksHolder mySharedRedoStacksHolder; + private final @NotNull UndoSharedState myUndoSharedState; private @Nullable CurrentEditorProvider myOverriddenEditorProvider; @@ -80,9 +78,7 @@ public class UndoManagerImpl extends UndoManager { @NonInjectable protected UndoManagerImpl(@Nullable ComponentManager componentManager) { myProject = componentManager instanceof Project project ? project : null; - myAdjustableUndoableActionsHolder = new SharedAdjustableUndoableActionsHolder(); - mySharedUndoStacksHolder = new SharedUndoRedoStacksHolder(myAdjustableUndoableActionsHolder, isPerClientSupported(), true); - mySharedRedoStacksHolder = new SharedUndoRedoStacksHolder(myAdjustableUndoableActionsHolder, isPerClientSupported(), false); + myUndoSharedState = new UndoSharedState(isPerClientSupported()); } @Override @@ -272,8 +268,7 @@ public class UndoManagerImpl extends UndoManager { for (UndoClientState state : getAllClientStates()) { state.clearDocumentReferences(document); } - mySharedUndoStacksHolder.clearDocumentReferences(document); - mySharedRedoStacksHolder.clearDocumentReferences(document); + myUndoSharedState.clearDocumentReferences(document); } @ApiStatus.Internal @@ -345,11 +340,6 @@ public class UndoManagerImpl extends UndoManager { return state.getStackSize(docRef, isUndo); } - void trimSharedStacks(@NotNull DocumentReference docRef) { - mySharedRedoStacksHolder.trimStacks(Collections.singleton(docRef)); - mySharedUndoStacksHolder.trimStacks(Collections.singleton(docRef)); - } - @ApiStatus.Internal protected void onCommandStarted( @Nullable Project project, @@ -391,36 +381,32 @@ public class UndoManagerImpl extends UndoManager { } @Nullable LocalUndoRedoSnapshot getUndoRedoSnapshotForDocument(@NotNull DocumentReference reference) { - HashMap map = new HashMap<>(); + var perClient = new HashMap(); for (UndoClientState state : getAllClientStates()) { - PerClientLocalUndoRedoSnapshot perClientSnapshot = state.getUndoRedoSnapshotForDocument(reference, myAdjustableUndoableActionsHolder); + PerClientLocalUndoRedoSnapshot perClientSnapshot = state.getUndoRedoSnapshotForDocument(reference); if (perClientSnapshot == null) { return null; } - map.put(state.getClientId(), perClientSnapshot); + perClient.put(state.getClientId(), perClientSnapshot); } return new LocalUndoRedoSnapshot( - map, - mySharedUndoStacksHolder.getStack(reference).snapshot(), - mySharedRedoStacksHolder.getStack(reference).snapshot() + Collections.unmodifiableMap(perClient), + myUndoSharedState.getSharedUndoRedoSnapshot(reference) ); } - boolean resetLocalHistory(DocumentReference reference, LocalUndoRedoSnapshot snapshot) { + boolean resetLocalHistory(@NotNull DocumentReference reference, @NotNull LocalUndoRedoSnapshot snapshot) { for (UndoClientState state : getAllClientStates()) { PerClientLocalUndoRedoSnapshot perClientSnapshot = snapshot.getClientSnapshots().get(state.getClientId()); if (perClientSnapshot == null) { perClientSnapshot = PerClientLocalUndoRedoSnapshot.empty(); } boolean success = state.resetLocalHistory(reference, perClientSnapshot); - if (success) { - myAdjustableUndoableActionsHolder.getStack(reference).resetTo(perClientSnapshot.getActionsHolderSnapshot()); - } else { + if (!success) { return false; } } - mySharedUndoStacksHolder.getStack(reference).resetTo(snapshot.getSharedUndoStack()); - mySharedRedoStacksHolder.getStack(reference).resetTo(snapshot.getSharedRedoStack()); + myUndoSharedState.resetLocalHistory(reference, snapshot.getSharedSnapshot()); return true; } @@ -430,15 +416,15 @@ public class UndoManagerImpl extends UndoManager { } @NotNull SharedAdjustableUndoableActionsHolder getAdjustableUndoableActionsHolder() { - return myAdjustableUndoableActionsHolder; + return myUndoSharedState.getAdjustableActions(); } @NotNull SharedUndoRedoStacksHolder getSharedUndoStacksHolder() { - return mySharedUndoStacksHolder; + return myUndoSharedState.getUndoStacks(); } @NotNull SharedUndoRedoStacksHolder getSharedRedoStacksHolder() { - return mySharedRedoStacksHolder; + return myUndoSharedState.getRedoStacks(); } @TestOnly @@ -469,7 +455,7 @@ public class UndoManagerImpl extends UndoManager { if (state != null) { DocumentReference docRef = DocumentReferenceManager.getInstance().create(file); state.clearUndoRedoQueue(docRef); - trimSharedStacks(docRef); + myUndoSharedState.trimSharedStacks(docRef); } } @@ -479,7 +465,7 @@ public class UndoManagerImpl extends UndoManager { if (state != null) { DocumentReference docRef = DocumentReferenceManager.getInstance().create(document); state.clearUndoRedoQueue(docRef); - trimSharedStacks(docRef); + myUndoSharedState.trimSharedStacks(docRef); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoListSnapshot.kt b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoListSnapshot.kt index e9cb130d4c85..8149b1e9e254 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoListSnapshot.kt +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedoListSnapshot.kt @@ -43,17 +43,21 @@ internal class LocalCommandMergerSnapshot( } } -internal class LocalUndoRedoSnapshot( - val clientSnapshots: Map, +internal class SharedUndoRedoSnapshot( + val actionsHolderSnapshot: UndoRedoSetSnapshot, val sharedUndoStack: UndoRedoListSnapshot, val sharedRedoStack: UndoRedoListSnapshot, ) +internal class LocalUndoRedoSnapshot( + val clientSnapshots: Map, + val sharedSnapshot: SharedUndoRedoSnapshot, +) + internal class PerClientLocalUndoRedoSnapshot( val localCommandMergerSnapshot: LocalCommandMergerSnapshot, val undoStackSnapshot: UndoRedoListSnapshot, val redoStackSnapshot: UndoRedoListSnapshot, - val actionsHolderSnapshot: UndoRedoSetSnapshot, ) { companion object { @JvmStatic @@ -61,7 +65,6 @@ internal class PerClientLocalUndoRedoSnapshot( LocalCommandMergerSnapshot.empty(), UndoRedoList().snapshot(), UndoRedoList().snapshot(), - UndoRedoSet().snapshot(), ) } } diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoSharedState.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoSharedState.java new file mode 100644 index 000000000000..9ec41865a5af --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoSharedState.java @@ -0,0 +1,57 @@ +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.openapi.command.impl; + +import com.intellij.openapi.command.undo.DocumentReference; +import com.intellij.openapi.editor.Document; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; + + +final class UndoSharedState { + private final @NotNull SharedAdjustableUndoableActionsHolder adjustableActions; + private final @NotNull SharedUndoRedoStacksHolder undoStacks; + private final @NotNull SharedUndoRedoStacksHolder redoStacks; + + UndoSharedState(boolean isPerClientSupported) { + adjustableActions = new SharedAdjustableUndoableActionsHolder(); + undoStacks = new SharedUndoRedoStacksHolder(adjustableActions, isPerClientSupported, true); + redoStacks = new SharedUndoRedoStacksHolder(adjustableActions, isPerClientSupported, false); + } + + @NotNull SharedUndoRedoSnapshot getSharedUndoRedoSnapshot(@NotNull DocumentReference reference) { + return new SharedUndoRedoSnapshot( + adjustableActions.getStack(reference).snapshot(), + undoStacks.getStack(reference).snapshot(), + redoStacks.getStack(reference).snapshot() + ); + } + + void resetLocalHistory(@NotNull DocumentReference reference, @NotNull SharedUndoRedoSnapshot snapshot) { + adjustableActions.getStack(reference).resetTo(snapshot.getActionsHolderSnapshot()); + undoStacks.getStack(reference).resetTo(snapshot.getSharedUndoStack()); + redoStacks.getStack(reference).resetTo(snapshot.getSharedRedoStack()); + } + + void clearDocumentReferences(@NotNull Document document) { + undoStacks.clearDocumentReferences(document); + redoStacks.clearDocumentReferences(document); + } + + void trimSharedStacks(@NotNull DocumentReference docRef) { + redoStacks.trimStacks(Collections.singleton(docRef)); + undoStacks.trimStacks(Collections.singleton(docRef)); + } + + @NotNull SharedAdjustableUndoableActionsHolder getAdjustableActions() { + return adjustableActions; + } + + @NotNull SharedUndoRedoStacksHolder getUndoStacks() { + return undoStacks; + } + + @NotNull SharedUndoRedoStacksHolder getRedoStacks() { + return redoStacks; + } +}