[debugger-rd] IJPL-160146: Wrap XStackFrame in Ref, so StateFlow will use reference equity

GitOrigin-RevId: 6523a64381f2ba92e46d435a84cc24478df7f1f3
This commit is contained in:
Nikolay Rykunov
2024-10-10 11:21:39 +02:00
committed by intellij-monorepo-bot
parent 9150b2c2d8
commit bcfe903c87
2 changed files with 15 additions and 15 deletions

View File

@@ -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<AnAction> 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<XStackFrame> getCurrentStackFrameFlow() {
public StateFlow<Ref<XStackFrame>> 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();

View File

@@ -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