From d05e2ad41e02d98b5120dcbb6d3749ea9fce3b6e Mon Sep 17 00:00:00 2001 From: Maksim Zuev Date: Fri, 15 Aug 2025 14:31:00 +0200 Subject: [PATCH] [rd debugger] Provide a way to handle mutable XDescriptors GitOrigin-RevId: 28cebb63cc78d9b73c1003209aa027b07eb6cf5e --- ...tellij.platform.debugger.impl.frontend.xml | 2 + .../FrontendDescriptorStateManager.kt | 50 +++++++++++++++++++ .../frontend/evaluate/quick/FrontendXValue.kt | 8 +++ 3 files changed, 60 insertions(+) create mode 100644 platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendDescriptorStateManager.kt diff --git a/platform/xdebugger-impl/frontend/resources/intellij.platform.debugger.impl.frontend.xml b/platform/xdebugger-impl/frontend/resources/intellij.platform.debugger.impl.frontend.xml index 33be8b48db0c..fd6c25ff8e4a 100644 --- a/platform/xdebugger-impl/frontend/resources/intellij.platform.debugger.impl.frontend.xml +++ b/platform/xdebugger-impl/frontend/resources/intellij.platform.debugger.impl.frontend.xml @@ -10,6 +10,8 @@ + diff --git a/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendDescriptorStateManager.kt b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendDescriptorStateManager.kt new file mode 100644 index 000000000000..0a14acff90f9 --- /dev/null +++ b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/FrontendDescriptorStateManager.kt @@ -0,0 +1,50 @@ +// 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.platform.debugger.impl.frontend + +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.service +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.project.Project +import com.intellij.xdebugger.frame.XDescriptor +import fleet.multiplatform.shims.ConcurrentHashMap +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.job +import org.jetbrains.annotations.ApiStatus + +/** + * Creates a plugin-specific state for a given [XDescriptor]. + * For example, if a [XDescriptor] contains a flow, this extension should create an object which will keep the flow's state. + */ +@ApiStatus.Internal +interface FrontendDescriptorStateManagerExtension { + fun createState(descriptor: XDescriptor, cs: CoroutineScope): Any? + + companion object { + private val EP_NAME = ExtensionPointName.create("com.intellij.xdebugger.descriptorStateManager") + + fun createState(descriptor: XDescriptor, cs: CoroutineScope): Any? { + return EP_NAME.extensionList.firstNotNullOfOrNull { it.createState(descriptor, cs) } + } + } +} + +@ApiStatus.Internal +@Service(Service.Level.PROJECT) +class FrontendDescriptorStateManager { + private val states = ConcurrentHashMap() + + internal fun registerDescriptor(descriptor: XDescriptor, cs: CoroutineScope) { + val state = FrontendDescriptorStateManagerExtension.createState(descriptor, cs) ?: return + states[descriptor] = state + cs.coroutineContext.job.invokeOnCompletion { states.remove(descriptor) } + } + + fun getState(descriptor: XDescriptor): Any? { + return states[descriptor] + } + + companion object { + @JvmStatic + fun getInstance(project: Project): FrontendDescriptorStateManager = project.service() + } +} diff --git a/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/evaluate/quick/FrontendXValue.kt b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/evaluate/quick/FrontendXValue.kt index 6fcfc4a6d94c..bc4c7fa4ef81 100644 --- a/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/evaluate/quick/FrontendXValue.kt +++ b/platform/xdebugger-impl/frontend/src/com/intellij/platform/debugger/impl/frontend/evaluate/quick/FrontendXValue.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.project.Project import com.intellij.openapi.util.NlsSafe +import com.intellij.platform.debugger.impl.frontend.FrontendDescriptorStateManager import com.intellij.platform.debugger.impl.rpc.* import com.intellij.platform.util.coroutines.childScope import com.intellij.util.ConcurrencyUtil @@ -38,6 +39,13 @@ class FrontendXValue private constructor( private val presentation: StateFlow, ) : XValue(), XValueTextProvider { + init { + cs.launch { + val descriptor = xValueDto.descriptor?.await() ?: return@launch + FrontendDescriptorStateManager.getInstance(project).registerDescriptor(descriptor, cs) + } + } + @Volatile private var modifier: XValueModifier? = null