Cleanup after update

GitOrigin-RevId: 408e26b1983444074232463125b3960768af1cac
This commit is contained in:
Nikolay Rykunov
2024-09-04 13:57:11 +02:00
committed by intellij-monorepo-bot
parent 4003441e9a
commit 3e5f254be6
10 changed files with 41 additions and 187 deletions

View File

@@ -1,138 +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.openapi.project.impl
import com.intellij.openapi.observable.util.whenDisposed
import com.intellij.openapi.progress.runBlockingMaybeCancellable
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.getOrCreateUserData
import com.intellij.platform.kernel.KernelService
import com.intellij.platform.kernel.util.flushLatestChange
import com.intellij.platform.kernel.withKernel
import com.jetbrains.rhizomedb.*
import fleet.kernel.DurableEntityType
import fleet.kernel.change
import fleet.kernel.kernel
import fleet.kernel.shared
import fleet.util.UID
import kotlinx.coroutines.withContext
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
val KERNEL_PROJECT_ID = Key.create<UID>("ProjectImpl.KERNEL_PROJECT_ID")
/**
* Represents a project entity that can be shared between backend and frontends.
* The entity is created on project initialization before any services and components are loaded.
*
* To convert a project to the entity use [asEntity]
*/
@ApiStatus.Internal
data class ProjectEntity(override val eid: EID) : Entity {
var projectId: UID by ProjectId
companion object: DurableEntityType<ProjectEntity>(ProjectEntity::class.java.name, "com.intellij", ::ProjectEntity) {
val ProjectId = requiredValue("projectId", UID.serializer(), Indexing.UNIQUE)
}
}
data class LocalProjectEntity(override val eid: EID) : Entity {
val sharedEntity: ProjectEntity by ProjectEntity
val project: Project by Project
companion object: EntityType<LocalProjectEntity>(LocalProjectEntity::class, ::LocalProjectEntity) {
val ProjectEntity = requiredRef<ProjectEntity>("sharedEntity", RefFlags.CASCADE_DELETE_BY)
val Project = requiredTransient<Project>("project")
}
}
/**
* Converts a given project to its corresponding [ProjectEntity].
*
* The method has to be called in a kernel context - see [com.intellij.platform.kernel.KernelService.kernelCoroutineContext]
*
* @return The [ProjectEntity] instance associated with the provided project,
* or null if no such entity is found
*/
@ApiStatus.Internal
fun Project.asEntity(): ProjectEntity? {
return LocalProjectEntity.all().singleOrNull { it.project == this }?.sharedEntity
}
/**
* Converts a given project entity to its corresponding [Project].
*
* The method has to be called in a kernel context - see [com.intellij.platform.kernel.KernelService.kernelCoroutineContext]
*
* @return The [Project] instance associated with the provided entity,
* or null if no such project is found (for example, if [ProjectEntity] doesn't exist anymore).
*/
@ApiStatus.Internal
fun ProjectEntity.asProject(): Project? {
return LocalProjectEntity.all().singleOrNull { it.sharedEntity == this }?.project
}
internal suspend fun Project.createEntity() = withKernel {
val project = this@createEntity
val projectId = project.getOrCreateUserData(KERNEL_PROJECT_ID) { UID.random() }
// TODO it shouldn't be here
change {
shared {
register(ProjectEntity)
}
}
change {
val projectEntity = shared {
/*
This check is added to ensure that only one ProjectEntity is going to be created in split mode.
Two entities are possible due to a different flow in creating a project in split mode.
First, a project is created on the backend (ProjectEntity is created at the same time).
Then a signal about project creation is sent to the frontend via RD protocol.
At the same time, the shared part of Rhizome DB (where ProjectEntity is stored) sends the changes to the frontend.
Events which are coming via RD protocol are not synced with events coming via Rhizome DB.
So it can happen that while on the backend the signal is sent strictly after ProjectEntity creation,
on the frontend the signal can be received before there is ProjectEntity available in DB.
If it happens that the entity has not been found and the frontend creates a new one, Rhizome DB will perform a "rebase"
which basically re-invokes the whole "change" block either on the backend or the frontend side.
*/
val existing = ProjectEntity.all().singleOrNull { it.projectId == projectId }
if (existing != null) {
existing
}
else {
ProjectEntity.new {
it[ProjectEntity.ProjectId] = projectId
}
}
}
LocalProjectEntity.new {
it[LocalProjectEntity.ProjectEntity] = projectEntity
it[LocalProjectEntity.Project] = project
}
}
project.whenDisposed {
runBlockingMaybeCancellable {
removeProjectEntity(project)
}
}
}
private suspend fun removeProjectEntity(project: Project) = withKernel {
change {
shared {
project.asEntity()?.delete()
}
}
// Removing ProjectEntity and LocalProjectEntity is the last operation in most of the tests
// Without calling "flushLatestChange" kernel keeps the project, which causes "testProjectLeak" failures
kernel().flushLatestChange()
}

