mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-rd] IJPL-176967: Rewrite XValueDescriptor, so it may be extended by plugins
GitOrigin-RevId: 9fd606e89cbf0680357a12c5159cc99ec3463914
This commit is contained in:
committed by
intellij-monorepo-bot
parent
abf7dd20c2
commit
50996fd44e
+3
-4
@@ -2,11 +2,10 @@
|
||||
package com.intellij.java.debugger.impl.frontend.actions
|
||||
|
||||
import com.intellij.java.debugger.impl.shared.actions.ViewTextActionBase
|
||||
import com.intellij.java.debugger.impl.shared.engine.JAVA_VALUE_KIND
|
||||
import com.intellij.java.debugger.impl.shared.engine.JavaValueDescriptor
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification
|
||||
import com.intellij.platform.debugger.impl.frontend.evaluate.quick.FrontendXValue
|
||||
import com.intellij.xdebugger.frame.XValueType
|
||||
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
|
||||
@@ -27,9 +26,9 @@ private class FrontendViewTextAction : ViewTextActionBase(), ActionRemoteBehavio
|
||||
override fun getStringNode(e: AnActionEvent): XValueNodeImpl? {
|
||||
val node = XDebuggerTreeActionBase.getSelectedNodes(e.dataContext).singleOrNull() ?: return null
|
||||
val xValue = node.valueContainer as? FrontendXValue ?: return null
|
||||
val descriptor = xValue.descriptor ?: return null
|
||||
val descriptor = (xValue.descriptor as? JavaValueDescriptor) ?: return null
|
||||
|
||||
if (xValue.modifier != null && descriptor.kind == JAVA_VALUE_KIND && descriptor.type is XValueType.StringType) {
|
||||
if (xValue.modifier != null && descriptor.isString) {
|
||||
return node
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.debugger.ui.impl.watch.*;
|
||||
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.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -58,7 +59,7 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.intellij.java.debugger.impl.shared.engine.XValueTypeKt.JAVA_VALUE_KIND;
|
||||
import static com.intellij.java.debugger.impl.shared.engine.JavaValueDescriptorKt.JAVA_VALUE_KIND;
|
||||
|
||||
public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XValueTextProvider,
|
||||
PinToTopParentValue, PinToTopMemberValue {
|
||||
@@ -513,14 +514,9 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
@Override
|
||||
public @Nullable CompletableFuture<XValueDescriptor> getXValueDescriptorAsync() {
|
||||
return myValueDescriptor.getInitFuture().thenApply(ignored -> {
|
||||
XValueType type;
|
||||
if (myValueDescriptor.isString()) {
|
||||
type = XValueType.StringType.INSTANCE;
|
||||
}
|
||||
else {
|
||||
type = XValueType.Unknown.INSTANCE;
|
||||
}
|
||||
return new XValueDescriptor(JAVA_VALUE_KIND, type);
|
||||
return new JavaValueDescriptor(
|
||||
myValueDescriptor.isString()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,5 +4,7 @@
|
||||
<applicationSettings service="com.intellij.debugger.settings.DebuggerSettings"/>
|
||||
<xdebugger.hotSwapUiExtension implementation="com.intellij.debugger.impl.hotswap.JvmHotSwapUiExtension"/>
|
||||
<rdct.remoteSettingProvider implementation="com.intellij.debugger.settings.JavaDebuggerSettingsProvider"/>
|
||||
<xdebugger.xValueCustomDescriptorSerializerProvider
|
||||
implementation="com.intellij.java.debugger.impl.shared.engine.JavaValueDescriptorSerializerProvider"/>
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
// 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.engine
|
||||
|
||||
import com.intellij.xdebugger.frame.XValueCustomDescriptorSerializerProvider
|
||||
import com.intellij.xdebugger.frame.XValueDescriptor
|
||||
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"
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
class JavaValueDescriptor(
|
||||
val isString: Boolean,
|
||||
) : XValueDescriptor {
|
||||
override val kind: String = JAVA_VALUE_KIND
|
||||
}
|
||||
|
||||
private class JavaValueDescriptorSerializerProvider : XValueCustomDescriptorSerializerProvider {
|
||||
override fun registerSerializer(builder: PolymorphicModuleBuilder<XValueDescriptor>) {
|
||||
builder.subclass(JavaValueDescriptor::class)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// 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.engine
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
const val JAVA_VALUE_KIND: String = "JavaValue"
|
||||
@@ -1,16 +1,40 @@
|
||||
// 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
|
||||
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 org.jetbrains.annotations.ApiStatus
|
||||
|
||||
/**
|
||||
* Provides additional information about XValue which can be used by UI and actions.
|
||||
* Provides additional information about XValue which can be used by UI and actions on the Frontend.
|
||||
*
|
||||
* Internal plugins may extend this interface providing custom implementation, but they should be serializable.
|
||||
* Also, it is required to provide serializer for the implementation using
|
||||
* [com.intellij.xdebugger.frame.XValueCustomDescriptorSerializerProvider].
|
||||
* Otherwise, the default implementation will be used during a serialization/deserialization process.
|
||||
*
|
||||
*
|
||||
* @see createXValueDescriptor
|
||||
* @see XValueCustomDescriptorSerializerProvider
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Serializable
|
||||
data class XValueDescriptor(
|
||||
@Serializable(with = XValueDescriptorSerializer::class)
|
||||
interface XValueDescriptor {
|
||||
/**
|
||||
* [kind] is used to differentiate various implementations of XValue by their type instead of using `instanceOf` on [XValue].
|
||||
* Examples of possible kinds: "JavaValue", "PhpValue", "RubyValue"
|
||||
@@ -19,25 +43,75 @@ data class XValueDescriptor(
|
||||
* which makes `instanceOf` comparisons of XValue impossible, this property provides a way to
|
||||
* differentiate between various types of XValue on the frontend.
|
||||
*/
|
||||
val kind: String,
|
||||
val kind: String
|
||||
}
|
||||
|
||||
/**
|
||||
* [XValue] type (see instances of the [XValueType]).
|
||||
* Typically, the client may use the type to check the availability of some action or show XValue differently in UI.
|
||||
*/
|
||||
val type: XValueType,
|
||||
)
|
||||
// TODO: should be called just XValueDescriptor, but it won't be available in Java then
|
||||
@ApiStatus.Internal
|
||||
fun createXValueDescriptor(kind: String): XValueDescriptor {
|
||||
return XValueDescriptorImpl(kind)
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
interface XValueCustomDescriptorSerializerProvider {
|
||||
companion object {
|
||||
internal val EP_NAME = ExtensionPointName<XValueCustomDescriptorSerializerProvider>("com.intellij.xdebugger.xValueCustomDescriptorSerializerProvider")
|
||||
}
|
||||
|
||||
fun registerSerializer(builder: PolymorphicModuleBuilder<XValueDescriptor>)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed interface XValueType {
|
||||
// TODO: add other types of XValue
|
||||
@Serializable
|
||||
data object StringType : XValueType
|
||||
private data class XValueDescriptorImpl(override val kind: String) : XValueDescriptor
|
||||
|
||||
@Serializable
|
||||
data class Other(val rawType: String) : XValueType
|
||||
|
||||
@Serializable
|
||||
data object Unknown : XValueType
|
||||
private object XValueDescriptorSerializer : KSerializer<XValueDescriptor> {
|
||||
override val descriptor: SerialDescriptor = JsonElement.serializer().descriptor
|
||||
|
||||
override fun serialize(encoder: Encoder, value: XValueDescriptor) {
|
||||
val json = service<XValueDescriptorJsonProvider>().json
|
||||
val element = json.encodeToJsonElement(value)
|
||||
encoder.encodeSerializableValue(JsonElement.serializer(), element)
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): XValueDescriptor {
|
||||
val json = service<XValueDescriptorJsonProvider>().json
|
||||
val element = decoder.decodeSerializableValue(JsonElement.serializer())
|
||||
return json.decodeFromJsonElement(element)
|
||||
}
|
||||
}
|
||||
|
||||
@Service
|
||||
private class XValueDescriptorJsonProvider(cs: CoroutineScope) {
|
||||
@Volatile
|
||||
var json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
encodeDefaults = true
|
||||
}
|
||||
|
||||
init {
|
||||
updateJson()
|
||||
XValueCustomDescriptorSerializerProvider.EP_NAME.addExtensionPointListener(cs, object : ExtensionPointAdapter<XValueCustomDescriptorSerializerProvider>() {
|
||||
override fun extensionListChanged() {
|
||||
updateJson()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,9 @@
|
||||
<extensionPoint name="xdebugger.controlExceptionBreakpointSupport" interface="com.intellij.xdebugger.codeinsight.ControlExceptionBreakpointSupport" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="xdebugger.hotSwapUiExtension" interface="com.intellij.xdebugger.impl.hotswap.HotSwapUiExtension" dynamic="true"/>
|
||||
|
||||
<extensionPoint name="xdebugger.xValueCustomDescriptorSerializerProvider"
|
||||
interface="com.intellij.xdebugger.frame.XValueCustomDescriptorSerializerProvider" dynamic="true"/>
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
|
||||
Reference in New Issue
Block a user