From 4df2a2b07fd52207e4d3044f78addbd513f40964 Mon Sep 17 00:00:00 2001 From: Maksim Zuev Date: Thu, 9 Oct 2025 14:09:49 +0200 Subject: [PATCH] [rd debugger] Refactor Fe session tab creation GitOrigin-RevId: 9baba3e93fb4011edf6c70614601e604675e1040 --- .../impl/frontend/FrontendXDebuggerManager.kt | 2 +- .../impl/frontend/FrontendXDebuggerSession.kt | 76 ++++++++++--------- .../xdebugger/impl/XDebugSessionImpl.kt | 6 +- .../xdebugger/impl/XDebuggerManagerImpl.java | 2 +- .../xdebugger/impl/rpc/XDebugSessionTabApi.kt | 2 +- 5 files changed, 48 insertions(+), 40 deletions(-) diff --git a/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerManager.kt b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerManager.kt index 2269465468ba..a1910049a6c1 100644 --- a/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerManager.kt +++ b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerManager.kt @@ -151,7 +151,7 @@ class FrontendXDebuggerManager(private val project: Project, private val cs: Cor } private fun getSessionIdByContentDescriptor(descriptor: RunContentDescriptor): XDebugSessionId? { - return sessionsFlow.value.firstOrNull { it.sessionTab?.runContentDescriptor === descriptor }?.id + return sessions.firstOrNull { it.sessionTab?.runContentDescriptor === descriptor }?.id } private suspend fun createDebuggerSession(sessionDto: XDebugSessionDto): XDebugSessionProxy { diff --git a/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerSession.kt b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerSession.kt index a12319a53570..c3247c202162 100644 --- a/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerSession.kt +++ b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendXDebuggerSession.kt @@ -11,6 +11,7 @@ import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.DataSink import com.intellij.openapi.actionSystem.DefaultActionGroup import com.intellij.openapi.application.EDT +import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.project.Project import com.intellij.platform.debugger.impl.frontend.evaluate.quick.FrontendXValue import com.intellij.platform.debugger.impl.frontend.frame.FrontendDropFrameHandler @@ -284,45 +285,52 @@ class FrontendXDebuggerSession private constructor( } @OptIn(AwaitCancellationAndInvoke::class) - private fun initTabInfo(tabDto: XDebuggerSessionTabDto) { + private suspend fun initTabInfo(tabDto: XDebuggerSessionTabDto) { val (tabInfo, pausedFlow) = tabDto - tabScope.launch { - if (tabInfo !is XDebuggerSessionTabInfo) return@launch + if (tabInfo !is XDebuggerSessionTabInfo) return + val backendRunContentDescriptorId = tabInfo.backendRunContendDescriptorId.await() + val executionEnvironmentId = tabInfo.executionEnvironmentId - val backendRunContentDescriptorId = tabInfo.backendRunContendDescriptorId.await() - val executionEnvironmentId = tabInfo.executionEnvironmentId + suspend fun onTabClosed() { + tabInfo.tabClosedCallback.send(Unit) + tabInfo.tabClosedCallback.close() + tabScope.cancel() + } - val proxy = this@FrontendXDebuggerSession - withContext(Dispatchers.EDT) { - // TODO restore content to reuse on frontend if needed (it is not used now in create) - XDebugSessionTab.create(proxy, tabInfo.iconId?.icon(), tabInfo.executionEnvironmentProxyDto?.executionEnvironment(project, tabScope), null, - tabInfo.forceNewDebuggerUi, tabInfo.withFramesCustomization, tabInfo.defaultFramesViewKey).apply { - setAdditionalKeysProvider { sink -> - sink[SplitDebuggerUIUtil.SPLIT_RUN_CONTENT_DESCRIPTOR_KEY] = backendRunContentDescriptorId - if (executionEnvironmentId != null) { - sink[SplitDebuggerUIUtil.SPLIT_EXECUTION_ENVIRONMENT_KEY] = executionEnvironmentId - } - } - sessionTabDeferred.complete(this) - proxy.onTabInitialized(this) - showTab() - val descriptorScope = runContentDescriptor?.coroutineScope - // don't subscribe on additional tabs if we have [ExecutionEnvironment] (it means this is Monolith) - if (descriptorScope != null && tabInfo.executionEnvironmentProxyDto?.executionEnvironment == null) { - subscribeOnAdditionalTabs(descriptorScope, this@apply, tabInfo.additionalTabsComponentManagerId) - } - descriptorScope?.awaitCancellationAndInvoke { - tabInfo.tabClosedCallback.send(Unit) - tabInfo.tabClosedCallback.close() - tabScope.cancel() - } - pausedFlow.toFlow().collectLatest { paused -> - if (paused == null) return@collectLatest - withContext(Dispatchers.EDT) { - onPause(paused.pausedByUser, paused.topFrameIsAbsent) - } + val proxy = this@FrontendXDebuggerSession + val tab = withContext(Dispatchers.EDT) { + // TODO restore content to reuse on frontend if needed (it is not used now in create) + XDebugSessionTab.create(proxy, tabInfo.iconId?.icon(), tabInfo.executionEnvironmentProxyDto?.executionEnvironment(project, tabScope), null, + tabInfo.forceNewDebuggerUi, tabInfo.withFramesCustomization, tabInfo.defaultFramesViewKey).apply { + setAdditionalKeysProvider { sink -> + sink[SplitDebuggerUIUtil.SPLIT_RUN_CONTENT_DESCRIPTOR_KEY] = backendRunContentDescriptorId + if (executionEnvironmentId != null) { + sink[SplitDebuggerUIUtil.SPLIT_EXECUTION_ENVIRONMENT_KEY] = executionEnvironmentId } } + sessionTabDeferred.complete(this) + proxy.onTabInitialized(this) + showTab() + } + } + + val runContentDescriptor = tab.runContentDescriptor + if (runContentDescriptor == null) { + onTabClosed() + thisLogger().error("Run content descriptor is not set for tab") + return + } + runContentDescriptor.coroutineScope.awaitCancellationAndInvoke { + onTabClosed() + } + // don't subscribe on additional tabs if we have [ExecutionEnvironment] (it means this is Monolith) + if (tabInfo.executionEnvironmentProxyDto?.executionEnvironment == null) { + subscribeOnAdditionalTabs(tabScope, tab, tabInfo.additionalTabsComponentManagerId) + } + + tabScope.launch(Dispatchers.EDT) { + pausedFlow.toFlow().collectLatest { paused -> + tab.onPause(paused.pausedByUser, paused.topFrameIsAbsent) } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.kt b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.kt index bd8d9957e05c..20549024b1f3 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.kt +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.kt @@ -308,7 +308,7 @@ class XDebugSessionImpl @JvmOverloads constructor( } @ApiStatus.Internal - fun getPausedEventsFlow(): Flow { + fun getPausedEventsFlow(): Flow { return myPausedEvents } @@ -551,8 +551,8 @@ class XDebugSessionImpl @JvmOverloads constructor( } fun showSessionTab() { - if (sessionTab != null) { - sessionTab!!.showTab() + if (!useFeProxy()) { + sessionTab?.showTab() } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java index 48b68a07e696..5a8a069e29d1 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerManagerImpl.java @@ -285,7 +285,7 @@ public final class XDebuggerManagerImpl extends XDebuggerManager implements Pers XDebugSessionImpl session = startSession(contentToReuse, starter, new XDebugSessionImpl(environment, this, sessionName, icon, showToolWindowOnSuspendOnly, contentToReuse)); - if (!showToolWindowOnSuspendOnly && !XDebugSessionProxy.useFeProxy()) { + if (!showToolWindowOnSuspendOnly) { session.showSessionTab(); } ProcessHandler handler = session.getDebugProcess().getProcessHandler(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/rpc/XDebugSessionTabApi.kt b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/rpc/XDebugSessionTabApi.kt index 200509743ff4..cfd70e767060 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/rpc/XDebugSessionTabApi.kt +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/rpc/XDebugSessionTabApi.kt @@ -44,7 +44,7 @@ interface XDebugSessionTabApi : RemoteApi { @Serializable data class XDebuggerSessionTabDto( val tabInfo: XDebuggerSessionTabAbstractInfo, - val pausedInfo: RpcFlow, + val pausedInfo: RpcFlow, ) @ApiStatus.Internal