IJPL-201747 Better docs for Experimental RPC APi

GitOrigin-RevId: 230dab513f61ba3323b2dc9df27b8de2e59095c5
This commit is contained in:
Kate Botsman
2025-08-15 18:55:27 +02:00
committed by intellij-monorepo-bot
parent 4396e5c683
commit 063e189d5d
7 changed files with 231 additions and 21 deletions

View File

@@ -8,7 +8,25 @@ import kotlinx.serialization.Transient
import org.jetbrains.annotations.ApiStatus
/**
* Converts an [DataContext] instance into a [DataContextId] which can be used in RPC calls and stored in Rhizome.
* Converts a [DataContext] instance into a [DataContextId] which can be used in RPC calls and stored in Rhizome.
*
* **WARNING: Use with extreme care, and preferably avoid using this function at all.**
*
* In the monolith version of the IDE, this essentially stores a reference to the original DataContext object.
* In Remote Development scenarios, this function attempts to serialize the entire DataContext for RPC transmission,
* but **not all elements of DataContext can be properly sent/retrieved** using this mechanism.
* Many DataContext values may:
* - Not be serializable
* - Reference local IDE components that don't exist on the remote side
* - Contain complex objects that can't be safely transmitted
*
* **Recommended approach:** Instead of using this function, manually send only the specific data you need
* via RPC. This ensures better reliability, performance, and maintainability.
*
* **For custom data types:** If you need to serialize custom DataContext elements, implement
* [com.intellij.ide.CustomDataContextSerializer] for your specific data types.
*
* @return A [DataContextId] that can be used in RPC calls, but may not contain all original DataContext elements
*/
@ApiStatus.Experimental
fun DataContext.rpcId(): DataContextId {
@@ -20,6 +38,26 @@ fun DataContext.rpcId(): DataContextId {
/**
* Retrieves the [DataContext] associated with the given [DataContextId].
*
* **WARNING: Use with extreme care, and preferably avoid using this function at all.**
*
* In the monolith version of the IDE, this method essentially does nothing - it just reuses the original
* object that was passed to [rpcId]. However, in distributed scenarios (Remote Development), this function
* attempts to deserialize a DataContext from RPC data, but **not all elements of DataContext can be properly
* sent/retrieved** using this mechanism. The retrieved DataContext may:
* - Be missing important data that couldn't be serialized
* - Contain stale or invalid references
* - Not reflect the current state of the IDE
* - Fail to deserialize complex objects properly
*
* **Recommended approach:** Instead of using this function, manually send only the specific data you need
* via RPC and work with that data directly. This ensures better reliability, performance, and maintainability.
*
* **For custom data types:** If you need to deserialize custom DataContext elements, implement
* [com.intellij.ide.CustomDataContextSerializer] for your specific data types.
*
* @return The deserialized [DataContext] if available, or null if deserialization fails or no context is available.
* Note that even a non-null result may not contain all expected DataContext elements.
*/
@ApiStatus.Experimental
fun DataContextId.dataContext(): DataContext? {

View File

@@ -11,7 +11,19 @@ import org.jetbrains.annotations.ApiStatus
private val LOG = fileLogger()
/**
* Converts an [Document] instance into a [DocumentId] which can be used in RPC calls and stored in Rhizome.
* Converts a [Document] instance into a [DocumentId] which can be used in RPC calls and stored in Rhizome.
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this essentially stores a reference to the original document object.
* In Remote Development scenarios, the document is serialized for transmission to the frontend.
*
* Important limitations:
* - **Won't work for documents created manually on the frontend** - only documents that exist in the backend
* IDE instance can be properly serialized and retrieved
* - Document state may not be fully synchronized with the backend's one
*
* @return A [DocumentId] that can be used in RPC calls
*/
@ApiStatus.Experimental
fun Document.rpcId(): DocumentId {
@@ -22,6 +34,20 @@ fun Document.rpcId(): DocumentId {
/**
* Retrieves the [Document] associated with the given [DocumentId].
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this method essentially does nothing - it just reuses the original
* document object that was passed to [rpcId]. However, in distributed scenarios (Remote Development), this
* function attempts to deserialize a Document from RPC data.
*
* Important limitations:
* - **Won't work for documents created manually on the frontend** - only documents that originated from
* the backend IDE instance can be properly retrieved
* - Document state may not be fully synchronized with the frontend's one
* - May return null if deserialization fails or the document is no longer available
*
* @return The [Document] if available, or null if deserialization fails or the document cannot be found
*/
@ApiStatus.Experimental
fun DocumentId.document(): Document? {

View File

@@ -14,7 +14,14 @@ import java.awt.Color
private val LOG = fileLogger()
/**
* Converts an [Color] instance into a [ColorId] which can be used in RPC calls and stored in Rhizome.
* Converts a [Color] instance into a [ColorId] which can be used in RPC calls and stored in Rhizome.
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this essentially stores a reference to the original Color object.
* In Remote Development scenarios, the Color is serialized for transmission to the frontend.
*
* @return A [ColorId] that can be used in RPC calls
*/
@ApiStatus.Experimental
fun Color.rpcId(): ColorId {
@@ -26,6 +33,14 @@ fun Color.rpcId(): ColorId {
/**
* Retrieves the [Color] associated with the given [ColorId].
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this method essentially does nothing - it just reuses the original
* Color object that was passed to [rpcId]. However, in distributed scenarios (Remote Development), this
* function attempts to deserialize a Color from RPC data.
*
* @return The [Color] if available, or [JBColor.BLACK] if deserialization fails
*/
@ApiStatus.Experimental
fun ColorId.color(): Color {

View File

@@ -14,7 +14,22 @@ import javax.swing.Icon
private val LOG = fileLogger()
/**
* Converts an [Icon] instance into a [IconId] which can be used in RPC calls and stored in Rhizome.
* Converts an [Icon] instance into an [IconId] which can be used in RPC calls and stored in Rhizome.
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this essentially stores a reference to the original icon object.
* In Remote Development scenarios, the icon is serialized for transmission to the frontend.
*
* Important limitations:
* - **Might not work for custom icon classes** - serialization may fail for custom Icon implementations
* - **Recommended approach:** Use default icon classes provided by the platform API
* instead of custom implementations for better compatibility
* - Custom icons may not serialize/deserialize properly across RPC boundaries
*
* @return An [IconId] that can be used in RPC calls
* @throws Exception if the icon cannot be serialized (use [rpcIdOrNull] for safer handling)
*/
@ApiStatus.Experimental
fun Icon.rpcId(): IconId {
@@ -24,6 +39,15 @@ fun Icon.rpcId(): IconId {
return IconId(serializedIcon, icon)
}
/**
* Converts an [Icon] instance into an [IconId] which can be used in RPC calls and stored in Rhizome.
*
* **WARNING: This API is experimental and should be used with care.**
*
* This is a safer version of [rpcId] that returns null instead of throwing an exception when serialization fails.
*
* @return An [IconId] that can be used in RPC calls, or null if serialization fails
*/
@ApiStatus.Experimental
fun Icon.rpcIdOrNull(): IconId? {
val icon = this
@@ -40,6 +64,19 @@ fun Icon.rpcIdOrNull(): IconId? {
/**
* Retrieves the [Icon] associated with the given [IconId].
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this method essentially does nothing - it just reuses the original
* icon object that was passed to [rpcId]. However, in distributed scenarios (Remote Development), this
* function attempts to deserialize an Icon from RPC data.
*
* Important limitations:
* - **Might not work for custom icon classes** - deserialization may fail for custom Icon implementations
* - **Recommended approach:** Use default icon classes provided by the platform API for better compatibility and reliability
* - Falls back to [AllIcons.Empty] if deserialization fails
*
* @return The [Icon] if available, or [AllIcons.Empty] if deserialization fails
*/
@ApiStatus.Experimental
fun IconId.icon(): Icon {

View File

@@ -13,7 +13,21 @@ import org.jetbrains.annotations.ApiStatus
private val LOG = fileLogger()
/**
* Converts an [VirtualFile] instance into a [VirtualFileId] which can be used in RPC calls and stored in Rhizome.
* Converts a [VirtualFile] instance into a [VirtualFileId] which can be used in RPC calls and stored in Rhizome.
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this essentially stores a reference to the original VirtualFile object.
* In Remote Development scenarios, the VirtualFile is serialized for transmission to the frontend.
*
* Important limitations:
* - **Won't work for files created manually on the frontend** - only files that exist in the backend
* IDE instance can be properly serialized and retrieved
* - VirtualFile references may become stale or invalid across RPC boundaries
* - File system state may change between serialization and deserialization
* - Some VirtualFile implementations may not serialize properly
*
* @return A [VirtualFileId] that can be used in RPC calls
*/
@ApiStatus.Experimental
fun VirtualFile.rpcId(): VirtualFileId {
@@ -24,6 +38,23 @@ fun VirtualFile.rpcId(): VirtualFileId {
/**
* Retrieves the [VirtualFile] associated with the given [VirtualFileId].
*
* **WARNING: This API is experimental and should be used with care.**
*
* In the monolith version of the IDE, this method essentially does nothing - it just reuses the original
* VirtualFile object that was passed to [rpcId]. However, in distributed scenarios (Remote Development), this
* function attempts to deserialize a VirtualFile from RPC data.
*
* Important limitations:
* - **Won't work for files created manually on the frontend** - only files that originated from
* the backend IDE instance can be properly retrieved
* - VirtualFile references may become stale or invalid after RPC transmission
* - File system state may have changed since serialization
* - The file may have been deleted, moved, or modified
* - Some VirtualFile implementations may not deserialize properly
* - May return null if deserialization fails or the file is no longer available
*
* @return The [VirtualFile] if available, or null if deserialization fails or the file cannot be found
*/
@ApiStatus.Experimental
fun VirtualFileId.virtualFile(): VirtualFile? {

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// 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.openapi.editor.impl
import com.intellij.openapi.editor.Editor
@@ -53,10 +53,19 @@ val KERNEL_EDITOR_ID_KEY = Key.create<EditorId>("EditorImpl.KERNEL_EDITOR_ID")
/**
* Provides [EditorId] for the given [Editor].
* This [EditorId] can be used for RPC calls between frontend and backend
* This [EditorId] can be used for RPC calls between frontend and backend.
*
* **WARNING: This API is experimental and should be used with care.**
*
* This function retrieves the unique identifier assigned to an Editor instance, returning null if not found.
* Important considerations:
* - Returns null for editors that have not been properly initialized with an EditorId
* - In Remote Development scenarios, ensures editor identity is maintained across frontend/backend boundaries
* - Safe to use for RPC transmission as EditorId is serializable
* - Safer alternative to [editorId] that doesn't throw exceptions
*
* @return The [EditorId] instance associated with the provided [Editor],
* or null if [Editor]'s implementation didn't assign id to it.
* or null if [Editor]'s implementation didn't assign id to it
*/
@ApiStatus.Experimental
fun Editor.editorIdOrNull(): EditorId? {
@@ -65,7 +74,15 @@ fun Editor.editorIdOrNull(): EditorId? {
/**
* Provides [EditorId] for the given [Editor].
* This [EditorId] can be used for RPC calls between frontend and backend
* This [EditorId] can be used for RPC calls between frontend and backend.
*
* **WARNING: This API is experimental and should be used with care.**
*
* This function retrieves the unique identifier assigned to an Editor instance. Important considerations:
* - Only works for editors that have been properly initialized with an EditorId
* - In Remote Development scenarios, ensures editor identity is maintained across frontend/backend boundaries
* - Safe to use for RPC transmission as EditorId is serializable
* - Throws an exception if the editor doesn't have an assigned ID
*
* @return The [EditorId] instance associated with the provided [Editor]
* @throws IllegalStateException if [Editor]'s implementation didn't assign [EditorId] to it
@@ -78,8 +95,16 @@ fun Editor.editorId(): EditorId {
/**
* Provides [Editor] for the given [EditorId].
*
* **WARNING: This API is experimental and should be used with care.**
*
* This function attempts to locate an Editor instance by its unique identifier. Important considerations:
* - **Won't work for editors created on the frontend** - only editors that exist on the backend
* can be found using this method
* - Only finds editors that are currently open and have been assigned the corresponding EditorId
* - May return null if the editor was closed or disposed after the EditorId was obtained
*
* @return The [Editor] instance associated with the provided [EditorId],
* or null if there is no editor with the given [EditorId].
* or null if there is no editor with the given [EditorId]
*/
@ApiStatus.Experimental
fun EditorId.findEditorOrNull(): Editor? {
@@ -89,9 +114,17 @@ fun EditorId.findEditorOrNull(): Editor? {
/**
* Provides [Editor] for the given [EditorId].
*
* @return The [Editor] instance associated with the provided [EditorId],
* or null if there is no editor with the given [EditorId].
* @throws IllegalStateException if there is no editor with the given [EditorId].
* **WARNING: This API is experimental and should be used with care.**
*
* This function attempts to locate an Editor instance by its unique identifier and throws an exception if not found.
* Important considerations:
* - **Won't work for editors created on the frontend** - only editors that exist on the backend
* can be found using this method
* - Only finds editors that are currently open and have been assigned the corresponding EditorId
* - Throws an exception if the editor was closed or disposed after the EditorId was obtained
*
* @return The [Editor] instance associated with the provided [EditorId]
* @throws IllegalStateException if there is no editor with the given [EditorId]
*/
@ApiStatus.Experimental
fun EditorId.findEditor(): Editor {

View File

@@ -91,10 +91,19 @@ fun setNewProjectId(project: Project, newProjectId: ProjectId) {
/**
* Provides the [ProjectId] for the given [Project].
* This [ProjectId] can be used for RPC calls between frontend and backend
* This [ProjectId] can be used for RPC calls between frontend and backend.
*
* **WARNING: This API is experimental and should be used with care.**
*
* This function retrieves the unique identifier assigned to a Project instance, returning null if not found.
* Important considerations:
* - Returns null for projects that have not been properly registered with a ProjectId
* - In Remote Development scenarios, ensures project identity is maintained across frontend/backend boundaries
* - Safe to use for RPC transmission as ProjectId is serializable
* - Safer alternative to [projectId] that doesn't throw exceptions
*
* @return The [ProjectId] instance associated with the provided [Project],
* or null if [Project]'s implementation didn't assign id to it.
* or null if [Project]'s implementation didn't assign id to it
*/
@ApiStatus.Experimental
fun Project.projectIdOrNull(): ProjectId? {
@@ -103,10 +112,17 @@ fun Project.projectIdOrNull(): ProjectId? {
/**
* Provides the [ProjectId] for the given [Project].
* This [ProjectId] can be used for RPC calls between frontend and backend
* 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.
* **WARNING: This API is experimental and should be used with care.**
*
* This function retrieves the unique identifier assigned to a Project instance. Important considerations:
* - Only works for projects that have been properly registered with a ProjectId
* - In Remote Development scenarios, ensures project identity is maintained across frontend/backend boundaries
* - Safe to use for RPC transmission as ProjectId is serializable
*
* @return The [ProjectId] instance associated with the provided [Project]
* @throws IllegalStateException if [Project]'s implementation didn't assign id to it
*/
@ApiStatus.Experimental
fun Project.projectId(): ProjectId {
@@ -125,8 +141,15 @@ fun Project.projectIdOrNullWithLogError(log: Logger): ProjectId? {
/**
* Provides [Project] for the given [ProjectId].
*
* **WARNING: This API is experimental and should be used with care.**
*
* This function attempts to locate a Project instance by its unique identifier. Important considerations:
* - Only finds projects that are currently open and registered in the IDE
* - In Remote Development scenarios, only searches for projects on the current (backend) side
* - May return null if the project was closed or unregistered after the ProjectId was obtained
*
* @return The [Project] instance associated with the provided [ProjectId],
* or null if there is no project with the given [ProjectId].
* or null if there is no project with the given [ProjectId]
*/
@ApiStatus.Experimental
fun ProjectId.findProjectOrNull(): Project? {
@@ -151,8 +174,15 @@ fun ProjectId.findProjectOrNullWithLogError(log: Logger): Project? {
/**
* 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].
* **WARNING: This API is experimental and should be used with care.**
*
* This function attempts to locate a Project instance by its unique identifier and throws an exception if not found.
* Important considerations:
* - Only finds projects that are currently open and registered in the IDE
* - Throws an exception if the project was closed or unregistered after the ProjectId was obtained
*
* @return The [Project] instance associated with the provided [ProjectId]
* @throws IllegalStateException if there is no project with the given [ProjectId]
*/
@ApiStatus.Experimental
fun ProjectId.findProject(): Project {