From bcfe903c871f30242d0be298fb6655d57e89bfeb Mon Sep 17 00:00:00 2001 From: Nikolay Rykunov Date: Thu, 10 Oct 2024 11:21:39 +0200 Subject: [PATCH] [debugger-rd] IJPL-160146: Wrap XStackFrame in Ref, so StateFlow will use reference equity GitOrigin-RevId: 6523a64381f2ba92e46d435a84cc24478df7f1f3 --- .../xdebugger/impl/XDebugSessionImpl.java | 27 +++++++++---------- .../impl/XDebuggerActiveSessionController.kt | 3 ++- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index 14704feffb00..55adb44cdd2a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -27,6 +27,7 @@ import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; import com.intellij.platform.util.coroutines.CoroutineScopeKt; import com.intellij.ui.AppUIUtil; import com.intellij.util.EventDispatcher; @@ -56,10 +57,7 @@ import com.intellij.xdebugger.stepping.XSmartStepIntoHandler; import com.intellij.xdebugger.stepping.XSmartStepIntoVariant; import kotlin.coroutines.EmptyCoroutineContext; import kotlinx.coroutines.CoroutineScope; -import kotlinx.coroutines.flow.FlowKt; -import kotlinx.coroutines.flow.MutableStateFlow; -import kotlinx.coroutines.flow.StateFlow; -import kotlinx.coroutines.flow.StateFlowKt; +import kotlinx.coroutines.flow.*; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -113,7 +111,7 @@ public final class XDebugSessionImpl implements XDebugSession { private final List myExtraActions = new SmartList<>(); private ConsoleView myConsoleView; private final Icon myIcon; - private final MutableStateFlow<@Nullable XStackFrame> myCurrentStackFrame = createMutableStateFlow(null); + private final MutableStateFlow<@NotNull Ref<@Nullable XStackFrame>> myCurrentStackFrame = createMutableStateFlow(Ref.create(null)); private volatile boolean breakpointsInitialized; private long myUserRequestStart; @@ -269,14 +267,15 @@ public final class XDebugSessionImpl implements XDebugSession { return myPaused.get(); } + // returns Ref to skip StateFlow's equals check @ApiStatus.Internal - public StateFlow getCurrentStackFrameFlow() { + public StateFlow> getCurrentStackFrameFlow() { return myCurrentStackFrame; } @Override public @Nullable XStackFrame getCurrentStackFrame() { - return myCurrentStackFrame.getValue(); + return myCurrentStackFrame.getValue().get(); } public @Nullable XExecutionStack getCurrentExecutionStack() { @@ -290,7 +289,7 @@ public final class XDebugSessionImpl implements XDebugSession { @Override public @Nullable XSourcePosition getCurrentPosition() { - return getFrameSourcePosition(myCurrentStackFrame.getValue()); + return getFrameSourcePosition(myCurrentStackFrame.getValue().get()); } @Override @@ -672,7 +671,7 @@ public final class XDebugSessionImpl implements XDebugSession { private void clearPausedData() { mySuspendContext = null; myCurrentExecutionStack = null; - myCurrentStackFrame.setValue(null); + myCurrentStackFrame.setValue(Ref.create(null)); myTopStackFrame = null; clearActiveNonLineBreakpoint(); updateExecutionPosition(); @@ -687,8 +686,8 @@ public final class XDebugSessionImpl implements XDebugSession { // allowed only for the active session if (myDebuggerManager.getCurrentSession() == this) { boolean isTopFrame = isTopFrameSelected(); - XSourcePosition mainSourcePosition = getFrameSourcePosition(myCurrentStackFrame.getValue(), XSourceKind.MAIN); - XSourcePosition alternativeSourcePosition = getFrameSourcePosition(myCurrentStackFrame.getValue(), XSourceKind.ALTERNATIVE); + XSourcePosition mainSourcePosition = getFrameSourcePosition(myCurrentStackFrame.getValue().get(), XSourceKind.MAIN); + XSourcePosition alternativeSourcePosition = getFrameSourcePosition(myCurrentStackFrame.getValue().get(), XSourceKind.ALTERNATIVE); myExecutionPointManager.setExecutionPoint(mainSourcePosition, alternativeSourcePosition, isTopFrame, navigationSourceKind); updateExecutionPointGutterIconRenderer(); } @@ -717,9 +716,9 @@ public final class XDebugSessionImpl implements XDebugSession { public void setCurrentStackFrame(@NotNull XExecutionStack executionStack, @NotNull XStackFrame frame, boolean isTopFrame) { if (mySuspendContext == null) return; - boolean frameChanged = myCurrentStackFrame.getValue() != frame; + boolean frameChanged = myCurrentStackFrame.getValue().get() != frame; myCurrentExecutionStack = executionStack; - myCurrentStackFrame.setValue(frame); + myCurrentStackFrame.setValue(Ref.create(frame)); myIsTopFrame = isTopFrame; if (frameChanged) { @@ -942,7 +941,7 @@ public final class XDebugSessionImpl implements XDebugSession { mySuspendContext = suspendContext; myCurrentExecutionStack = suspendContext.getActiveExecutionStack(); XStackFrame newCurrentStackFrame = myCurrentExecutionStack != null ? myCurrentExecutionStack.getTopFrame() : null; - myCurrentStackFrame.setValue(newCurrentStackFrame); + myCurrentStackFrame.setValue(Ref.create(newCurrentStackFrame)); myIsTopFrame = true; myTopStackFrame = newCurrentStackFrame; XSourcePosition topFramePosition = getTopFramePosition(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerActiveSessionController.kt b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerActiveSessionController.kt index c1750f8590df..a8d72ef6bf8d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerActiveSessionController.kt +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerActiveSessionController.kt @@ -103,7 +103,8 @@ internal fun synchronizeActiveSessionWithDb(coroutineScope: CoroutineScope, proj private suspend fun synchronizeSessionEvaluatorWithDb(session: XDebugSessionImpl, sessionEntity: XDebuggerActiveSessionEntity) { // NB!: we assume that the current evaluator depends only on the current StackFrame - session.currentStackFrameFlow.collect { stackFrame -> + session.currentStackFrameFlow.collect { stackFrameRef -> + val stackFrame = stackFrameRef.get() withKernel { change { val currentEvaluator = stackFrame?.evaluator