View File

@@ -116,7 +116,6 @@
<action id="Resume" class="com.intellij.xdebugger.impl.actions.ResumeAction" icon="AllIcons.Actions.Resume"/>
<separator/>
<action id="EvaluateExpression" class="com.intellij.xdebugger.impl.actions.EvaluateAction" icon="AllIcons.Debugger.EvaluateExpression"/>
<action id="QuickEvaluateExpression" class="com.intellij.xdebugger.impl.actions.QuickEvaluateAction"/>
<action id="ShowExecutionPoint" class="com.intellij.xdebugger.impl.actions.ShowExecutionPointAction"
icon="AllIcons.Debugger.ShowCurrentFrame"/>
<separator/>

View File

@@ -16,7 +16,8 @@
<arrayArg name="pluginClasspaths">
<args>
<arg>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</arg>
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/1.9.20-0.1/rpc-compiler-plugin-1.9.20-0.1.jar</arg>
<arg>$MAVEN_REPOSITORY$/jetbrains/fleet/rhizomedb-compiler-plugin/2.0.0-0.22/rhizomedb-compiler-plugin-2.0.0-0.22.jar</arg>
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/2.0.0-0.2/rpc-compiler-plugin-2.0.0-0.2.jar</arg>
</args>
</arrayArg>
<arrayArg name="pluginOptions" />
@@ -46,5 +47,6 @@
<orderEntry type="library" name="fastutil-min" level="project" />
<orderEntry type="module" module-name="intellij.platform.concurrency" />
<orderEntry type="module" module-name="intellij.platform.ide.impl" />
<orderEntry type="module" module-name="intellij.platform.project" />
</component>
</module>

View File

