IJPL-160418 Introduce a unique ID for a Project

To use Project in communication between backend and frontend, we need some sort of serializable unique id that we'd be able to pass through RPC or Rhizome.

In split mode we have to pass this id through RD protocol, because this is how Projects are synchronized there at the moment.

GitOrigin-RevId: c92b1c40830d9f7acf9fd4d0b0e13fa1828e8786
This commit is contained in:
Kate Botsman
2024-08-28 11:41:27 +02:00
committed by intellij-monorepo-bot
parent 5afbd34022
commit 0ec8f3260d
4 changed files with 129 additions and 0 deletions

View File

@@ -142,6 +142,7 @@
<orderEntry type="module" module-name="intellij.platform.kernel" />
<orderEntry type="module" module-name="intellij.platform.ide.progress" />
<orderEntry type="library" name="googlecode.plist.dd" level="project" />
<orderEntry type="module" module-name="intellij.platform.project" />
<orderEntry type="module" module-name="intellij.platform.jbr" />
<orderEntry type="module" module-name="intellij.platform.ui.jcef" />
<orderEntry type="module" module-name="fleet.util.core" />

View File

@@ -72,6 +72,8 @@ import com.intellij.platform.PlatformProjectOpenProcessor.Companion.isLoadedFrom
import com.intellij.platform.attachToProjectAsync
import com.intellij.platform.diagnostic.telemetry.impl.span
import com.intellij.platform.ide.progress.ModalTaskOwner
import com.intellij.platform.project.PROJECT_ID
import com.intellij.platform.project.ProjectId
import com.intellij.platform.workspace.jps.JpsMetrics
import com.intellij.projectImport.ProjectAttachProcessor
import com.intellij.serviceContainer.ComponentManagerImpl
@@ -1285,6 +1287,8 @@ private suspend fun initProject(
}
project.putUserDataIfAbsent(PROJECT_PATH, file)
project.putUserDataIfAbsent(PROJECT_ID, ProjectId.create())
project.registerComponents()
registerComponentActivity?.end()

View File

@@ -1,5 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="kotlin-language" name="Kotlin">
<configuration version="5" platform="JVM 17" allPlatforms="JVM [17]" useProjectSettings="false">
<compilerSettings>
<option name="additionalArguments" value="-Xjvm-default=all" />
</compilerSettings>
<compilerArguments>
<stringArguments>
<stringArg name="jvmTarget" arg="17" />
<stringArg name="apiVersion" arg="1.9" />
<stringArg name="languageVersion" arg="1.9" />
</stringArguments>
<arrayArguments>
<arrayArg name="pluginClasspaths">
<args>$KOTLIN_BUNDLED$/lib/kotlinx-serialization-compiler-plugin.jar</args>
</arrayArg>
</arrayArguments>
</compilerArguments>
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
@@ -8,5 +29,10 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="kotlin-stdlib" level="project" />
<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.kernel" />
<orderEntry type="module" module-name="intellij.platform.projectModel" />
</component>
</module>

View File

@@ -0,0 +1,98 @@
// 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.project
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.util.Key
import fleet.util.UID
import kotlinx.serialization.Serializable
import org.jetbrains.annotations.ApiStatus
@JvmField
@ApiStatus.Internal
val PROJECT_ID = Key.create<ProjectId>("ProjectImpl.PROJECT_ID")
/**
* Represents a unique identifier for a [Project].
* This [ProjectId] is shared by frontend and backend.
*
* To retrieve the id of a given project use [projectIdOrNull] or [projectId]
*/
@Serializable
@ApiStatus.Internal
class ProjectId(private val id: UID) {
/**
* This API is necessary only for Split Mode, functionality that uses RD Protocol
* for RPC use just [ProjectId], since it is serializable
*/
@ApiStatus.Internal
fun serializeToString(): String {
return id.toString()
}
companion object {
/**
* Creates a new unique identifier for a [Project]
*/
@ApiStatus.Internal
fun create(): ProjectId {
return ProjectId(UID.random())
}
/**
* This API is necessary only for Split Mode, functionality that uses RD Protocol
* for RPC use just [ProjectId], since it is serializable
*/
@ApiStatus.Internal
fun deserializeFromString(value: String): ProjectId {
return ProjectId(UID.fromString(value))
}
}
}
/**
* Provides the [ProjectId] for the given [Project].
* This [ProjectId] can be used for RPC calls between frontend and backend
*
* @return The [ProjectId] instance associated with the provided [Project],
* or null if [Project]'s implementation didn't assign id to it.
*/
@ApiStatus.Internal
fun Project.projectIdOrNull(): ProjectId? {
return getUserData(PROJECT_ID)
}
/**
* Provides the [ProjectId] for the given [Project].
* This [ProjectId] can be used for RPC calls between frontend and backend
*
* @return The [ProjectId] instance associated with the provided [Project],
* @throws IllegalStateException if [Project]'s implementation didn't assign id to it.
*/
@ApiStatus.Internal
fun Project.projectId(): ProjectId {
return projectIdOrNull() ?: error("Project ID is not set for $this")
}
/**
* Provides [Project] for the given [ProjectId].
*
* @return The [Project] instance associated with the provided [ProjectId],
* or null if there is no project with the given [ProjectId].
*/
@ApiStatus.Internal
fun ProjectId.findProjectOrNull(): Project? {
return ProjectManager.getInstance().openProjects.firstOrNull { it.getUserData(PROJECT_ID) == this }
}
/**
* Provides [Project] for the given [ProjectId].
*
* @return The [Project] instance associated with the provided [ProjectId],
* @throws IllegalStateException if there is no project with the given [ProjectId].
*/
@ApiStatus.Internal
fun ProjectId.findProject(): Project {
return findProjectOrNull() ?: error("Project is not found for $this")
}