mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[rd debugger] IJPL-215857 Refactor: introduce XContainerId to unify computeChildren processing
IJ-CR-181826 GitOrigin-RevId: 8da907315334878315bae09eedc855b253e14610
This commit is contained in:
committed by
intellij-monorepo-bot
parent
dfc9f40a52
commit
7d20442491
-5
@@ -62,11 +62,6 @@ internal class BackendXExecutionStackApi : XExecutionStackApi {
|
||||
}.buffer(Channel.UNLIMITED)
|
||||
}
|
||||
|
||||
override fun computeVariables(xStackFrameId: XStackFrameId): Flow<XValueComputeChildrenEvent> {
|
||||
val stackFrameModel = xStackFrameId.findValue() ?: return emptyFlow()
|
||||
return computeContainerChildren(stackFrameModel.coroutineScope, stackFrameModel.stackFrame, stackFrameModel.session)
|
||||
}
|
||||
|
||||
override suspend fun canDrop(sessionId: XDebugSessionId, stackFrameId: XStackFrameId): Boolean {
|
||||
val session = sessionId.findValue() ?: return false
|
||||
val stack = stackFrameId.findValue() ?: return false
|
||||
|
||||
+31
-43
@@ -31,19 +31,13 @@ internal class BackendXValueApi : XValueApi {
|
||||
return xValueModel.computeTooltipPresentation()
|
||||
}
|
||||
|
||||
override fun computeChildren(xValueId: XValueId): Flow<XValueComputeChildrenEvent> {
|
||||
val xValueModel = BackendXValueModel.findById(xValueId) ?: return emptyFlow()
|
||||
return computeContainerChildren(xValueModel.cs, xValueModel.xValue, xValueModel.session)
|
||||
}
|
||||
|
||||
override fun computeXValueGroupChildren(xValueGroupId: XValueGroupId): Flow<XValueComputeChildrenEvent> {
|
||||
val xValueModel = xValueGroupId.findValue() ?: return emptyFlow()
|
||||
return computeContainerChildren(xValueModel.cs, xValueModel.xValueGroup, xValueModel.session)
|
||||
override fun computeChildren(id: XContainerId): Flow<XValueComputeChildrenEvent> {
|
||||
return computeChildrenInternal(id)
|
||||
}
|
||||
|
||||
override fun computeExpandedChildren(frameId: XStackFrameId, root: XDebuggerTreeExpandedNode): Flow<PreloadChildrenEvent> {
|
||||
return channelFlow {
|
||||
processExpandedChildren(XContainer.Frame(frameId), this, root)
|
||||
processExpandedChildren(frameId, this, root)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +171,7 @@ private class AddNextChildrenCallbackHandler(cs: CoroutineScope) {
|
||||
}
|
||||
|
||||
@Suppress("OPT_IN_USAGE")
|
||||
internal fun computeContainerChildren(
|
||||
private fun computeContainerChildren(
|
||||
parentCs: CoroutineScope,
|
||||
xValueContainer: XValueContainer,
|
||||
session: XDebugSessionImpl,
|
||||
@@ -326,48 +320,42 @@ private sealed interface RawComputeChildrenEvent {
|
||||
}
|
||||
}
|
||||
|
||||
private sealed interface XContainer {
|
||||
fun createExpandEvent(event: XValueComputeChildrenEvent): PreloadChildrenEvent.ExpandedChildrenEvent
|
||||
fun createPreloadEvent(): PreloadChildrenEvent.ToBePreloaded
|
||||
suspend fun computeChildren(): Flow<XValueComputeChildrenEvent>
|
||||
|
||||
data class Value(val id: XValueId) : XContainer {
|
||||
override fun createExpandEvent(event: XValueComputeChildrenEvent) = PreloadChildrenEvent.ExpandedChildrenEvent.Value(id, event)
|
||||
override fun createPreloadEvent() = PreloadChildrenEvent.ToBePreloaded.Value(id)
|
||||
override suspend fun computeChildren() = XValueApi.getInstance().computeChildren(id)
|
||||
}
|
||||
|
||||
data class Group(val id: XValueGroupId) : XContainer {
|
||||
override fun createExpandEvent(event: XValueComputeChildrenEvent) = PreloadChildrenEvent.ExpandedChildrenEvent.Group(id, event)
|
||||
override fun createPreloadEvent() = PreloadChildrenEvent.ToBePreloaded.Group(id)
|
||||
override suspend fun computeChildren() = XValueApi.getInstance().computeXValueGroupChildren(id)
|
||||
}
|
||||
|
||||
data class Frame(val id: XStackFrameId) : XContainer {
|
||||
override fun createExpandEvent(event: XValueComputeChildrenEvent) = PreloadChildrenEvent.ExpandedChildrenEvent.Frame(id, event)
|
||||
override fun createPreloadEvent() = error("Frame preload event is implicit")
|
||||
override suspend fun computeChildren() = XExecutionStackApi.getInstance().computeVariables(id)
|
||||
private fun computeChildrenInternal(containerId: XContainerId): Flow<XValueComputeChildrenEvent> {
|
||||
val (container, scope, session) = when (containerId) {
|
||||
is XStackFrameId -> {
|
||||
val stackFrameModel = containerId.findValue() ?: return emptyFlow()
|
||||
Triple(stackFrameModel.stackFrame, stackFrameModel.coroutineScope, stackFrameModel.session)
|
||||
}
|
||||
is XValueGroupId -> {
|
||||
val xGroupModel = containerId.findValue() ?: return emptyFlow()
|
||||
Triple(xGroupModel.xValueGroup, xGroupModel.cs, xGroupModel.session)
|
||||
}
|
||||
is XValueId -> {
|
||||
val xValueModel = BackendXValueModel.findById(containerId) ?: return emptyFlow()
|
||||
Triple(xValueModel.xValue, xValueModel.cs, xValueModel.session)
|
||||
}
|
||||
}
|
||||
return computeContainerChildren(scope, container, session)
|
||||
}
|
||||
|
||||
/**
|
||||
* Match [XContainer] children with [XDebuggerTreeExpandedNode] children, and start child computation if matched.
|
||||
* Match [XContainerId] children with [XDebuggerTreeExpandedNode] children, and start child computation if matched.
|
||||
*/
|
||||
private suspend fun processExpandedChildren(id: XContainer, producerScope: ProducerScope<PreloadChildrenEvent>, root: XDebuggerTreeExpandedNode) {
|
||||
private suspend fun processExpandedChildren(id: XContainerId, producerScope: ProducerScope<PreloadChildrenEvent>, root: XDebuggerTreeExpandedNode) {
|
||||
val name2Child = MultiMap<String, XDebuggerTreeExpandedNode>()
|
||||
for (child in root.children) {
|
||||
name2Child.putValue(child.name, child)
|
||||
}
|
||||
|
||||
val childrenEventsFlow = id.computeChildren()
|
||||
val childrenEventsFlow = computeChildrenInternal(id)
|
||||
childrenEventsFlow.collect { event ->
|
||||
val childrenToLoad = collectChildrenToLoad(event, name2Child)
|
||||
// notify which children are going to be preloaded
|
||||
for ((childId, _) in childrenToLoad) {
|
||||
producerScope.send(childId.createPreloadEvent())
|
||||
producerScope.send(PreloadChildrenEvent.ToBePreloaded(childId))
|
||||
}
|
||||
// then pass the original event
|
||||
producerScope.send(id.createExpandEvent(event))
|
||||
producerScope.send(PreloadChildrenEvent.ExpandedChildrenEvent(id, event))
|
||||
// and then start children loading
|
||||
for ((childId, node) in childrenToLoad) {
|
||||
producerScope.launch {
|
||||
@@ -380,9 +368,9 @@ private suspend fun processExpandedChildren(id: XContainer, producerScope: Produ
|
||||
private fun collectChildrenToLoad(
|
||||
event: XValueComputeChildrenEvent,
|
||||
name2Child: MultiMap<String, XDebuggerTreeExpandedNode>,
|
||||
): List<Pair<XContainer, XDebuggerTreeExpandedNode>> {
|
||||
): List<Pair<XContainerId, XDebuggerTreeExpandedNode>> {
|
||||
if (event !is XValueComputeChildrenEvent.AddChildren) return emptyList()
|
||||
val children = mutableListOf<Pair<XContainer, XDebuggerTreeExpandedNode>>()
|
||||
val children = mutableListOf<Pair<XContainerId, XDebuggerTreeExpandedNode>>()
|
||||
val namedContainers = collectNamedChildren(event)
|
||||
|
||||
for ((name, childId) in namedContainers) {
|
||||
@@ -395,17 +383,17 @@ private fun collectChildrenToLoad(
|
||||
return children
|
||||
}
|
||||
|
||||
private fun collectNamedChildren(event: XValueComputeChildrenEvent.AddChildren): List<Pair<String, XContainer>> {
|
||||
val nameAndId = mutableListOf<Pair<String, XContainer>>()
|
||||
private fun collectNamedChildren(event: XValueComputeChildrenEvent.AddChildren): List<Pair<String, XContainerId>> {
|
||||
val nameAndId = mutableListOf<Pair<String, XContainerId>>()
|
||||
for (group in event.topGroups) {
|
||||
nameAndId += group.groupName to XContainer.Group(group.id)
|
||||
nameAndId += group.groupName to group.id
|
||||
}
|
||||
for (value in event.topValues + event.children) {
|
||||
val name = value.name ?: continue
|
||||
nameAndId += name to XContainer.Value(value.id)
|
||||
nameAndId += name to value.id
|
||||
}
|
||||
for (group in event.bottomGroups) {
|
||||
nameAndId += group.groupName to XContainer.Group(group.id)
|
||||
nameAndId += group.groupName to group.id
|
||||
}
|
||||
return nameAndId
|
||||
}
|
||||
|
||||
+1
-3
@@ -68,9 +68,7 @@ class FrontendXValue private constructor(
|
||||
var canMarkValue: Boolean = false
|
||||
private set
|
||||
|
||||
private val xValueContainer = FrontendXValueContainer(project, cs, hasParentValue, xValueDto.id) {
|
||||
XValueApi.getInstance().computeChildren(xValueDto.id)
|
||||
}
|
||||
private val xValueContainer = FrontendXValueContainer(project, cs, hasParentValue, xValueDto.id)
|
||||
|
||||
private val fullValueEvaluator = fullValueEvaluatorFlow.map { evaluatorDto ->
|
||||
if (evaluatorDto == null) {
|
||||
|
||||
+4
-5
@@ -5,10 +5,11 @@ import com.intellij.ide.ui.icons.icon
|
||||
import com.intellij.openapi.application.EDT
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.debugger.impl.frontend.frame.PreloadManagerContainer
|
||||
import com.intellij.platform.debugger.impl.rpc.XContainerId
|
||||
import com.intellij.platform.debugger.impl.rpc.XValueApi
|
||||
import com.intellij.platform.debugger.impl.rpc.XValueComputeChildrenEvent
|
||||
import com.intellij.platform.debugger.impl.rpc.XValueGroupDto
|
||||
import com.intellij.platform.debugger.impl.shared.XValuesPresentationBuilder
|
||||
import com.intellij.platform.rpc.Id
|
||||
import com.intellij.ui.SimpleTextAttributes
|
||||
import com.intellij.xdebugger.frame.XCompositeNode
|
||||
import com.intellij.xdebugger.frame.XNamedValue
|
||||
@@ -16,20 +17,18 @@ import com.intellij.xdebugger.frame.XValueChildrenList
|
||||
import com.intellij.xdebugger.frame.XValueContainer
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class FrontendXValueContainer(
|
||||
private val project: Project,
|
||||
private val cs: CoroutineScope,
|
||||
private val hasParentValue: Boolean,
|
||||
private val id: Id,
|
||||
private val childrenComputation: suspend () -> Flow<XValueComputeChildrenEvent>,
|
||||
private val id: XContainerId,
|
||||
) : XValueContainer() {
|
||||
override fun computeChildren(node: XCompositeNode) {
|
||||
val preloadManager = cs.coroutineContext[PreloadManagerContainer]?.manager
|
||||
node.childCoroutineScope(parentScope = cs, "FrontendXValueContainer#computeChildren").launch(Dispatchers.EDT) {
|
||||
val flow = preloadManager?.getChildrenEventsFlow(id) ?: childrenComputation()
|
||||
val flow = preloadManager?.getChildrenEventsFlow(id) ?: XValueApi.getInstance().computeChildren(id)
|
||||
val builder = XValuesPresentationBuilder()
|
||||
flow.collect { event ->
|
||||
when (event) {
|
||||
|
||||
+1
-4
@@ -4,7 +4,6 @@ package com.intellij.platform.debugger.impl.frontend.evaluate.quick
|
||||
import com.intellij.ide.ui.icons.icon
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.platform.debugger.impl.rpc.XValueApi
|
||||
import com.intellij.platform.debugger.impl.rpc.XValueGroupDto
|
||||
import com.intellij.xdebugger.frame.XCompositeNode
|
||||
import com.intellij.xdebugger.frame.XValueGroup
|
||||
@@ -18,9 +17,7 @@ internal class FrontendXValueGroup(
|
||||
hasParentValue: Boolean,
|
||||
) : XValueGroup(xValueGroupDto.groupName) {
|
||||
|
||||
private val xValueContainer = FrontendXValueContainer(project, cs, hasParentValue, xValueGroupDto.id) {
|
||||
XValueApi.getInstance().computeXValueGroupChildren(xValueGroupDto.id)
|
||||
}
|
||||
private val xValueContainer = FrontendXValueContainer(project, cs, hasParentValue, xValueGroupDto.id)
|
||||
|
||||
override fun computeChildren(node: XCompositeNode) {
|
||||
xValueContainer.computeChildren(node)
|
||||
|
||||
+1
-3
@@ -43,9 +43,7 @@ internal class FrontendXStackFrame(
|
||||
createFrontendXDebuggerEvaluator(project, suspendContextLifetimeScope, evaluatorDto, id)
|
||||
}
|
||||
|
||||
private val xValueContainer = FrontendXValueContainer(project, cs, false, id) {
|
||||
XExecutionStackApi.getInstance().computeVariables(id)
|
||||
}
|
||||
private val xValueContainer = FrontendXValueContainer(project, cs, false, id)
|
||||
|
||||
val backgroundColor: Color?
|
||||
get() = bgColor?.colorId?.color()
|
||||
|
||||
+4
-5
@@ -3,11 +3,9 @@ package com.intellij.platform.debugger.impl.frontend.frame
|
||||
|
||||
import com.intellij.openapi.diagnostic.fileLogger
|
||||
import com.intellij.platform.debugger.impl.rpc.*
|
||||
import com.intellij.platform.rpc.Id
|
||||
import com.intellij.platform.util.coroutines.childScope
|
||||
import com.intellij.util.AwaitCancellationAndInvoke
|
||||
import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState
|
||||
import fleet.multiplatform.shims.ConcurrentHashMap
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
@@ -17,6 +15,7 @@ import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
import kotlin.coroutines.AbstractCoroutineContextElement
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@@ -50,7 +49,7 @@ class VariablesPreloadManager(
|
||||
frameId: XStackFrameId,
|
||||
) {
|
||||
private val cs = parentScope.childScope("VariablesPreloadManager")
|
||||
private val preloadedEvents = ConcurrentHashMap<Id, Channel<XValueComputeChildrenEvent>>()
|
||||
private val preloadedEvents = ConcurrentHashMap<XContainerId, Channel<XValueComputeChildrenEvent>>()
|
||||
|
||||
init {
|
||||
markToBeLoaded(frameId)
|
||||
@@ -72,14 +71,14 @@ class VariablesPreloadManager(
|
||||
}
|
||||
}
|
||||
|
||||
fun getChildrenEventsFlow(entityId: Id): Flow<XValueComputeChildrenEvent>? {
|
||||
fun getChildrenEventsFlow(entityId: XContainerId): Flow<XValueComputeChildrenEvent>? {
|
||||
val eventsChannel = preloadedEvents[entityId] ?: return null
|
||||
return channelFlow {
|
||||
eventsChannel.consumeEach { send(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun markToBeLoaded(id: Id) {
|
||||
private fun markToBeLoaded(id: XContainerId) {
|
||||
val old = preloadedEvents.put(id, Channel(capacity = Channel.UNLIMITED))
|
||||
assert(old == null) { "Channel for $id was already registered" }
|
||||
}
|
||||
|
||||
+1
-3
@@ -17,8 +17,6 @@ interface XExecutionStackApi : RemoteApi<Unit> {
|
||||
|
||||
suspend fun computeStackFrames(executionStackId: XExecutionStackId, firstFrameIndex: Int): Flow<XStackFramesEvent>
|
||||
|
||||
fun computeVariables(xStackFrameId: XStackFrameId): Flow<XValueComputeChildrenEvent>
|
||||
|
||||
suspend fun canDrop(sessionId: XDebugSessionId, stackFrameId: XStackFrameId): Boolean
|
||||
suspend fun dropFrame(sessionId: XDebugSessionId, stackFrameId: XStackFrameId)
|
||||
|
||||
@@ -42,7 +40,7 @@ data class XExecutionStackId(override val uid: UID) : Id
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
data class XStackFrameId(override val uid: UID) : Id
|
||||
data class XStackFrameId(override val uid: UID) : XContainerId
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
|
||||
+9
-26
@@ -18,8 +18,7 @@ import org.jetbrains.annotations.ApiStatus
|
||||
interface XValueApi : RemoteApi<Unit> {
|
||||
suspend fun computeTooltipPresentation(xValueId: XValueId): Flow<XValueSerializedPresentation>
|
||||
|
||||
fun computeChildren(xValueId: XValueId): Flow<XValueComputeChildrenEvent>
|
||||
fun computeXValueGroupChildren(xValueGroupId: XValueGroupId): Flow<XValueComputeChildrenEvent>
|
||||
fun computeChildren(id: XContainerId): Flow<XValueComputeChildrenEvent>
|
||||
fun computeExpandedChildren(frameId: XStackFrameId, root: XDebuggerTreeExpandedNode): Flow<PreloadChildrenEvent>
|
||||
|
||||
suspend fun disposeXValue(xValueId: XValueId)
|
||||
@@ -40,17 +39,21 @@ interface XValueApi : RemoteApi<Unit> {
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
sealed interface XContainerId : Id
|
||||
|
||||
/**
|
||||
* @see com.intellij.xdebugger.impl.rpc.models.BackendXValueModel
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
data class XValueId(override val uid: UID) : Id
|
||||
data class XValueId(override val uid: UID) : XContainerId
|
||||
|
||||
/** @see com.intellij.xdebugger.impl.rpc.models.BackendXValueGroupModel */
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
data class XValueGroupId(override val uid: UID) : Id
|
||||
data class XValueGroupId(override val uid: UID) : XContainerId
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
@@ -70,28 +73,8 @@ data class XDebuggerTreeExpandedNode(
|
||||
@Serializable
|
||||
sealed interface PreloadChildrenEvent {
|
||||
@Serializable
|
||||
sealed interface ToBePreloaded : PreloadChildrenEvent {
|
||||
val id: Id
|
||||
|
||||
@Serializable
|
||||
data class Value(override val id: XValueId) : ToBePreloaded
|
||||
|
||||
@Serializable
|
||||
data class Group(override val id: XValueGroupId) : ToBePreloaded
|
||||
}
|
||||
data class ToBePreloaded(val id: XContainerId) : PreloadChildrenEvent
|
||||
|
||||
@Serializable
|
||||
sealed interface ExpandedChildrenEvent : PreloadChildrenEvent {
|
||||
val id: Id
|
||||
val event: XValueComputeChildrenEvent
|
||||
|
||||
@Serializable
|
||||
data class Frame(override val id: XStackFrameId, override val event: XValueComputeChildrenEvent) : ExpandedChildrenEvent
|
||||
|
||||
@Serializable
|
||||
data class Value(override val id: XValueId, override val event: XValueComputeChildrenEvent) : ExpandedChildrenEvent
|
||||
|
||||
@Serializable
|
||||
data class Group(override val id: XValueGroupId, override val event: XValueComputeChildrenEvent) : ExpandedChildrenEvent
|
||||
}
|
||||
data class ExpandedChildrenEvent(val id: XContainerId, val event: XValueComputeChildrenEvent) : PreloadChildrenEvent
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user