@@ -7,19 +7,15 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.impl.EditorId
import com.intellij.openapi.editor.impl.findEditor
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.impl.ProjectEntity
import com.intellij.openapi.project.impl.asProject
import com.intellij.platform.kernel.KernelService
import com.intellij.platform.kernel.withKernel
import com.intellij.platform.project.ProjectId
import com.intellij.platform.project.findProject
import com.intellij.platform.rpc.backend.RemoteApiProvider
import com.intellij.xdebugger.impl.DebuggerSupport
import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint
import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType
import com.intellij.xdebugger.impl.rpc.RemoteValueHint
import com.intellij.xdebugger.impl.rpc.XDebuggerValueLookupHintsRemoteApi
import com.jetbrains.rhizomedb.entity
import fleet.rpc.remoteApiDescriptor
import fleet.util.UID
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -41,9 +37,9 @@ private class BackendDebuggerValueLookupHintsRemoteApiProvider : RemoteApiProvid
}
private class BackendDebuggerValueLookupHintsRemoteApi : XDebuggerValueLookupHintsRemoteApi {
override suspend fun canShowHint(projectId: UID, editorId: EditorId, offset: Int, hintType: ValueHintType): Boolean {
override suspend fun canShowHint(projectId: ProjectId, editorId: EditorId, offset: Int, hintType: ValueHintType): Boolean {
return withContext(Dispatchers.Main) {
val project = getProjectFromUID(projectId) ?: return@withContext false
val project = projectId.findProject()
val editor = editorId.findEditor()
val point = editor.offsetToXY(offset)
@@ -52,9 +48,9 @@ private class BackendDebuggerValueLookupHintsRemoteApi : XDebuggerValueLookupHin
}
}
override suspend fun createHint(projectId: UID, editorId: EditorId, offset: Int, hintType: ValueHintType): RemoteValueHint? {
override suspend fun createHint(projectId: ProjectId, editorId: EditorId, offset: Int, hintType: ValueHintType): RemoteValueHint? {
return withContext(Dispatchers.Main) {
val project = getProjectFromUID(projectId) ?: return@withContext null
val project = projectId.findProject()
val editor = editorId.findEditor()
val point = editor.offsetToXY(offset)
@@ -82,8 +78,8 @@ private class BackendDebuggerValueLookupHintsRemoteApi : XDebuggerValueLookupHin
return null
}
override suspend fun showHint(projectId: UID, hintId: Int): Flow<Unit> {
val project = getProjectFromUID(projectId) ?: return emptyFlow()
override suspend fun showHint(projectId: ProjectId, hintId: Int): Flow<Unit> {
val project = projectId.findProject()
val hint = BackendDebuggerValueLookupHintsHolder.getInstance(project).getHintById(hintId) ?: return emptyFlow()
return callbackFlow {
withContext(Dispatchers.Main) {
@@ -96,21 +92,14 @@ private class BackendDebuggerValueLookupHintsRemoteApi : XDebuggerValueLookupHin
}
}
override suspend fun removeHint(projectId: UID, hintId: Int) {
val project = getProjectFromUID(projectId) ?: return
override suspend fun removeHint(projectId: ProjectId, hintId: Int) {
val project = projectId.findProject()
val hint = BackendDebuggerValueLookupHintsHolder.getInstance(project).getHintById(hintId) ?: return
BackendDebuggerValueLookupHintsHolder.getInstance(project).removeHint(hintId)
withContext(Dispatchers.Main) {
hint.hideHint()
}
}
private suspend fun getProjectFromUID(projectId: UID): Project? {
return withKernel {
val projectEntity = entity<ProjectEntity, UID>(ProjectEntity.ProjectId, projectId)
projectEntity?.asProject()
}
}
}
// exposed only for backend.split part

View File

@@ -14,7 +14,11 @@
</stringArguments>
<arrayArguments>
<arrayArg name="pluginClasspaths">
<args>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/1.9.20-0.1/rpc-compiler-plugin-1.9.20-0.1.jar</args>
<args>
<arg>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</arg>
<arg>$MAVEN_REPOSITORY$/jetbrains/fleet/rhizomedb-compiler-plugin/2.0.0-0.22/rhizomedb-compiler-plugin-2.0.0-0.22.jar</arg>
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/2.0.0-0.2/rpc-compiler-plugin-2.0.0-0.2.jar</arg>
</args>
</arrayArg>
<arrayArg name="pluginOptions" />
</arrayArguments>
@@ -41,5 +45,6 @@
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
<orderEntry type="module" module-name="intellij.platform.core" />
<orderEntry type="module" module-name="intellij.platform.project" />
</component>
</module>

View File

@@ -2,12 +2,14 @@
package com.intellij.platform.debugger.impl.frontend.evaluate.quick.common
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.impl.asProject
import com.intellij.platform.kernel.withKernel
import com.intellij.platform.project.asProject
import com.intellij.xdebugger.impl.evaluate.XDebuggerValueLookupHideHintsRequestEntity
import com.intellij.xdebugger.impl.evaluate.XDebuggerValueLookupListeningStartedEntity
import fleet.kernel.change
import fleet.kernel.rete.*
import fleet.kernel.rete.collect
import fleet.kernel.rete.each
import fleet.kernel.rete.filter
import fleet.kernel.shared
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -22,7 +24,7 @@ internal fun subscribeForDebuggingStart(cs: CoroutineScope, project: Project, on
register(XDebuggerValueLookupListeningStartedEntity)
}
}
XDebuggerValueLookupListeningStartedEntity.each().filter { it.projectEntity.asProject()!! === project }.collect {
XDebuggerValueLookupListeningStartedEntity.each().filter { it.projectEntity.asProject() === project }.collect {
withContext(Dispatchers.Main) {
onStartListening()
}
@@ -39,7 +41,7 @@ internal fun subscribeForValueHintHideRequest(cs: CoroutineScope, project: Proje
register(XDebuggerValueLookupHideHintsRequestEntity)
}
}
XDebuggerValueLookupHideHintsRequestEntity.each().filter { it.projectEntity.asProject()!! === project }.collect { entity ->
XDebuggerValueLookupHideHintsRequestEntity.each().filter { it.projectEntity.asProject() === project }.collect { entity ->
withContext(Dispatchers.Main) {
onHintHidden()
}

View File

@@ -5,22 +5,20 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.editor.impl.editorId
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.impl.asEntity
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.TextRange
import com.intellij.platform.kernel.KernelService
import com.intellij.platform.kernel.withKernel
import com.intellij.platform.project.ProjectId
import com.intellij.platform.project.projectId
import com.intellij.platform.rpc.RemoteApiProviderService
import com.intellij.platform.util.coroutines.childScope
import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint
import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler
import com.intellij.xdebugger.impl.evaluate.quick.common.QuickEvaluateHandler.CancellableHint
import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType
import com.intellij.xdebugger.impl.rpc.RemoteValueHint
import com.intellij.xdebugger.impl.rpc.XDebuggerValueLookupHintsRemoteApi
import com.intellij.xdebugger.settings.XDebuggerSettingsManager
import fleet.rpc.remoteApiDescriptor
import fleet.util.UID
import kotlinx.coroutines.*
import kotlinx.coroutines.future.asCompletableFuture
import org.jetbrains.annotations.ApiStatus
@@ -42,7 +40,6 @@ open class ValueLookupManagerQuickEvaluateHandler : QuickEvaluateHandler() {
return null
}
@OptIn(DelicateCoroutinesApi::class)
override fun createValueHintAsync(project: Project, editor: Editor, point: Point, type: ValueHintType?): CancellableHint {
if (type == null) {
return CancellableHint(resolvedPromise(), null)
@@ -54,11 +51,7 @@ open class ValueLookupManagerQuickEvaluateHandler : QuickEvaluateHandler() {
val hint: Deferred<AbstractValueHint?> = coroutineScope.async(Dispatchers.IO) {
withKernel {
val remoteApi = RemoteApiProviderService.resolve(remoteApiDescriptor<XDebuggerValueLookupHintsRemoteApi>())
val projectEntity = project.asEntity()
if (projectEntity == null) {
return@withKernel null
}
val projectId = projectEntity.projectId
val projectId = project.projectId()
val editorId = editor.editorId()
val canShowHint = remoteApi.canShowHint(projectId, editorId, offset, type)
if (!canShowHint) {
@@ -92,7 +85,7 @@ open class ValueLookupManagerQuickEvaluateHandler : QuickEvaluateHandler() {
private class ValueLookupManagerValueHint(
private val parentCoroutineScope: CoroutineScope,
project: Project, private val projectId: UID,
project: Project, private val projectId: ProjectId,
private val editor: Editor,
point: Point,
private val type: ValueHintType,
@@ -101,7 +94,6 @@ private class ValueLookupManagerValueHint(
private var remoteHint: Deferred<RemoteValueHint?>? = null
private var hintCoroutineScope: CoroutineScope? = null
@OptIn(DelicateCoroutinesApi::class)
override fun evaluateAndShowHint() {
hintCoroutineScope = parentCoroutineScope.childScope("ValueLookupManagerValueHintScope")
val remoteHint = hintCoroutineScope!!.async(Dispatchers.IO) {

View File

@@ -16,7 +16,8 @@
<arrayArg name="pluginClasspaths">
<args>
<arg>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</arg>
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/1.9.20-0.1/rpc-compiler-plugin-1.9.20-0.1.jar</arg>
<arg>$MAVEN_REPOSITORY$/jetbrains/fleet/rhizomedb-compiler-plugin/2.0.0-0.22/rhizomedb-compiler-plugin-2.0.0-0.22.jar</arg>
<arg>$MAVEN_REPOSITORY$/com/jetbrains/fleet/rpc-compiler-plugin/2.0.0-0.2/rpc-compiler-plugin-2.0.0-0.2.jar</arg>
</args>
</arrayArg>
<arrayArg name="pluginOptions" />
@@ -57,5 +58,6 @@
<orderEntry type="module" module-name="intellij.platform.kernel" />
<orderEntry type="library" name="kotlinx-serialization-core" level="project" />
<orderEntry type="library" name="kotlinx-serialization-json" level="project" />
<orderEntry type="module" module-name="intellij.platform.project" />
</component>
</module>

View File

@@ -4,10 +4,10 @@ package com.intellij.xdebugger.impl.evaluate
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.impl.ProjectEntity
import com.intellij.openapi.project.impl.asEntity
import com.intellij.openapi.util.Key
import com.intellij.platform.kernel.withKernel
import com.intellij.platform.project.ProjectEntity
import com.intellij.platform.project.asEntity
import com.jetbrains.rhizomedb.EID
import com.jetbrains.rhizomedb.Entity
import fleet.kernel.DurableEntityType
@@ -69,7 +69,7 @@ class ValueLookupManagerController(private val project: Project, private val cs:
change {
shared {
XDebuggerValueLookupListeningStartedEntity.new {
it[XDebuggerValueLookupListeningStartedEntity.Project] = project.asEntity()!!
it[XDebuggerValueLookupListeningStartedEntity.Project] = project.asEntity()
}
}
}
@@ -89,7 +89,7 @@ class ValueLookupManagerController(private val project: Project, private val cs:
shared {
register(XDebuggerValueLookupHideHintsRequestEntity)
XDebuggerValueLookupHideHintsRequestEntity.new {
it[XDebuggerValueLookupHideHintsRequestEntity.Project] = project.asEntity()!!
it[XDebuggerValueLookupHideHintsRequestEntity.Project] = project.asEntity()
}
}
}

View File

@@ -2,6 +2,7 @@
package com.intellij.xdebugger.impl.rpc
import com.intellij.openapi.editor.impl.EditorId
import com.intellij.platform.project.ProjectId
import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType
import fleet.rpc.RemoteApi
import fleet.rpc.Rpc
@@ -13,13 +14,13 @@ import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
@Rpc
interface XDebuggerValueLookupHintsRemoteApi : RemoteApi<Unit> {
suspend fun canShowHint(projectId: UID, editorId: EditorId, offset: Int, hintType: ValueHintType): Boolean
suspend fun canShowHint(projectId: ProjectId, editorId: EditorId, offset: Int, hintType: ValueHintType): Boolean
suspend fun createHint(projectId: UID, editorId: EditorId, offset: Int, hintType: ValueHintType): RemoteValueHint?
suspend fun createHint(projectId: ProjectId, editorId: EditorId, offset: Int, hintType: ValueHintType): RemoteValueHint?
suspend fun showHint(projectId: UID, hintId: Int): Flow<Unit>
suspend fun showHint(projectId: ProjectId, hintId: Int): Flow<Unit>
suspend fun removeHint(projectId: UID, hintId: Int)
suspend fun removeHint(projectId: ProjectId, hintId: Int)
}
@ApiStatus.Internal