Support enum serialization in FIR
for all runtime versions, re-enable optimization in IR backend by correctly determining presence of functions in runtime.
This commit is contained in:
@@ -5,6 +5,10 @@ plugins {
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(intellijCore())
|
||||
compileOnly(commonDependency("org.jetbrains.intellij.deps:asm-all"))
|
||||
|
||||
+3
-3
@@ -48,10 +48,10 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
= compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.ARRAY_MASK_FIELD_MISSING_FUNC_NAME)).singleOrNull()
|
||||
|
||||
private val enumSerializerFactoryFunc
|
||||
= compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME)).singleOrNull()
|
||||
= compilerContext.enumSerializerFactoryFunc
|
||||
|
||||
private val markedEnumSerializerFactoryFunc
|
||||
= compilerContext.referenceFunctions(CallableId(SerializationPackages.internalPackageFqName, SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)).singleOrNull()
|
||||
= compilerContext.markedEnumSerializerFactoryFunc
|
||||
|
||||
fun useFieldMissingOptimization(): Boolean {
|
||||
return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null
|
||||
@@ -535,7 +535,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
}
|
||||
|
||||
|
||||
val serializable = serializerClass?.owner?.let { getSerializableClassDescriptorBySerializer(it) }
|
||||
val serializable = serializerClass?.owner?.let { compilerContext.getSerializableClassDescriptorBySerializer(it) }
|
||||
requireNotNull(serializerClass)
|
||||
val ctor = if (serializable?.typeParameters?.isNotEmpty() == true) {
|
||||
requireNotNull(
|
||||
|
||||
+5
-7
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.fir.SerializationPluginKey
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
@@ -61,10 +62,7 @@ internal fun IrClass.findPluginGeneratedMethod(name: String): IrSimpleFunction?
|
||||
}
|
||||
}
|
||||
|
||||
internal fun IrClass.isEnumWithLegacyGeneratedSerializer(): Boolean = isInternallySerializableEnum() && useGeneratedEnumSerializer
|
||||
|
||||
internal val IrClass.useGeneratedEnumSerializer: Boolean
|
||||
get() = true // FIXME This would break if we try to use this new IR compiler with pre-1.4.1 serialization versions. I think we just need to raise min runtime version.
|
||||
internal fun IrClass.isEnumWithLegacyGeneratedSerializer(context: SerializationPluginContext): Boolean = isInternallySerializableEnum() && !context.runtimeHasEnumSerializerFactoryFunctions
|
||||
|
||||
internal val IrClass.isSealedSerializableInterface: Boolean
|
||||
get() = kind == ClassKind.INTERFACE && modality == Modality.SEALED && hasSerializableOrMetaAnnotation()
|
||||
@@ -100,9 +98,9 @@ internal val IrClass.isSerialInfoAnnotation: Boolean
|
||||
|| annotations.hasAnnotation(SerializationAnnotations.inheritableSerialInfoFqName)
|
||||
|| annotations.hasAnnotation(SerializationAnnotations.metaSerializableAnnotationFqName)
|
||||
|
||||
internal val IrClass.shouldHaveGeneratedSerializer: Boolean
|
||||
get() = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN))
|
||||
|| isEnumWithLegacyGeneratedSerializer()
|
||||
internal fun IrClass.shouldHaveGeneratedSerializer(context: SerializationPluginContext): Boolean
|
||||
= (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN))
|
||||
|| isEnumWithLegacyGeneratedSerializer(context)
|
||||
|
||||
internal val IrClass.shouldHaveGeneratedMethodsInCompanion: Boolean
|
||||
get() = this.isSerializableObject || this.isSerializableEnum() || (this.kind == ClassKind.CLASS && hasSerializableOrMetaAnnotation()) || this.isSealedSerializableInterface
|
||||
|
||||
+4
-4
@@ -56,7 +56,7 @@ open class SerializerIrGenerator(
|
||||
compilerContext: SerializationPluginContext,
|
||||
metadataPlugin: SerializationDescriptorSerializerPlugin?,
|
||||
) : BaseIrGenerator(irClass, compilerContext) {
|
||||
protected val serializableIrClass = getSerializableClassDescriptorBySerializer(irClass)!!
|
||||
protected val serializableIrClass = compilerContext.getSerializableClassDescriptorBySerializer(irClass)!!
|
||||
|
||||
protected val serialName: String = serializableIrClass.serialName()
|
||||
protected val properties = serializablePropertiesForIrBackend(serializableIrClass, metadataPlugin)
|
||||
@@ -620,13 +620,13 @@ open class SerializerIrGenerator(
|
||||
context: SerializationPluginContext,
|
||||
metadataPlugin: SerializationDescriptorSerializerPlugin?,
|
||||
) {
|
||||
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
|
||||
val serializableDesc = context.getSerializableClassDescriptorBySerializer(irClass) ?: return
|
||||
val generator = when {
|
||||
serializableDesc.isEnumWithLegacyGeneratedSerializer() -> SerializerForEnumsGenerator(
|
||||
serializableDesc.isEnumWithLegacyGeneratedSerializer(context) -> SerializerForEnumsGenerator(
|
||||
irClass,
|
||||
context
|
||||
)
|
||||
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context)
|
||||
serializableDesc.isValue -> SerializerForInlineClassGenerator(irClass, context)
|
||||
else -> SerializerIrGenerator(irClass, context, metadataPlugin)
|
||||
}
|
||||
generator.generate()
|
||||
|
||||
+4
-4
@@ -117,7 +117,7 @@ fun findTypeSerializer(context: SerializationPluginContext, type: IrType): IrCla
|
||||
}
|
||||
fun findEnumTypeSerializer(context: SerializationPluginContext, type: IrType): IrClassSymbol? {
|
||||
val classSymbol = type.classOrNull?.owner ?: return null
|
||||
return if (classSymbol.kind == ClassKind.ENUM_CLASS && !classSymbol.isEnumWithLegacyGeneratedSerializer())
|
||||
return if (classSymbol.kind == ClassKind.ENUM_CLASS && !classSymbol.isEnumWithLegacyGeneratedSerializer(context))
|
||||
context.referenceClass(enumSerializerId)
|
||||
else null
|
||||
}
|
||||
@@ -130,7 +130,7 @@ internal fun IrClass?.classSerializer(context: SerializationPluginContext): IrCl
|
||||
// can infer @Poly?
|
||||
polymorphicSerializerIfApplicableAutomatically(context)?.let { return it }
|
||||
// default serializable?
|
||||
if (shouldHaveGeneratedSerializer) {
|
||||
if (shouldHaveGeneratedSerializer(context)) {
|
||||
// $serializer nested class
|
||||
return this.declarations
|
||||
.filterIsInstance<IrClass>()
|
||||
@@ -217,7 +217,7 @@ fun BaseIrGenerator.allSealedSerializableSubclassesFor(
|
||||
}.unzip()
|
||||
}
|
||||
|
||||
internal fun getSerializableClassDescriptorBySerializer(serializer: IrClass): IrClass? {
|
||||
internal fun SerializationPluginContext.getSerializableClassDescriptorBySerializer(serializer: IrClass): IrClass? {
|
||||
val serializerForClass = serializer.serializerForClass
|
||||
if (serializerForClass != null) return serializerForClass.owner
|
||||
if (serializer.name !in setOf(
|
||||
@@ -226,7 +226,7 @@ internal fun getSerializableClassDescriptorBySerializer(serializer: IrClass): Ir
|
||||
)
|
||||
) return null
|
||||
val classDescriptor = (serializer.parent as? IrClass) ?: return null
|
||||
if (!classDescriptor.shouldHaveGeneratedSerializer) return null
|
||||
if (!classDescriptor.shouldHaveGeneratedSerializer(this)) return null
|
||||
return classDescriptor
|
||||
}
|
||||
|
||||
|
||||
+19
@@ -17,9 +17,12 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.ir.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
@@ -44,6 +47,22 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
|
||||
lateinit var serialInfoImplJvmIrGenerator: SerialInfoImplJvmIrGenerator
|
||||
|
||||
internal val copiedStaticWriteSelf: MutableMap<IrSimpleFunction, IrSimpleFunction> = ConcurrentHashMap()
|
||||
|
||||
internal val enumSerializerFactoryFunc = baseContext.referenceFunctions(
|
||||
CallableId(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
)
|
||||
).singleOrNull()
|
||||
|
||||
internal val markedEnumSerializerFactoryFunc = baseContext.referenceFunctions(
|
||||
CallableId(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
)
|
||||
).singleOrNull()
|
||||
|
||||
val runtimeHasEnumSerializerFactoryFunctions = enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null
|
||||
}
|
||||
|
||||
private inline fun IrClass.runPluginSafe(block: () -> Unit) {
|
||||
|
||||
+21
-1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.moduleData
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.*
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
@@ -53,6 +54,21 @@ val kSerializerClassId = ClassId(SerializationPackages.packageFqName, SerialEnti
|
||||
|
||||
class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGenerationExtension(session) {
|
||||
|
||||
internal val runtimeHasEnumSerializerFactory by lazy {
|
||||
val hasFactory = session.symbolProvider.getTopLevelCallableSymbols(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
).isNotEmpty()
|
||||
val hasMarkedFactory = session.symbolProvider.getTopLevelCallableSymbols(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
).isNotEmpty()
|
||||
hasFactory && hasMarkedFactory
|
||||
}
|
||||
|
||||
internal val FirClassSymbol<*>.shouldHaveGeneratedSerializer: Boolean
|
||||
get() = (isInternalSerializable && isFinalOrOpen()) || (classKind == ClassKind.ENUM_CLASS && hasSerializableAnnotationWithoutArgs && !runtimeHasEnumSerializerFactory)
|
||||
|
||||
override fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||
val result = mutableSetOf<Name>()
|
||||
if (classSymbol.shouldHaveGeneratedMethodsInCompanion && !classSymbol.isSerializableObject)
|
||||
@@ -156,7 +172,11 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
return listOf(copy.symbol)
|
||||
}
|
||||
|
||||
private fun generateSerializerGetterInCompanion(owner: FirClassSymbol<*>, serializableClassSymbol: FirClassSymbol<*>, callableId: CallableId): FirNamedFunctionSymbol {
|
||||
private fun generateSerializerGetterInCompanion(
|
||||
owner: FirClassSymbol<*>,
|
||||
serializableClassSymbol: FirClassSymbol<*>,
|
||||
callableId: CallableId
|
||||
): FirNamedFunctionSymbol {
|
||||
val f = buildSimpleFunction {
|
||||
moduleData = session.moduleData
|
||||
symbol = FirNamedFunctionSymbol(callableId)
|
||||
|
||||
+1
-13
@@ -5,22 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlinx.serialization.compiler.fir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingDeclarationSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.outerClassSymbol
|
||||
import org.jetbrains.kotlin.fir.declarations.findArgumentByName
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.expressions.classId
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isSerializableObject
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.shouldHaveGeneratedMethodsInCompanion
|
||||
|
||||
internal val FirClassSymbol<*>.hasSerializableAnnotation
|
||||
get() = this.annotations.any {
|
||||
@@ -56,13 +50,7 @@ internal val FirClassSymbol<*>.isInternalSerializable: Boolean
|
||||
|
||||
internal fun FirClassSymbol<*>.isSerializableEnum(): Boolean = classKind == ClassKind.ENUM_CLASS && hasSerializableAnnotation
|
||||
|
||||
internal fun FirClassSymbol<*>.isInternallySerializableEnum(): Boolean =
|
||||
classKind == ClassKind.ENUM_CLASS && hasSerializableAnnotationWithoutArgs
|
||||
|
||||
internal val FirClassSymbol<*>.shouldHaveGeneratedSerializer: Boolean
|
||||
get() = (isInternalSerializable && isFinalOrOpen()) || isInternallySerializableEnum()
|
||||
|
||||
private fun FirClassSymbol<*>.isFinalOrOpen(): Boolean {
|
||||
internal fun FirClassSymbol<*>.isFinalOrOpen(): Boolean {
|
||||
val modality = rawStatus.modality
|
||||
// null means default modality, final
|
||||
return (modality == null || modality == Modality.FINAL || modality == Modality.OPEN)
|
||||
|
||||
+6
@@ -49,6 +49,12 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/defaultProperties.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enums.kt")
|
||||
public void testEnums() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/enums.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProperties.kt")
|
||||
public void testMultipleProperties() throws Exception {
|
||||
|
||||
+6
@@ -48,6 +48,12 @@ public class SerializationFirMembersTestGenerated extends AbstractSerializationF
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/defaultProperties.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enums.kt")
|
||||
public void testEnums() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/enums.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multipleProperties.kt")
|
||||
public void testMultipleProperties() throws Exception {
|
||||
|
||||
+6
@@ -37,6 +37,12 @@ public class SerializationIrBoxTestGenerated extends AbstractSerializationIrBoxT
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxIr/classSerializerAsObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enumsAreCached.kt")
|
||||
public void testEnumsAreCached() throws Exception {
|
||||
runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxIr/enumsAreCached.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("generics.kt")
|
||||
public void testGenerics() throws Exception {
|
||||
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlinx.serialization.internal.*
|
||||
|
||||
enum class Plain {
|
||||
A, B
|
||||
}
|
||||
|
||||
@Serializable enum class WithNames {
|
||||
@SerialName("A") ENTRY1,
|
||||
@SerialName("B") ENTRY2
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Holder(val p: Plain, val w: WithNames)
|
||||
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
fun box(): String {
|
||||
val cs = (Holder.serializer() as GeneratedSerializer<*>).childSerializers()
|
||||
val str1 = cs[0].toString()
|
||||
if (!str1.contains("kotlinx.serialization.internal.EnumSerializer")) return str1
|
||||
|
||||
/**
|
||||
* Serialization 1.4.1+ have runtime factories to create EnumSerializer instead of synthetic $serializer, saving bytecode
|
||||
* and bringing consistency. After updating the version, uncomment this block.
|
||||
*/
|
||||
// val str2 = cs[1].toString()
|
||||
// if (!str2.contains("kotlinx.serialization.internal.EnumSerializer")) return str2
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+132
@@ -0,0 +1,132 @@
|
||||
FILE: enums.kt
|
||||
public final enum class Plain : R|kotlin/Enum<Plain>| {
|
||||
private constructor(): R|Plain| {
|
||||
super<R|kotlin/Enum<Plain>|>()
|
||||
}
|
||||
|
||||
public final static enum entry A: R|Plain|
|
||||
public final static enum entry B: R|Plain|
|
||||
public final static fun values(): R|kotlin/Array<Plain>| {
|
||||
}
|
||||
|
||||
public final static fun valueOf(value: R|kotlin/String|): R|Plain| {
|
||||
}
|
||||
|
||||
public final static val entries: R|kotlin/enums/EnumEntries<Plain>|
|
||||
public get(): R|kotlin/enums/EnumEntries<Plain>|
|
||||
|
||||
}
|
||||
@R|kotlinx/serialization/Serializable|() public final enum class WithNames : R|kotlin/Enum<WithNames>| {
|
||||
private constructor(): R|WithNames| {
|
||||
super<R|kotlin/Enum<WithNames>|>()
|
||||
}
|
||||
|
||||
@R|kotlinx/serialization/SerialName|(value = String(A)) public final static enum entry ENTRY1: R|WithNames| = object : R|WithNames| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|WithNames|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@R|kotlinx/serialization/SerialName|(value = String(B)) public final static enum entry ENTRY2: R|WithNames| = object : R|WithNames| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|WithNames|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static fun values(): R|kotlin/Array<WithNames>| {
|
||||
}
|
||||
|
||||
public final static fun valueOf(value: R|kotlin/String|): R|WithNames| {
|
||||
}
|
||||
|
||||
public final static val entries: R|kotlin/enums/EnumEntries<WithNames>|
|
||||
public get(): R|kotlin/enums/EnumEntries<WithNames>|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<WithNames>|
|
||||
|
||||
private constructor(): R|WithNames.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<WithNames>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|WithNames|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|WithNames|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|WithNames.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|kotlinx/serialization/Serializable|() public final class Holder : R|kotlin/Any| {
|
||||
public constructor(p: R|Plain|, w: R|WithNames|): R|Holder| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val p: R|Plain| = R|<local>/p|
|
||||
public get(): R|Plain|
|
||||
|
||||
public final val w: R|WithNames| = R|<local>/w|
|
||||
public get(): R|WithNames|
|
||||
|
||||
public final companion object Companion : R|kotlin/Any| {
|
||||
public final fun serializer(): R|kotlinx/serialization/KSerializer<Holder>|
|
||||
|
||||
private constructor(): R|Holder.Companion|
|
||||
|
||||
}
|
||||
|
||||
public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer<Holder>| {
|
||||
public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|Holder|): R|kotlin/Unit|
|
||||
|
||||
public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|Holder|
|
||||
|
||||
public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
public get(): R|kotlinx/serialization/descriptors/SerialDescriptor|
|
||||
|
||||
public final fun childSerializers(): R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|
|
||||
|
||||
private constructor(): R|Holder.$serializer|
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@R|kotlin/OptIn|(markerClass = vararg(<getClass>(Q|kotlinx/serialization/InternalSerializationApi|))) public final fun testSerializers(): R|kotlin/String| {
|
||||
lval cs: R|kotlin/Array<kotlinx/serialization/KSerializer<*>>| = (Q|Holder|.R|/Holder.Companion.serializer|() as R|kotlinx/serialization/internal/GeneratedSerializer<*>|).R|SubstitutionOverride<kotlinx/serialization/internal/GeneratedSerializer.childSerializers: R|kotlin/Array<kotlinx/serialization/KSerializer<*>>|>|()
|
||||
lval str1: R|kotlin/String| = R|<local>/cs|.R|SubstitutionOverride<kotlin/Array.get: R|kotlinx/serialization/KSerializer<*>|>|(Int(0)).R|kotlin/Any.toString|()
|
||||
when () {
|
||||
R|<local>/str1|.R|kotlin/text/contains|(String(kotlinx.serialization.internal.EnumSerializer)).R|kotlin/Boolean.not|() -> {
|
||||
^testSerializers R|<local>/str1|
|
||||
}
|
||||
}
|
||||
|
||||
^testSerializers String(OK)
|
||||
}
|
||||
public final fun testSerialization(previous: R|kotlin/String|): R|kotlin/String| {
|
||||
when () {
|
||||
!=(R|<local>/previous|, String(OK)) -> {
|
||||
^testSerialization R|<local>/previous|
|
||||
}
|
||||
}
|
||||
|
||||
lval h: R|Holder| = R|/Holder.Holder|(Q|Plain|.R|/Plain.B|, Q|WithNames|.R|/WithNames.ENTRY1|)
|
||||
lval s: R|kotlin/String| = Q|kotlinx/serialization/json/Json|.R|kotlinx/serialization/json/Json.encodeToString|<R|Holder|>(Q|Holder|.R|/Holder.Companion.serializer|(), R|<local>/h|)
|
||||
when () {
|
||||
!=(R|<local>/s|, String({"p":"B","w":"A"})) -> {
|
||||
^testSerialization R|<local>/s|
|
||||
}
|
||||
}
|
||||
|
||||
^testSerialization String(OK)
|
||||
}
|
||||
public final fun box(): R|kotlin/String| {
|
||||
^box R|/testSerialization|(R|/testSerializers|())
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
|
||||
// WITH_STDLIB
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlinx.serialization.internal.*
|
||||
|
||||
enum class Plain {
|
||||
A, B
|
||||
}
|
||||
|
||||
@Serializable enum class WithNames {
|
||||
@SerialName("A") ENTRY1,
|
||||
@SerialName("B") ENTRY2
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class Holder(val p: Plain, val w: WithNames)
|
||||
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
fun testSerializers(): String {
|
||||
val cs = (Holder.serializer() as GeneratedSerializer<*>).childSerializers()
|
||||
val str1 = cs[0].toString()
|
||||
if (!str1.contains("kotlinx.serialization.internal.EnumSerializer")) return str1
|
||||
|
||||
/**
|
||||
* Serialization 1.4.1+ have runtime factories to create EnumSerializer instead of synthetic $serializer, saving bytecode
|
||||
* and bringing consistency. After updating the version, uncomment this block.
|
||||
*/
|
||||
// val str2 = cs[1].toString()
|
||||
// if (!str2.contains("kotlinx.serialization.internal.EnumSerializer")) return str2
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun testSerialization(previous: String): String {
|
||||
if (previous != "OK") return previous
|
||||
val h = Holder(Plain.B, WithNames.ENTRY1)
|
||||
val s = Json.encodeToString(Holder.serializer(), h)
|
||||
if (s != """{"p":"B","w":"A"}""") return s
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return testSerialization(testSerializers())
|
||||
}
|
||||
Reference in New Issue
Block a user