diff --git a/platform/object-serializer/src/xml/KotlinxSerializationBinding.kt b/platform/object-serializer/src/xml/KotlinxSerializationBinding.kt index 0ae0856e43fce..d810f5e49e182 100644 --- a/platform/object-serializer/src/xml/KotlinxSerializationBinding.kt +++ b/platform/object-serializer/src/xml/KotlinxSerializationBinding.kt @@ -9,6 +9,8 @@ import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json import org.jdom.CDATA import org.jdom.Element +import java.lang.invoke.MethodHandles +import java.lang.invoke.MethodType @OptIn(ExperimentalSerializationApi::class) private val json = Json { @@ -17,7 +19,22 @@ private val json = Json { ignoreUnknownKeys = true } -internal class KotlinxSerializationBinding(private val serializer: KSerializer) : NotNullDeserializeBinding() { +private val lookup = MethodHandles.lookup() +private val kotlinMethodType = MethodType.methodType(KSerializer::class.java) + +internal class KotlinxSerializationBinding(aClass: Class<*>) : NotNullDeserializeBinding() { + private val serializer: KSerializer + + init { + // don't use official `::kotlin.get().serializer()` API — avoid kotlin refection wrapper creation + // findStaticGetter cannot be used because type of Companion not used + val field = aClass.getDeclaredField("Companion") + field.isAccessible = true + val companion = lookup.unreflectGetter(field).invoke() + @Suppress("UNCHECKED_CAST") + serializer = lookup.findVirtual(companion.javaClass, "serializer", kotlinMethodType).invoke(companion) as KSerializer + } + override fun serialize(o: Any, context: Any?, filter: SerializationFilter?): Any { val element = Element("state") element.addContent(CDATA(json.encodeToString(serializer, o))) diff --git a/platform/object-serializer/src/xml/xmlSerializer.kt b/platform/object-serializer/src/xml/xmlSerializer.kt index 6852c8edcfc1f..fa7e99641db7b 100644 --- a/platform/object-serializer/src/xml/xmlSerializer.kt +++ b/platform/object-serializer/src/xml/xmlSerializer.kt @@ -10,9 +10,7 @@ import com.intellij.serialization.xml.KotlinAwareBeanBinding import com.intellij.serialization.xml.KotlinxSerializationBinding import com.intellij.util.io.URLUtil import com.intellij.util.xmlb.* -import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.Serializable -import kotlinx.serialization.serializer import org.jdom.Element import org.jdom.JDOMException import org.jetbrains.annotations.TestOnly @@ -172,14 +170,12 @@ private abstract class OldBindingProducer { } private class MyXmlSerializer : XmlSerializerImpl.XmlSerializerBase() { - @OptIn(InternalSerializationApi::class) val bindingProducer = object : OldBindingProducer() { override fun createRootBinding(aClass: Class<*>, type: Type, cacheKey: Type, map: MutableMap): Binding { var binding = createClassBinding(aClass, null, type) if (binding == null) { if (aClass.isAnnotationPresent(Serializable::class.java)) { - @Suppress("UNCHECKED_CAST") - binding = KotlinxSerializationBinding((aClass as Class)::kotlin.get().serializer()) + binding = KotlinxSerializationBinding(aClass) } else { binding = KotlinAwareBeanBinding(aClass)