Support situation when argument for serializer<T>() function has SerialInfo annotations.
Because SerializationJvmIrIntrinsicSupport does not instantiate annotations yet, this info could be lost. As a workaround, it is possible to call Companion.serializer() functions instead of direct serializer instantiation, as they are plugin-generated and correctly handle annotations. Note that for some cases (enums & interfaces) this WA is not enough, so additional work is needed later. Fixes https://github.com/Kotlin/kotlinx.serialization/issues/2179
This commit is contained in:
committed by
Space Team
parent
363330f904
commit
e0dce31cde
+11
-6
@@ -49,6 +49,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.referenceArraySerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.referenceArraySerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.sealedSerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.sealedSerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SpecialBuiltins
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SpecialBuiltins
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.annotationsWithArguments
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
@@ -381,8 +382,8 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
val descriptor = StringBuilder("(${serializersModuleType.descriptor}${AsmTypes.K_CLASS_TYPE.descriptor}")
|
val descriptor = StringBuilder("(${serializersModuleType.descriptor}${AsmTypes.K_CLASS_TYPE.descriptor}")
|
||||||
// Generic args (if present)
|
// Generic args (if present)
|
||||||
if (argSerializers.isNotEmpty()) {
|
if (argSerializers.isNotEmpty()) {
|
||||||
fillArray(kSerializerType, argSerializers) { _, serializer ->
|
fillArray(kSerializerType, argSerializers) { _, (type, _) ->
|
||||||
instantiate(serializer, null)
|
generateSerializerForType(type, this, intrinsicType)
|
||||||
}
|
}
|
||||||
descriptor.append(kSerializerArrayType.descriptor)
|
descriptor.append(kSerializerArrayType.descriptor)
|
||||||
}
|
}
|
||||||
@@ -485,8 +486,8 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
aconst(null)
|
aconst(null)
|
||||||
}
|
}
|
||||||
signature.append(kSerializerType.descriptor)
|
signature.append(kSerializerType.descriptor)
|
||||||
fillArray(kSerializerType, argSerializers) { _, serializer ->
|
fillArray(kSerializerType, argSerializers) { _, (type, _) ->
|
||||||
instantiate(serializer, null)
|
generateSerializerForType(type, this, intrinsicType)
|
||||||
}
|
}
|
||||||
signature.append(kSerializerArrayType.descriptor)
|
signature.append(kSerializerArrayType.descriptor)
|
||||||
}
|
}
|
||||||
@@ -498,7 +499,8 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
// Reference array serializer still needs serializer for its argument type
|
// Reference array serializer still needs serializer for its argument type
|
||||||
instantiate(argSerializers[0], signature)
|
generateSerializerForType(argSerializers[0].first, this, intrinsicType)
|
||||||
|
signature.append(kSerializerType.descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
sealedSerializerId -> {
|
sealedSerializerId -> {
|
||||||
@@ -550,7 +552,10 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
|||||||
signature.append("Ljava/lang/Object;")
|
signature.append("Ljava/lang/Object;")
|
||||||
}
|
}
|
||||||
// all serializers get arguments with serializers of their generic types
|
// all serializers get arguments with serializers of their generic types
|
||||||
else -> argSerializers.forEach { instantiate(it, signature) }
|
else -> argSerializers.forEach { (type, _) ->
|
||||||
|
generateSerializerForType(type, this, intrinsicType)
|
||||||
|
signature.append(kSerializerType.descriptor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
signature.append(")V")
|
signature.append(")V")
|
||||||
// invoke constructor
|
// invoke constructor
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.json.*
|
||||||
|
import kotlinx.serialization.internal.*
|
||||||
|
import kotlinx.serialization.descriptors.*
|
||||||
|
import kotlinx.serialization.modules.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@JsonClassDiscriminator("sealed")
|
||||||
|
sealed class Sealed
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@JsonClassDiscriminator("abstract")
|
||||||
|
abstract class Abstract
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@JsonClassDiscriminator("object")
|
||||||
|
object Object
|
||||||
|
|
||||||
|
fun test(descriptor: SerialDescriptor, value: String, name: String = descriptor.serialName) {
|
||||||
|
val anno = descriptor.annotations.filterIsInstance<JsonClassDiscriminator>().singleOrNull()
|
||||||
|
requireNotNull(anno) { "Annotation value not found for $name" }
|
||||||
|
assertEquals(anno.discriminator, value, "Annotation value incorrect for $name")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
test(serializer<Sealed>().descriptor, "sealed")
|
||||||
|
test(serializer<Abstract>().descriptor, "abstract")
|
||||||
|
test(serializer<Object>().descriptor, "object")
|
||||||
|
test(serializer<List<Sealed>>().descriptor.getElementDescriptor(0), "sealed", "List<Sealed>")
|
||||||
|
test(serializer<List<Abstract>>().descriptor.getElementDescriptor(0), "abstract", "List<Abstract>")
|
||||||
|
test(serializer<List<Object>>().descriptor.getElementDescriptor(0), "object", "List<Object>")
|
||||||
|
test(serializer<Array<Sealed>>().descriptor.getElementDescriptor(0), "sealed", "Array<Sealed>")
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -127,7 +127,8 @@ public final class IntrinsicsKt : java/lang/Object {
|
|||||||
GETSTATIC (Box, Companion, LBox$Companion;)
|
GETSTATIC (Box, Companion, LBox$Companion;)
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
||||||
DUP
|
DUP
|
||||||
GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;)
|
GETSTATIC (Simple, Companion, LSimple$Companion;)
|
||||||
|
INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
||||||
INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;)
|
INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;)
|
||||||
POP
|
POP
|
||||||
@@ -142,7 +143,8 @@ public final class IntrinsicsKt : java/lang/Object {
|
|||||||
GETSTATIC (Box, Companion, LBox$Companion;)
|
GETSTATIC (Box, Companion, LBox$Companion;)
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
||||||
DUP
|
DUP
|
||||||
GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;)
|
GETSTATIC (Simple, Companion, LSimple$Companion;)
|
||||||
|
INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
||||||
INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;)
|
INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;)
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
||||||
@@ -167,10 +169,9 @@ public final class IntrinsicsKt : java/lang/Object {
|
|||||||
DUP
|
DUP
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
||||||
DUP
|
DUP
|
||||||
NEW (Box$$serializer)
|
GETSTATIC (Box, Companion, LBox$Companion;)
|
||||||
DUP
|
|
||||||
GETSTATIC (kotlinx/serialization/internal/IntSerializer, INSTANCE, Lkotlinx/serialization/internal/IntSerializer;)
|
GETSTATIC (kotlinx/serialization/internal/IntSerializer, INSTANCE, Lkotlinx/serialization/internal/IntSerializer;)
|
||||||
INVOKESPECIAL (Box$$serializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKEVIRTUAL (Box$Companion, serializer, (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;)
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
||||||
LABEL (L21)
|
LABEL (L21)
|
||||||
|
|||||||
+4
-2
@@ -50,7 +50,8 @@ public final class IntrinsicsAdvancedKt : java/lang/Object {
|
|||||||
POP
|
POP
|
||||||
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
NEW (kotlinx/serialization/internal/ArrayListSerializer)
|
||||||
DUP
|
DUP
|
||||||
GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;)
|
GETSTATIC (Simple, Companion, LSimple$Companion;)
|
||||||
|
INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
||||||
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, <init>, (Lkotlinx/serialization/KSerializer;)V)
|
||||||
POP
|
POP
|
||||||
LABEL (L3)
|
LABEL (L3)
|
||||||
@@ -109,7 +110,8 @@ public final class IntrinsicsAdvancedKt : java/lang/Object {
|
|||||||
ANEWARRAY (kotlinx/serialization/KSerializer)
|
ANEWARRAY (kotlinx/serialization/KSerializer)
|
||||||
DUP
|
DUP
|
||||||
ICONST_0
|
ICONST_0
|
||||||
GETSTATIC (Simple$$serializer, INSTANCE, LSimple$$serializer;)
|
GETSTATIC (Simple, Companion, LSimple$Companion;)
|
||||||
|
INVOKEVIRTUAL (Simple$Companion, serializer, ()Lkotlinx/serialization/KSerializer;)
|
||||||
AASTORE
|
AASTORE
|
||||||
INVOKESTATIC (kotlinx/serialization/SerializersKt, noCompiledSerializer, (Lkotlinx/serialization/modules/SerializersModule;Lkotlin/reflect/KClass;[Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;)
|
INVOKESTATIC (kotlinx/serialization/SerializersKt, noCompiledSerializer, (Lkotlinx/serialization/modules/SerializersModule;Lkotlin/reflect/KClass;[Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;)
|
||||||
LABEL (L15)
|
LABEL (L15)
|
||||||
|
|||||||
+6
@@ -111,6 +111,12 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization
|
|||||||
runTest("plugins/kotlinx-serialization/testData/boxIr/inlineClasses.kt");
|
runTest("plugins/kotlinx-serialization/testData/boxIr/inlineClasses.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("intrinsicAnnotations.kt")
|
||||||
|
public void testIntrinsicAnnotations() throws Exception {
|
||||||
|
runTest("plugins/kotlinx-serialization/testData/boxIr/intrinsicAnnotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("intrinsicsBox.kt")
|
@TestMetadata("intrinsicsBox.kt")
|
||||||
public void testIntrinsicsBox() throws Exception {
|
public void testIntrinsicsBox() throws Exception {
|
||||||
|
|||||||
+6
@@ -109,6 +109,12 @@ public class SerializationIrBoxTestGenerated extends AbstractSerializationIrBoxT
|
|||||||
runTest("plugins/kotlinx-serialization/testData/boxIr/inlineClasses.kt");
|
runTest("plugins/kotlinx-serialization/testData/boxIr/inlineClasses.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("intrinsicAnnotations.kt")
|
||||||
|
public void testIntrinsicAnnotations() throws Exception {
|
||||||
|
runTest("plugins/kotlinx-serialization/testData/boxIr/intrinsicAnnotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("intrinsicsBox.kt")
|
@TestMetadata("intrinsicsBox.kt")
|
||||||
public void testIntrinsicsBox() throws Exception {
|
public void testIntrinsicsBox() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user