diff --git a/java/debugger/backend/intellij.java.debugger.impl.backend.iml b/java/debugger/backend/intellij.java.debugger.impl.backend.iml
index 32b60207c61f..3dc76ebe58e9 100644
--- a/java/debugger/backend/intellij.java.debugger.impl.backend.iml
+++ b/java/debugger/backend/intellij.java.debugger.impl.backend.iml
@@ -43,5 +43,6 @@
+
\ No newline at end of file
diff --git a/java/debugger/backend/resources/intellij.java.debugger.impl.backend.xml b/java/debugger/backend/resources/intellij.java.debugger.impl.backend.xml
index 984008f6a315..0ecfb4bbfe37 100644
--- a/java/debugger/backend/resources/intellij.java.debugger.impl.backend.xml
+++ b/java/debugger/backend/resources/intellij.java.debugger.impl.backend.xml
@@ -2,4 +2,8 @@
+
+
+
\ No newline at end of file
diff --git a/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerLuxActionsApi.kt b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerLuxActionsApi.kt
new file mode 100644
index 000000000000..713b4ce042b5
--- /dev/null
+++ b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerLuxActionsApi.kt
@@ -0,0 +1,27 @@
+// 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.java.debugger.impl.backend
+
+import com.intellij.debugger.memory.action.DebuggerTreeAction
+import com.intellij.debugger.memory.filtering.ClassInstancesProvider
+import com.intellij.debugger.memory.ui.InstancesWindow
+import com.intellij.java.debugger.impl.shared.rpc.JavaDebuggerLuxActionsApi
+import com.intellij.openapi.application.EDT
+import com.intellij.xdebugger.impl.rhizome.XValueEntity
+import com.intellij.xdebugger.impl.rpc.XValueId
+import com.jetbrains.rhizomedb.entity
+import com.sun.jdi.ReferenceType
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+
+internal class BackendJavaDebuggerLuxActionsApi : JavaDebuggerLuxActionsApi {
+ override suspend fun showInstancesDialog(xValueId: XValueId) {
+ val xValueEntity = entity(XValueEntity.XValueId, xValueId) ?: return
+ val xValue = xValueEntity.xValue
+ val session = xValueEntity.sessionEntity.session
+ val objectRef = DebuggerTreeAction.getObjectReference(xValue) ?: return
+ val referenceType: ReferenceType = objectRef.referenceType()
+ withContext(Dispatchers.EDT) {
+ InstancesWindow(session, ClassInstancesProvider(referenceType), referenceType).show()
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerRemoteApiProvider.kt b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerRemoteApiProvider.kt
new file mode 100644
index 000000000000..e32dab09f0fc
--- /dev/null
+++ b/java/debugger/backend/src/com/intellij/java/debugger/impl/backend/BackendJavaDebuggerRemoteApiProvider.kt
@@ -0,0 +1,14 @@
+// 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.java.debugger.impl.backend
+
+import com.intellij.java.debugger.impl.shared.rpc.JavaDebuggerLuxActionsApi
+import com.intellij.platform.rpc.backend.RemoteApiProvider
+import fleet.rpc.remoteApiDescriptor
+
+private class BackendJavaDebuggerRemoteApiProvider : RemoteApiProvider {
+ override fun RemoteApiProvider.Sink.remoteApis() {
+ remoteApi(remoteApiDescriptor()) {
+ BackendJavaDebuggerLuxActionsApi()
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/debugger/frontend/resources/intellij.java.debugger.impl.frontend.xml b/java/debugger/frontend/resources/intellij.java.debugger.impl.frontend.xml
index 4f113cca30f8..2632d8ada77e 100644
--- a/java/debugger/frontend/resources/intellij.java.debugger.impl.frontend.xml
+++ b/java/debugger/frontend/resources/intellij.java.debugger.impl.frontend.xml
@@ -7,5 +7,9 @@
+
+
+
\ No newline at end of file
diff --git a/java/debugger/frontend/resources/messages/JavaDebuggerImplFrontendBundle.properties b/java/debugger/frontend/resources/messages/JavaDebuggerImplFrontendBundle.properties
index a100a15ff6c0..6fbcb9bbe3a7 100644
--- a/java/debugger/frontend/resources/messages/JavaDebuggerImplFrontendBundle.properties
+++ b/java/debugger/frontend/resources/messages/JavaDebuggerImplFrontendBundle.properties
@@ -1,2 +1,4 @@
action.Debugger.ViewText.Frontend.text=View Text
-action.Debugger.ViewText.Frontend.description=View text value of selected node in a separate pane
\ No newline at end of file
+action.Debugger.ViewText.Frontend.description=View text value of selected node in a separate pane
+action.MemoryView.ShowInstancesFromDebuggerTree.Frontend.text=Show Instances
+action.show.objects.text=Show {0} Objects\u2026
\ No newline at end of file
diff --git a/java/debugger/frontend/src/com/intellij/java/debugger/impl/frontend/actions/FrontendShowInstancesByClassAction.kt b/java/debugger/frontend/src/com/intellij/java/debugger/impl/frontend/actions/FrontendShowInstancesByClassAction.kt
new file mode 100644
index 000000000000..398600784c04
--- /dev/null
+++ b/java/debugger/frontend/src/com/intellij/java/debugger/impl/frontend/actions/FrontendShowInstancesByClassAction.kt
@@ -0,0 +1,57 @@
+// 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.java.debugger.impl.frontend.actions
+
+import com.intellij.openapi.actionSystem.ActionUpdateThread
+import com.intellij.openapi.actionSystem.AnActionEvent
+import com.intellij.openapi.util.text.StringUtil
+import com.intellij.platform.debugger.impl.frontend.evaluate.quick.FrontendXValue
+import com.intellij.xdebugger.impl.actions.areFrontendDebuggerActionsEnabled
+import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl
+import com.intellij.java.debugger.impl.frontend.messages.JavaDebuggerImplFrontendBundle
+import com.intellij.java.debugger.impl.shared.engine.JavaValueDescriptor
+import com.intellij.java.debugger.impl.shared.rpc.JavaDebuggerLuxActionsApi
+import com.intellij.openapi.components.Service
+import com.intellij.openapi.components.service
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/**
+ * Frontend version of [com.intellij.debugger.memory.action.ShowInstancesByClassAction]
+ */
+private class FrontendShowInstancesByClassAction : XDebuggerTreeActionBase() {
+ override fun getActionUpdateThread(): ActionUpdateThread {
+ return ActionUpdateThread.BGT
+ }
+
+ override fun update(e: AnActionEvent) {
+ if (!areFrontendDebuggerActionsEnabled()) {
+ e.presentation.isEnabledAndVisible = false
+ return
+ }
+
+ super.update(e)
+ }
+
+ override fun isEnabled(node: XValueNodeImpl, e: AnActionEvent): Boolean {
+ val xValue = node.valueContainer as? FrontendXValue ?: return false
+ val descriptor = (xValue.descriptor as? JavaValueDescriptor) ?: return false
+ val objectReferenceInfo = descriptor.objectReferenceInfo ?: return false
+
+ val visibleTypeName = StringUtil.getShortName(objectReferenceInfo.typeName)
+ e.presentation.setText(JavaDebuggerImplFrontendBundle.message("action.show.objects.text", visibleTypeName))
+
+ return true
+ }
+
+
+ override fun perform(node: XValueNodeImpl, nodeName: String, e: AnActionEvent) {
+ val xValue = node.valueContainer as? FrontendXValue ?: return
+ service().cs.launch {
+ JavaDebuggerLuxActionsApi.getInstance().showInstancesDialog(xValue.xValueDto.id)
+ }
+ }
+}
+
+@Service(Service.Level.APP)
+private class FrontendShowInstancesByClassActionCoroutineScope(val cs: CoroutineScope)
\ No newline at end of file
diff --git a/java/debugger/frontend/src/com/intellij/java/debugger/impl/frontend/messages/JavaDebuggerImplFrontendBundle.java b/java/debugger/frontend/src/com/intellij/java/debugger/impl/frontend/messages/JavaDebuggerImplFrontendBundle.java
index f5448452708b..4147d4a8a75c 100644
--- a/java/debugger/frontend/src/com/intellij/java/debugger/impl/frontend/messages/JavaDebuggerImplFrontendBundle.java
+++ b/java/debugger/frontend/src/com/intellij/java/debugger/impl/frontend/messages/JavaDebuggerImplFrontendBundle.java
@@ -6,7 +6,8 @@ import org.jetbrains.annotations.*;
import java.util.function.Supplier;
-final class JavaDebuggerImplFrontendBundle {
+@ApiStatus.Internal
+public final class JavaDebuggerImplFrontendBundle {
private static final @NonNls String BUNDLE_FQN = "messages.JavaDebuggerImplFrontendBundle";
private static final DynamicBundle BUNDLE = new DynamicBundle(JavaDebuggerImplFrontendBundle.class, BUNDLE_FQN);
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
index 45c7c6cc0385..83aedc328209 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
@@ -23,6 +23,7 @@ import com.intellij.debugger.ui.tree.*;
import com.intellij.debugger.ui.tree.render.*;
import com.intellij.debugger.ui.tree.render.Renderer;
import com.intellij.java.debugger.impl.shared.engine.JavaValueDescriptor;
+import com.intellij.java.debugger.impl.shared.engine.JavaValueObjectReferenceInfo;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.diagnostic.Logger;
@@ -59,8 +60,6 @@ import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
-import static com.intellij.java.debugger.impl.shared.engine.JavaValueDescriptorKt.JAVA_VALUE_KIND;
-
public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XValueTextProvider,
PinToTopParentValue, PinToTopMemberValue {
private static final Logger LOG = Logger.getInstance(JavaValue.class);
@@ -514,8 +513,14 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
@Override
public @Nullable CompletableFuture getXValueDescriptorAsync() {
return myValueDescriptor.getInitFuture().thenApply(ignored -> {
+ Value value = myValueDescriptor.getValue();
+ JavaValueObjectReferenceInfo objectReferenceInfo = null;
+ if (value instanceof ObjectReference ref) {
+ objectReferenceInfo = new JavaValueObjectReferenceInfo(ref.referenceType().name(), ref.virtualMachine().canGetInstanceInfo());
+ }
return new JavaValueDescriptor(
- myValueDescriptor.isString()
+ myValueDescriptor.isString(),
+ objectReferenceInfo
);
});
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/action/DebuggerTreeAction.java b/java/debugger/impl/src/com/intellij/debugger/memory/action/DebuggerTreeAction.java
index 4e03d3089c05..fe6a4b9755bc 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/action/DebuggerTreeAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/action/DebuggerTreeAction.java
@@ -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.debugger.memory.action;
import com.intellij.debugger.ui.impl.watch.NodeDescriptorProvider;
@@ -9,12 +9,18 @@ import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
import com.sun.jdi.ObjectReference;
import com.sun.jdi.Value;
+import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class DebuggerTreeAction extends XDebuggerTreeActionBase {
public static @Nullable ObjectReference getObjectReference(@NotNull XValueNodeImpl node) {
XValue valueContainer = node.getValueContainer();
+ return getObjectReference(valueContainer);
+ }
+
+ @ApiStatus.Internal
+ public static @Nullable ObjectReference getObjectReference(@NotNull XValue valueContainer) {
if (valueContainer instanceof NodeDescriptorProvider) {
NodeDescriptor descriptor = ((NodeDescriptorProvider)valueContainer).getDescriptor();
if (descriptor instanceof ValueDescriptorImpl) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/action/ShowInstancesByClassAction.java b/java/debugger/impl/src/com/intellij/debugger/memory/action/ShowInstancesByClassAction.java
index 4c5e70072a99..4f0eb4a58f0f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/action/ShowInstancesByClassAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/action/ShowInstancesByClassAction.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// 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.debugger.memory.action;
import com.intellij.debugger.JavaDebuggerBundle;
@@ -15,6 +15,9 @@ import com.sun.jdi.ObjectReference;
import com.sun.jdi.ReferenceType;
import org.jetbrains.annotations.NotNull;
+/**
+ * See the frontend version of the action: com.intellij.java.debugger.impl.frontend.actions.FrontendShowInstancesByClassAction
+ */
public class ShowInstancesByClassAction extends DebuggerTreeAction {
@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
diff --git a/java/debugger/impl/src/com/intellij/debugger/memory/filtering/providers.kt b/java/debugger/impl/src/com/intellij/debugger/memory/filtering/providers.kt
index 43371f7f0e2e..840b93f02db8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/memory/filtering/providers.kt
+++ b/java/debugger/impl/src/com/intellij/debugger/memory/filtering/providers.kt
@@ -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.debugger.memory.filtering
import com.intellij.debugger.memory.ui.JavaReferenceInfo
@@ -6,8 +6,10 @@ import com.intellij.xdebugger.memory.ui.ReferenceInfo
import com.intellij.xdebugger.memory.utils.InstancesProvider
import com.sun.jdi.ObjectReference
import com.sun.jdi.ReferenceType
+import org.jetbrains.annotations.ApiStatus
-internal interface InstanceProviderEx : InstancesProvider {
+@ApiStatus.Internal
+interface InstanceProviderEx : InstancesProvider {
fun returnAllInstancesOfAClass(): Boolean
/**
@@ -23,9 +25,10 @@ internal class FixedListProvider(private val references: List)
override fun estimateInstancesCount(): Int = references.size
}
-internal class ClassInstancesProvider(private val referenceType: ReferenceType) : InstanceProviderEx {
+@ApiStatus.Internal
+class ClassInstancesProvider(private val referenceType: ReferenceType) : InstanceProviderEx {
override fun getInstances(limit: Int): MutableList = referenceType.instances(limit.toLong()).mapToInfoList()
- override fun returnAllInstancesOfAClass() = true
+ override fun returnAllInstancesOfAClass(): Boolean = true
override fun estimateInstancesCount(): Int = referenceType.virtualMachine().instanceCounts(listOf(referenceType))[0]
.let { if (it < 0 || it > Int.MAX_VALUE) Int.MAX_VALUE else it.toInt() }
}
diff --git a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/engine/JavaValueDescriptor.kt b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/engine/JavaValueDescriptor.kt
index 25a4ae8cd047..fe0e360a96e8 100644
--- a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/engine/JavaValueDescriptor.kt
+++ b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/engine/JavaValueDescriptor.kt
@@ -3,24 +3,36 @@ package com.intellij.java.debugger.impl.shared.engine
import com.intellij.xdebugger.frame.XValueCustomDescriptorSerializerProvider
import com.intellij.xdebugger.frame.XValueDescriptor
+import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
-import kotlinx.serialization.modules.PolymorphicModuleBuilder
-import kotlinx.serialization.modules.subclass
import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
const val JAVA_VALUE_KIND: String = "JavaValue"
+// TODO: this class can be refactored,
+// for now its fields are just added adhoc for actions
@ApiStatus.Internal
@Serializable
-class JavaValueDescriptor(
+data class JavaValueDescriptor(
val isString: Boolean,
+ val objectReferenceInfo: JavaValueObjectReferenceInfo?,
) : XValueDescriptor {
override val kind: String = JAVA_VALUE_KIND
}
+@ApiStatus.Internal
+@Serializable
+data class JavaValueObjectReferenceInfo(
+ val typeName: String,
+ val canGetInstanceInfo: Boolean,
+)
+
private class JavaValueDescriptorSerializerProvider : XValueCustomDescriptorSerializerProvider {
- override fun registerSerializer(builder: PolymorphicModuleBuilder) {
- builder.subclass(JavaValueDescriptor::class)
+ override fun getSerializer(kind: String): KSerializer? {
+ if (kind == JAVA_VALUE_KIND) {
+ return JavaValueDescriptor.serializer()
+ }
+ return null
}
}
\ No newline at end of file
diff --git a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerLuxActionsApi.kt b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerLuxActionsApi.kt
new file mode 100644
index 000000000000..6d892ab14eac
--- /dev/null
+++ b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/JavaDebuggerLuxActionsApi.kt
@@ -0,0 +1,20 @@
+// 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.java.debugger.impl.shared.rpc
+
+import com.intellij.platform.rpc.RemoteApiProviderService
+import com.intellij.xdebugger.impl.rpc.XValueId
+import fleet.rpc.RemoteApi
+import fleet.rpc.Rpc
+import fleet.rpc.remoteApiDescriptor
+
+@Rpc
+interface JavaDebuggerLuxActionsApi : RemoteApi {
+ suspend fun showInstancesDialog(xValueId: XValueId)
+
+ companion object {
+ @JvmStatic
+ suspend fun getInstance(): JavaDebuggerLuxActionsApi {
+ return RemoteApiProviderService.resolve(remoteApiDescriptor())
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/package-info.java b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/package-info.java
new file mode 100644
index 000000000000..583fa1778563
--- /dev/null
+++ b/java/debugger/shared/src/com/intellij/java/debugger/impl/shared/rpc/package-info.java
@@ -0,0 +1,5 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+@Internal
+package com.intellij.java.debugger.impl.shared.rpc;
+
+import org.jetbrains.annotations.ApiStatus.Internal;
diff --git a/java/plugin/plugin-content.yaml b/java/plugin/plugin-content.yaml
index 1817e0192ed2..276a3719f1c8 100644
--- a/java/plugin/plugin-content.yaml
+++ b/java/plugin/plugin-content.yaml
@@ -76,6 +76,7 @@
- name: intellij.java.performancePlugin
- name: intellij.java.compiler.charts
- name: intellij.java.terminal
+ - name: intellij.java.debugger.impl.backend
- name: lib/javac2.jar
modules:
- name: intellij.java.compiler.antTasks
@@ -128,9 +129,6 @@
- name: lib/maven-resolver-connector-basic.jar
- name: lib/maven-resolver-transport-file.jar
- name: lib/maven-resolver-transport-http.jar
-- name: lib/modules/intellij.java.debugger.impl.backend.jar
- contentModules:
- - name: intellij.java.debugger.impl.backend
- name: lib/modules/intellij.java.debugger.impl.frontend.jar
contentModules:
- name: intellij.java.debugger.impl.frontend
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueDescriptor.kt b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueDescriptor.kt
index c639aa66ad24..c6c91f04bb3d 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueDescriptor.kt
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XValueDescriptor.kt
@@ -1,11 +1,7 @@
// 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.xdebugger.frame
-import com.intellij.openapi.components.Service
-import com.intellij.openapi.components.service
-import com.intellij.openapi.extensions.ExtensionPointAdapter
import com.intellij.openapi.extensions.ExtensionPointName
-import kotlinx.coroutines.CoroutineScope
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.SerialDescriptor
@@ -13,11 +9,8 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.decodeFromJsonElement
-import kotlinx.serialization.json.encodeToJsonElement
-import kotlinx.serialization.modules.PolymorphicModuleBuilder
-import kotlinx.serialization.modules.SerializersModule
-import kotlinx.serialization.modules.polymorphic
+import kotlinx.serialization.json.jsonObject
+import kotlinx.serialization.json.jsonPrimitive
import org.jetbrains.annotations.ApiStatus
/**
@@ -58,60 +51,38 @@ interface XValueCustomDescriptorSerializerProvider {
internal val EP_NAME = ExtensionPointName("com.intellij.xdebugger.xValueCustomDescriptorSerializerProvider")
}
- fun registerSerializer(builder: PolymorphicModuleBuilder)
+ fun getSerializer(kind: String): KSerializer?
}
@Serializable
private data class XValueDescriptorImpl(override val kind: String) : XValueDescriptor
-
private object XValueDescriptorSerializer : KSerializer {
- override val descriptor: SerialDescriptor = JsonElement.serializer().descriptor
-
- override fun serialize(encoder: Encoder, value: XValueDescriptor) {
- val json = service().json
- val element = json.encodeToJsonElement(value)
- encoder.encodeSerializableValue(JsonElement.serializer(), element)
- }
-
- override fun deserialize(decoder: Decoder): XValueDescriptor {
- val json = service().json
- val element = decoder.decodeSerializableValue(JsonElement.serializer())
- return json.decodeFromJsonElement(element)
- }
-}
-
-@Service
-private class XValueDescriptorJsonProvider(cs: CoroutineScope) {
- @Volatile
- var json = Json {
+ private val json = Json {
ignoreUnknownKeys = true
encodeDefaults = true
}
- init {
- updateJson()
- XValueCustomDescriptorSerializerProvider.EP_NAME.addExtensionPointListener(cs, object : ExtensionPointAdapter() {
- override fun extensionListChanged() {
- updateJson()
- }
- })
+ override val descriptor: SerialDescriptor = JsonElement.serializer().descriptor
+
+ override fun serialize(encoder: Encoder, value: XValueDescriptor) {
+ val serializer = getSerializerByKind(value.kind)
+ val element = json.encodeToJsonElement(serializer as KSerializer, value)
+ encoder.encodeSerializableValue(JsonElement.serializer(), element)
}
- private fun updateJson() {
- json = Json {
- ignoreUnknownKeys = true
- encodeDefaults = true
- serializersModule = SerializersModule {
- polymorphic(XValueDescriptor::class) {
- for (provider in XValueCustomDescriptorSerializerProvider.EP_NAME.extensionList) {
- provider.registerSerializer(this)
- }
- defaultDeserializer {
- XValueDescriptorImpl.serializer()
- }
- }
- }
+ override fun deserialize(decoder: Decoder): XValueDescriptor {
+ val element = decoder.decodeSerializableValue(JsonElement.serializer())
+ if (!element.jsonObject.containsKey("kind")) {
+ throw IllegalArgumentException("Missing required 'kind' property")
}
+ val kind = element.jsonObject["kind"]!!.jsonPrimitive.content
+ val serializer = getSerializerByKind(kind)
+ return json.decodeFromJsonElement(serializer, element)
+ }
+
+ private fun getSerializerByKind(kind: String): KSerializer {
+ return XValueCustomDescriptorSerializerProvider.EP_NAME.extensionList.firstNotNullOfOrNull { it.getSerializer(kind) }
+ ?: XValueDescriptorImpl.serializer()
}
}
\ No newline at end of file