mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
[debugger-rd] IJPL-160146: ActiveSession should be provided only by backend
GitOrigin-RevId: cb80a52ce914dcf8f7106be9e889139dbb7363ca
This commit is contained in:
committed by
intellij-monorepo-bot
parent
bcfe903c87
commit
1c1f348eeb
@@ -6,5 +6,6 @@
|
||||
<platform.rpc.backend.remoteApiProvider
|
||||
implementation="com.intellij.platform.debugger.impl.backend.BackendXDebuggerRemoteApiProviders"/>
|
||||
<platform.entityTypes implementation="com.intellij.platform.debugger.impl.backend.BackendXDebuggerEntityTypesProvider"/>
|
||||
<postStartupActivity implementation="com.intellij.platform.debugger.impl.backend.BackendXDebuggerActiveSessionControllerProjectActivity"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright 2000-2024 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.backend
|
||||
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.ProjectActivity
|
||||
import com.intellij.platform.kernel.withKernel
|
||||
import com.intellij.platform.project.asEntity
|
||||
import com.intellij.xdebugger.XDebuggerManager
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl
|
||||
import com.intellij.xdebugger.impl.XDebuggerActiveSessionEntity
|
||||
import com.intellij.xdebugger.impl.XDebuggerManagerImpl
|
||||
import com.intellij.xdebugger.impl.rpc.XDebuggerEvaluatorId
|
||||
import com.jetbrains.rhizomedb.entity
|
||||
import fleet.kernel.change
|
||||
import fleet.kernel.shared
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
|
||||
private class BackendXDebuggerActiveSessionControllerProjectActivity : ProjectActivity {
|
||||
override suspend fun execute(project: Project) {
|
||||
project.service<BackendXDebuggerActiveSessionController>().synchronizeActiveSessionWithDb()
|
||||
}
|
||||
}
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
private class BackendXDebuggerActiveSessionController(private val project: Project, private val cs: CoroutineScope) {
|
||||
fun synchronizeActiveSessionWithDb() {
|
||||
val activeSessionState = (XDebuggerManager.getInstance(project) as? XDebuggerManagerImpl)?.currentSessionFlow ?: return
|
||||
cs.launch(Dispatchers.IO) {
|
||||
activeSessionState.collectLatest { newActiveSession ->
|
||||
// if there is no active session -> remove entity from DB
|
||||
if (newActiveSession == null) {
|
||||
withKernel {
|
||||
change {
|
||||
shared {
|
||||
val projectEntity = project.asEntity()
|
||||
entity(XDebuggerActiveSessionEntity.Project, projectEntity)?.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
return@collectLatest
|
||||
}
|
||||
// remove an old session and create a new one
|
||||
val newActiveSessionEntity = withKernel {
|
||||
withKernel {
|
||||
change {
|
||||
shared {
|
||||
val projectEntity = project.asEntity()
|
||||
entity(XDebuggerActiveSessionEntity.Project, projectEntity)?.delete()
|
||||
XDebuggerActiveSessionEntity.new {
|
||||
it[XDebuggerActiveSessionEntity.Project] = projectEntity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// synchronize evaluator for the created session entity
|
||||
// this scope will be cancelled when a newActiveSession is appeared
|
||||
supervisorScope {
|
||||
launch {
|
||||
synchronizeSessionEvaluatorWithDb(newActiveSession, newActiveSessionEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun synchronizeSessionEvaluatorWithDb(session: XDebugSessionImpl, sessionEntity: XDebuggerActiveSessionEntity) {
|
||||
// NB!: we assume that the current evaluator depends only on the current StackFrame
|
||||
session.currentStackFrameFlow.collect { stackFrameRef ->
|
||||
val stackFrame = stackFrameRef.get()
|
||||
withKernel {
|
||||
change {
|
||||
val currentEvaluator = stackFrame?.evaluator
|
||||
if (currentEvaluator == null) {
|
||||
entity(LocalXDebuggerSessionEvaluatorEntity.Session, sessionEntity)?.delete()
|
||||
shared {
|
||||
sessionEntity[XDebuggerActiveSessionEntity.EvaluatorId] = null
|
||||
}
|
||||
}
|
||||
else {
|
||||
val evaluatorEntity = LocalXDebuggerSessionEvaluatorEntity.upsert(LocalXDebuggerSessionEvaluatorEntity.Session, sessionEntity) {
|
||||
it[LocalXDebuggerSessionEvaluatorEntity.Session] = sessionEntity
|
||||
it[LocalXDebuggerSessionEvaluatorEntity.Evaluator] = currentEvaluator
|
||||
}
|
||||
val evaluatorId = XDebuggerEvaluatorId(evaluatorEntity.eid)
|
||||
shared {
|
||||
sessionEntity[XDebuggerActiveSessionEntity.EvaluatorId] = evaluatorId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import com.intellij.ui.SimpleTextAttributes
|
||||
import com.intellij.xdebugger.XDebuggerBundle
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator.XEvaluationCallback
|
||||
import com.intellij.xdebugger.frame.*
|
||||
import com.intellij.xdebugger.impl.LocalXDebuggerSessionEvaluatorEntity
|
||||
import com.intellij.xdebugger.impl.rpc.*
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValuePresentationUtil.XValuePresentationTextExtractor
|
||||
import com.jetbrains.rhizomedb.entity
|
||||
|
||||
@@ -5,15 +5,20 @@ import com.intellij.platform.kernel.EntityTypeProvider
|
||||
import com.intellij.platform.project.ProjectEntity
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator
|
||||
import com.intellij.xdebugger.frame.XValue
|
||||
import com.intellij.xdebugger.impl.XDebuggerActiveSessionEntity
|
||||
import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint
|
||||
import com.jetbrains.rhizomedb.*
|
||||
import com.jetbrains.rhizomedb.EID
|
||||
import com.jetbrains.rhizomedb.Entity
|
||||
import com.jetbrains.rhizomedb.EntityType
|
||||
import com.jetbrains.rhizomedb.RefFlags
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
private class BackendXDebuggerEntityTypesProvider : EntityTypeProvider {
|
||||
override fun entityTypes(): List<EntityType<*>> {
|
||||
return listOf(
|
||||
LocalValueHintEntity,
|
||||
LocalHintXValueEntity
|
||||
LocalHintXValueEntity,
|
||||
LocalXDebuggerSessionEvaluatorEntity,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -46,4 +51,19 @@ internal data class LocalHintXValueEntity(override val eid: EID) : Entity {
|
||||
val Project = requiredRef<ProjectEntity>("project")
|
||||
val XValue = requiredTransient<XValue>("xValue")
|
||||
}
|
||||
}
|
||||
|
||||
internal data class LocalXDebuggerSessionEvaluatorEntity(override val eid: EID) : Entity {
|
||||
val sessionEntity by Session
|
||||
val evaluator by Evaluator
|
||||
|
||||
@ApiStatus.Internal
|
||||
companion object : EntityType<LocalXDebuggerSessionEvaluatorEntity>(
|
||||
LocalXDebuggerSessionEvaluatorEntity::class.java.name,
|
||||
"com.intellij",
|
||||
::LocalXDebuggerSessionEvaluatorEntity
|
||||
) {
|
||||
val Session = requiredRef<XDebuggerActiveSessionEntity>("session", RefFlags.UNIQUE)
|
||||
val Evaluator = requiredTransient<XDebuggerEvaluator>("evaluator")
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.xdebugger.impl
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.kernel.EntityTypeProvider
|
||||
import com.intellij.platform.kernel.withKernel
|
||||
import com.intellij.platform.project.ProjectEntity
|
||||
import com.intellij.platform.project.asEntity
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator
|
||||
import com.intellij.xdebugger.impl.rpc.XDebuggerEvaluatorId
|
||||
import com.jetbrains.rhizomedb.*
|
||||
import fleet.kernel.DurableEntityType
|
||||
import fleet.kernel.change
|
||||
import fleet.kernel.shared
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
private class XDebuggerActiveSessionEntityTypesProvider : EntityTypeProvider {
|
||||
override fun entityTypes(): List<EntityType<*>> {
|
||||
return listOf(
|
||||
XDebuggerActiveSessionEntity,
|
||||
LocalXDebuggerSessionEvaluatorEntity
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
data class XDebuggerActiveSessionEntity(override val eid: EID) : Entity {
|
||||
val projectEntity by Project
|
||||
val evaluatorId by EvaluatorId
|
||||
|
||||
@ApiStatus.Internal
|
||||
companion object : DurableEntityType<XDebuggerActiveSessionEntity>(
|
||||
XDebuggerActiveSessionEntity::class.java.name,
|
||||
"com.intellij",
|
||||
::XDebuggerActiveSessionEntity
|
||||
) {
|
||||
val Project = requiredRef<ProjectEntity>("project", RefFlags.UNIQUE)
|
||||
var EvaluatorId = optionalValue<XDebuggerEvaluatorId>("evaluatorId", XDebuggerEvaluatorId.serializer())
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
data class LocalXDebuggerSessionEvaluatorEntity(override val eid: EID) : Entity {
|
||||
val sessionEntity by Session
|
||||
val evaluator by Evaluator
|
||||
|
||||
@ApiStatus.Internal
|
||||
companion object : DurableEntityType<LocalXDebuggerSessionEvaluatorEntity>(
|
||||
LocalXDebuggerSessionEvaluatorEntity::class.java.name,
|
||||
"com.intellij",
|
||||
::LocalXDebuggerSessionEvaluatorEntity
|
||||
) {
|
||||
val Session = requiredRef<XDebuggerActiveSessionEntity>("session", RefFlags.UNIQUE)
|
||||
val Evaluator = requiredTransient<XDebuggerEvaluator>("evaluator")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun synchronizeActiveSessionWithDb(coroutineScope: CoroutineScope, project: Project, activeSessionState: Flow<XDebugSessionImpl?>) {
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
activeSessionState.collectLatest { newActiveSession ->
|
||||
// if there is no active session -> remove entity from DB
|
||||
if (newActiveSession == null) {
|
||||
withKernel {
|
||||
change {
|
||||
shared {
|
||||
val projectEntity = project.asEntity()
|
||||
entity(XDebuggerActiveSessionEntity.Project, projectEntity)?.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
return@collectLatest
|
||||
}
|
||||
// remove an old session and create a new one
|
||||
val newActiveSessionEntity = withKernel {
|
||||
withKernel {
|
||||
change {
|
||||
shared {
|
||||
val projectEntity = project.asEntity()
|
||||
entity(XDebuggerActiveSessionEntity.Project, projectEntity)?.delete()
|
||||
XDebuggerActiveSessionEntity.new {
|
||||
it[XDebuggerActiveSessionEntity.Project] = projectEntity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// synchronize evaluator for the created session entity
|
||||
// this scope will be cancelled when a newActiveSession is appeared
|
||||
supervisorScope {
|
||||
launch {
|
||||
synchronizeSessionEvaluatorWithDb(newActiveSession, newActiveSessionEntity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun synchronizeSessionEvaluatorWithDb(session: XDebugSessionImpl, sessionEntity: XDebuggerActiveSessionEntity) {
|
||||
// NB!: we assume that the current evaluator depends only on the current StackFrame
|
||||
session.currentStackFrameFlow.collect { stackFrameRef ->
|
||||
val stackFrame = stackFrameRef.get()
|
||||
withKernel {
|
||||
change {
|
||||
val currentEvaluator = stackFrame?.evaluator
|
||||
if (currentEvaluator == null) {
|
||||
entity(LocalXDebuggerSessionEvaluatorEntity.Session, sessionEntity)?.delete()
|
||||
shared {
|
||||
sessionEntity[XDebuggerActiveSessionEntity.EvaluatorId] = null
|
||||
}
|
||||
}
|
||||
else {
|
||||
val evaluatorEntity = LocalXDebuggerSessionEvaluatorEntity.upsert(LocalXDebuggerSessionEvaluatorEntity.Session, sessionEntity) {
|
||||
it[LocalXDebuggerSessionEvaluatorEntity.Session] = sessionEntity
|
||||
it[LocalXDebuggerSessionEvaluatorEntity.Evaluator] = currentEvaluator
|
||||
}
|
||||
val evaluatorId = XDebuggerEvaluatorId(evaluatorEntity.eid)
|
||||
shared {
|
||||
sessionEntity[XDebuggerActiveSessionEntity.EvaluatorId] = evaluatorId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.xdebugger.impl
|
||||
|
||||
import com.intellij.platform.kernel.EntityTypeProvider
|
||||
import com.intellij.platform.project.ProjectEntity
|
||||
import com.intellij.xdebugger.impl.rpc.XDebuggerEvaluatorId
|
||||
import com.jetbrains.rhizomedb.EID
|
||||
import com.jetbrains.rhizomedb.Entity
|
||||
import com.jetbrains.rhizomedb.EntityType
|
||||
import com.jetbrains.rhizomedb.RefFlags
|
||||
import fleet.kernel.DurableEntityType
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
private class XDebuggerActiveSessionEntityTypesProvider : EntityTypeProvider {
|
||||
override fun entityTypes(): List<EntityType<*>> {
|
||||
return listOf(
|
||||
XDebuggerActiveSessionEntity,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
data class XDebuggerActiveSessionEntity(override val eid: EID) : Entity {
|
||||
val projectEntity by Project
|
||||
val evaluatorId by EvaluatorId
|
||||
|
||||
@ApiStatus.Internal
|
||||
companion object : DurableEntityType<XDebuggerActiveSessionEntity>(
|
||||
XDebuggerActiveSessionEntity::class.java.name,
|
||||
"com.intellij",
|
||||
::XDebuggerActiveSessionEntity
|
||||
) {
|
||||
val Project = requiredRef<ProjectEntity>("project", RefFlags.UNIQUE)
|
||||
var EvaluatorId = optionalValue<XDebuggerEvaluatorId>("evaluatorId", XDebuggerEvaluatorId.serializer())
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,6 @@ import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import static com.intellij.xdebugger.impl.CoroutineUtilsKt.createMutableStateFlow;
|
||||
import static com.intellij.xdebugger.impl.XDebuggerActiveSessionControllerKt.synchronizeActiveSessionWithDb;
|
||||
|
||||
@ApiStatus.Internal
|
||||
@State(name = "XDebuggerManager", storages = @Storage(StoragePathMacros.WORKSPACE_FILE))
|
||||
@@ -114,8 +113,6 @@ public final class XDebuggerManagerImpl extends XDebuggerManager implements Pers
|
||||
myPinToTopManager = new XDebuggerPinToTopManager(coroutineScope);
|
||||
myExecutionPointManager = new XDebuggerExecutionPointManager(project, coroutineScope);
|
||||
|
||||
synchronizeActiveSessionWithDb(coroutineScope, project, myActiveSession);
|
||||
|
||||
messageBusConnection.subscribe(FileDocumentManagerListener.TOPIC, new FileDocumentManagerListener() {
|
||||
@Override
|
||||
public void fileContentLoaded(@NotNull VirtualFile file, @NotNull Document document) {
|
||||
|
||||
Reference in New Issue
Block a user