Support sealed, generic and abstract polymorphic inheritors in sealed class serialization
This commit is contained in:
+6
-2
@@ -90,12 +90,16 @@ fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty): S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AbstractSerialGenerator.immediateSealedSerializableSubclassesFor(
|
fun AbstractSerialGenerator.allSealedSerializableSubclassesFor(
|
||||||
klass: ClassDescriptor,
|
klass: ClassDescriptor,
|
||||||
module: ModuleDescriptor
|
module: ModuleDescriptor
|
||||||
): Pair<List<KotlinType>, List<ClassDescriptor>> {
|
): Pair<List<KotlinType>, List<ClassDescriptor>> {
|
||||||
assert(klass.kind == ClassKind.CLASS && klass.modality == Modality.SEALED)
|
assert(klass.kind == ClassKind.CLASS && klass.modality == Modality.SEALED)
|
||||||
val serializableSubtypes = klass.sealedSubclasses.map { it.toSimpleType() }
|
fun recursiveSealed(klass: ClassDescriptor): Collection<ClassDescriptor> {
|
||||||
|
return klass.sealedSubclasses.flatMap { if (it.modality == Modality.SEALED) recursiveSealed(it) else setOf(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val serializableSubtypes = recursiveSealed(klass).map { it.toSimpleType() }
|
||||||
return serializableSubtypes to serializableSubtypes.mapNotNull { findTypeSerializerOrContextUnchecked(module, it) }
|
return serializableSubtypes to serializableSubtypes.mapNotNull { findTypeSerializerOrContextUnchecked(module, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-12
@@ -33,8 +33,8 @@ import org.jetbrains.kotlin.types.*
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.AbstractSerialGenerator
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.AbstractSerialGenerator
|
||||||
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.allSealedSerializableSubclassesFor
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.immediateSealedSerializableSubclassesFor
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
@@ -466,7 +466,6 @@ interface IrBuilderExtension {
|
|||||||
return serializerInstance(
|
return serializerInstance(
|
||||||
generator,
|
generator,
|
||||||
dispatchReceiverParameter,
|
dispatchReceiverParameter,
|
||||||
generator.serializableDescriptor,
|
|
||||||
serializer,
|
serializer,
|
||||||
property.module,
|
property.module,
|
||||||
property.type,
|
property.type,
|
||||||
@@ -506,37 +505,34 @@ interface IrBuilderExtension {
|
|||||||
fun IrBuilderWithScope.serializerInstance(
|
fun IrBuilderWithScope.serializerInstance(
|
||||||
enclosingGenerator: SerializerIrGenerator,
|
enclosingGenerator: SerializerIrGenerator,
|
||||||
dispatchReceiverParameter: IrValueParameter,
|
dispatchReceiverParameter: IrValueParameter,
|
||||||
serializableDescriptor: ClassDescriptor,
|
|
||||||
serializerClassOriginal: ClassDescriptor?,
|
serializerClassOriginal: ClassDescriptor?,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
kType: KotlinType,
|
kType: KotlinType,
|
||||||
genericIndex: Int? = null
|
genericIndex: Int? = null
|
||||||
): IrExpression? = serializerInstance(
|
): IrExpression? = serializerInstance(
|
||||||
enclosingGenerator,
|
enclosingGenerator,
|
||||||
serializableDescriptor,
|
|
||||||
serializerClassOriginal,
|
serializerClassOriginal,
|
||||||
module,
|
module,
|
||||||
kType,
|
kType,
|
||||||
genericIndex
|
genericIndex
|
||||||
) {
|
) { it, _ ->
|
||||||
val prop = enclosingGenerator.localSerializersFieldsDescriptors[it]
|
val prop = enclosingGenerator.localSerializersFieldsDescriptors[it]
|
||||||
irGetField(irGet(dispatchReceiverParameter), compilerContext.localSymbolTable.referenceField(prop).owner)
|
irGetField(irGet(dispatchReceiverParameter), compilerContext.localSymbolTable.referenceField(prop).owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrBuilderWithScope.serializerInstance(
|
fun IrBuilderWithScope.serializerInstance(
|
||||||
enclosingGenerator: AbstractSerialGenerator,
|
enclosingGenerator: AbstractSerialGenerator,
|
||||||
serializableDescriptor: ClassDescriptor,
|
|
||||||
serializerClassOriginal: ClassDescriptor?,
|
serializerClassOriginal: ClassDescriptor?,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
kType: KotlinType,
|
kType: KotlinType,
|
||||||
genericIndex: Int? = null,
|
genericIndex: Int? = null,
|
||||||
genericGetter: (Int) -> IrExpression
|
genericGetter: ((Int, KotlinType) -> IrExpression)? = null
|
||||||
): IrExpression? {
|
): IrExpression? {
|
||||||
val nullableSerClass =
|
val nullableSerClass =
|
||||||
compilerContext.externalSymbols.referenceClass(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
|
compilerContext.externalSymbols.referenceClass(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
|
||||||
if (serializerClassOriginal == null) {
|
if (serializerClassOriginal == null) {
|
||||||
if (genericIndex == null) return null
|
if (genericIndex == null) return null
|
||||||
return genericGetter(genericIndex)
|
return genericGetter?.invoke(genericIndex, kType)
|
||||||
}
|
}
|
||||||
if (serializerClassOriginal.kind == ClassKind.OBJECT) {
|
if (serializerClassOriginal.kind == ClassKind.OBJECT) {
|
||||||
return irGetObject(serializerClassOriginal)
|
return irGetObject(serializerClassOriginal)
|
||||||
@@ -544,7 +540,6 @@ interface IrBuilderExtension {
|
|||||||
fun instantiate(serializer: ClassDescriptor?, type: KotlinType): IrExpression? {
|
fun instantiate(serializer: ClassDescriptor?, type: KotlinType): IrExpression? {
|
||||||
val expr = serializerInstance(
|
val expr = serializerInstance(
|
||||||
enclosingGenerator,
|
enclosingGenerator,
|
||||||
serializableDescriptor,
|
|
||||||
serializer,
|
serializer,
|
||||||
module,
|
module,
|
||||||
type,
|
type,
|
||||||
@@ -569,7 +564,8 @@ interface IrBuilderExtension {
|
|||||||
sealedSerializerId -> {
|
sealedSerializerId -> {
|
||||||
args = mutableListOf<IrExpression>().apply {
|
args = mutableListOf<IrExpression>().apply {
|
||||||
add(irString(kType.serialName()))
|
add(irString(kType.serialName()))
|
||||||
val (subclasses, subSerializers) = enclosingGenerator.immediateSealedSerializableSubclassesFor(
|
add(classReference(kType))
|
||||||
|
val (subclasses, subSerializers) = enclosingGenerator.allSealedSerializableSubclassesFor(
|
||||||
kType.toClassDescriptor!!,
|
kType.toClassDescriptor!!,
|
||||||
module
|
module
|
||||||
)
|
)
|
||||||
@@ -583,14 +579,33 @@ interface IrBuilderExtension {
|
|||||||
add(
|
add(
|
||||||
createArrayOfExpression(
|
createArrayOfExpression(
|
||||||
wrapIrTypeIntoKSerializerIrType(module, thisIrType, variance = Variance.OUT_VARIANCE),
|
wrapIrTypeIntoKSerializerIrType(module, thisIrType, variance = Variance.OUT_VARIANCE),
|
||||||
subSerializers.mapIndexed { i, ser -> instantiate(ser, subclasses[i])!! }
|
subSerializers.mapIndexed { i, serializer ->
|
||||||
|
val type = subclasses[i]
|
||||||
|
val expr = serializerInstance(
|
||||||
|
enclosingGenerator,
|
||||||
|
serializer,
|
||||||
|
module,
|
||||||
|
type,
|
||||||
|
type.genericIndex
|
||||||
|
) { _, genericType ->
|
||||||
|
serializerInstance(
|
||||||
|
enclosingGenerator,
|
||||||
|
module.getClassFromSerializationPackage(
|
||||||
|
SpecialBuiltins.polymorphicSerializer
|
||||||
|
),
|
||||||
|
module,
|
||||||
|
genericType
|
||||||
|
)!!
|
||||||
|
}!!
|
||||||
|
wrapWithNullableSerializerIfNeeded(module, type, expr, nullableSerClass)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
typeArgs = listOf(thisIrType)
|
typeArgs = listOf(thisIrType)
|
||||||
}
|
}
|
||||||
enumSerializerId -> {
|
enumSerializerId -> {
|
||||||
serializerClass = serializableDescriptor.getClassFromInternalSerializationPackage("CommonEnumSerializer")
|
serializerClass = module.getClassFromInternalSerializationPackage("CommonEnumSerializer")
|
||||||
args = kType.toClassDescriptor!!.let { enumDesc ->
|
args = kType.toClassDescriptor!!.let { enumDesc ->
|
||||||
listOf(
|
listOf(
|
||||||
irString(enumDesc.serialName()),
|
irString(enumDesc.serialName()),
|
||||||
|
|||||||
+2
-6
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.builders.irReturn
|
|||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.types.defaultType
|
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
@@ -23,8 +22,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.shouldHaveGeneratedMethodsInCompanion
|
|
||||||
|
|
||||||
class SerializableCompanionIrGenerator(
|
class SerializableCompanionIrGenerator(
|
||||||
val irClass: IrClass,
|
val irClass: IrClass,
|
||||||
@@ -94,10 +91,9 @@ class SerializableCompanionIrGenerator(
|
|||||||
val args: List<IrExpression> = getter.valueParameters.map { irGet(it) }
|
val args: List<IrExpression> = getter.valueParameters.map { irGet(it) }
|
||||||
val expr = serializerInstance(
|
val expr = serializerInstance(
|
||||||
this@SerializableCompanionIrGenerator,
|
this@SerializableCompanionIrGenerator,
|
||||||
serializableDescriptor, serializer,
|
serializer, serializableDescriptor.module,
|
||||||
serializableDescriptor.module,
|
|
||||||
serializableDescriptor.defaultType
|
serializableDescriptor.defaultType
|
||||||
) { args[it] }
|
) { it, _ -> args[it] }
|
||||||
patchSerializableClassWithMarkerAnnotation(serializer)
|
patchSerializableClassWithMarkerAnnotation(serializer)
|
||||||
+irReturn(requireNotNull(expr))
|
+irReturn(requireNotNull(expr))
|
||||||
}
|
}
|
||||||
|
|||||||
-2
@@ -248,7 +248,6 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
|
|||||||
val innerSerial = serializerInstance(
|
val innerSerial = serializerInstance(
|
||||||
this@SerializerIrGenerator,
|
this@SerializerIrGenerator,
|
||||||
saveFunc.dispatchReceiverParameter!!,
|
saveFunc.dispatchReceiverParameter!!,
|
||||||
serializableDescriptor,
|
|
||||||
sti.serializer,
|
sti.serializer,
|
||||||
property.module,
|
property.module,
|
||||||
property.type,
|
property.type,
|
||||||
@@ -381,7 +380,6 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
|
|||||||
val innerSerial = serializerInstance(
|
val innerSerial = serializerInstance(
|
||||||
this@SerializerIrGenerator,
|
this@SerializerIrGenerator,
|
||||||
loadFunc.dispatchReceiverParameter!!,
|
loadFunc.dispatchReceiverParameter!!,
|
||||||
serializableDescriptor,
|
|
||||||
sti.serializer,
|
sti.serializer,
|
||||||
property.module,
|
property.module,
|
||||||
property.type,
|
property.type,
|
||||||
|
|||||||
+21
-5
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
@@ -134,13 +135,18 @@ internal fun AbstractSerialGenerator.serializerInstance(
|
|||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
kType: KotlinType,
|
kType: KotlinType,
|
||||||
genericIndex: Int? = null,
|
genericIndex: Int? = null,
|
||||||
genericGetter: (Int) -> JsExpression = { JsNameRef(context.scope().declareName("${SerialEntityNames.typeArgPrefix}$it"), JsThisRef()) }
|
genericGetter: (Int, KotlinType) -> JsExpression = { it, _ ->
|
||||||
|
JsNameRef(
|
||||||
|
context.scope().declareName("${SerialEntityNames.typeArgPrefix}$it"),
|
||||||
|
JsThisRef()
|
||||||
|
)
|
||||||
|
}
|
||||||
): JsExpression? {
|
): JsExpression? {
|
||||||
val nullableSerClass =
|
val nullableSerClass =
|
||||||
context.translateQualifiedReference(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
|
context.translateQualifiedReference(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
|
||||||
if (serializerClass == null) {
|
if (serializerClass == null) {
|
||||||
if (genericIndex == null) return null
|
if (genericIndex == null) return null
|
||||||
return genericGetter(genericIndex)
|
return genericGetter(genericIndex, kType)
|
||||||
}
|
}
|
||||||
if (serializerClass.kind == ClassKind.OBJECT) {
|
if (serializerClass.kind == ClassKind.OBJECT) {
|
||||||
return context.serializerObjectGetter(serializerClass)
|
return context.serializerObjectGetter(serializerClass)
|
||||||
@@ -163,7 +169,8 @@ internal fun AbstractSerialGenerator.serializerInstance(
|
|||||||
)
|
)
|
||||||
serializerClass.classId == sealedSerializerId -> mutableListOf<JsExpression>().apply {
|
serializerClass.classId == sealedSerializerId -> mutableListOf<JsExpression>().apply {
|
||||||
add(JsStringLiteral(kType.serialName()))
|
add(JsStringLiteral(kType.serialName()))
|
||||||
val (subclasses, subSerializers) = immediateSealedSerializableSubclassesFor(
|
add(ExpressionVisitor.getObjectKClass(context, kType.toClassDescriptor!!))
|
||||||
|
val (subclasses, subSerializers) = allSealedSerializableSubclassesFor(
|
||||||
kType.toClassDescriptor!!,
|
kType.toClassDescriptor!!,
|
||||||
module
|
module
|
||||||
)
|
)
|
||||||
@@ -173,8 +180,17 @@ internal fun AbstractSerialGenerator.serializerInstance(
|
|||||||
it.toClassDescriptor!!
|
it.toClassDescriptor!!
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
add(JsArrayLiteral(subSerializers.mapIndexed { i, ser ->
|
add(JsArrayLiteral(subSerializers.mapIndexed { i, serializer ->
|
||||||
instantiate(ser, subclasses[i])!!
|
val type = subclasses[i]
|
||||||
|
val expr = serializerInstance(context, serializer, module, type, type.genericIndex) { _, genericType ->
|
||||||
|
serializerInstance(
|
||||||
|
context,
|
||||||
|
module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer),
|
||||||
|
module,
|
||||||
|
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound
|
||||||
|
)!!
|
||||||
|
}!!
|
||||||
|
if (type.isMarkedNullable) JsNew(nullableSerClass, listOf(expr)) else expr
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
else -> kType.arguments.map {
|
else -> kType.arguments.map {
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ class SerializableCompanionJsTranslator(
|
|||||||
serializer,
|
serializer,
|
||||||
serializableDescriptor.module,
|
serializableDescriptor.module,
|
||||||
serializableDescriptor.defaultType,
|
serializableDescriptor.defaultType,
|
||||||
genericGetter = {
|
genericGetter = { it, _ ->
|
||||||
args[it]
|
args[it]
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
+37
-8
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
||||||
@@ -177,7 +178,7 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(
|
|||||||
serializer,
|
serializer,
|
||||||
this,
|
this,
|
||||||
sti.property.genericIndex
|
sti.property.genericIndex
|
||||||
) { idx ->
|
) { idx, _ ->
|
||||||
load(varIndexStart + idx, kSerializerType)
|
load(varIndexStart + idx, kSerializerType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +202,7 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializerWithou
|
|||||||
serializer,
|
serializer,
|
||||||
this,
|
this,
|
||||||
property.genericIndex
|
property.genericIndex
|
||||||
) { idx ->
|
) { idx, _ ->
|
||||||
load(0, kSerializerType)
|
load(0, kSerializerType)
|
||||||
getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$idx", kSerializerType.descriptor)
|
getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$idx", kSerializerType.descriptor)
|
||||||
}.also { if (it && property.type.isMarkedNullable) wrapStackValueIntoNullableSerializer() }
|
}.also { if (it && property.type.isMarkedNullable) wrapStackValueIntoNullableSerializer() }
|
||||||
@@ -211,7 +212,7 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codeg
|
|||||||
return serializerCodegen.stackValueSerializerInstance(
|
return serializerCodegen.stackValueSerializerInstance(
|
||||||
codegen, sti.property.module, sti.property.type,
|
codegen, sti.property.module, sti.property.type,
|
||||||
sti.serializer, this, sti.property.genericIndex
|
sti.serializer, this, sti.property.genericIndex
|
||||||
) { idx ->
|
) { idx, _ ->
|
||||||
load(0, kSerializerType)
|
load(0, kSerializerType)
|
||||||
getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$idx", kSerializerType.descriptor)
|
getfield(codegen.typeMapper.mapClass(codegen.descriptor).internalName, "$typeArgPrefix$idx", kSerializerType.descriptor)
|
||||||
}
|
}
|
||||||
@@ -220,10 +221,13 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codeg
|
|||||||
// returns false is cannot not use serializer
|
// returns false is cannot not use serializer
|
||||||
// use iv == null to check only (do not emit serializer onto stack)
|
// use iv == null to check only (do not emit serializer onto stack)
|
||||||
internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||||
iv: InstructionAdapter?, genericIndex: Int? = null, genericSerializerFieldGetter: (InstructionAdapter.(Int) -> Unit)? = null): Boolean {
|
iv: InstructionAdapter?,
|
||||||
|
genericIndex: Int? = null,
|
||||||
|
genericSerializerFieldGetter: (InstructionAdapter.(Int, KotlinType) -> Unit)? = null
|
||||||
|
): Boolean {
|
||||||
if (maybeSerializer == null && genericIndex != null) {
|
if (maybeSerializer == null && genericIndex != null) {
|
||||||
// get field from serializer object
|
// get field from serializer object
|
||||||
iv?.run { genericSerializerFieldGetter?.invoke(this, genericIndex) }
|
iv?.run { genericSerializerFieldGetter?.invoke(this, genericIndex, kType) }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
val serializer = maybeSerializer ?: return false
|
val serializer = maybeSerializer ?: return false
|
||||||
@@ -302,16 +306,41 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: Class
|
|||||||
sealedSerializerId -> {
|
sealedSerializerId -> {
|
||||||
aconst(serialName)
|
aconst(serialName)
|
||||||
signature.append("Ljava/lang/String;")
|
signature.append("Ljava/lang/String;")
|
||||||
val (subClasses, subSerializers) = immediateSealedSerializableSubclassesFor(kType.toClassDescriptor!!, module)
|
aconst(codegen.typeMapper.mapType(kType, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
|
signature.append(AsmTypes.K_CLASS_TYPE.descriptor)
|
||||||
|
val (subClasses, subSerializers) = allSealedSerializableSubclassesFor(kType.toClassDescriptor!!, module)
|
||||||
// KClasses vararg
|
// KClasses vararg
|
||||||
fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { i, type ->
|
fillArray(AsmTypes.K_CLASS_TYPE, subClasses) { _, type ->
|
||||||
aconst(codegen.typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
aconst(codegen.typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||||
AsmUtil.wrapJavaClassIntoKClass(this)
|
AsmUtil.wrapJavaClassIntoKClass(this)
|
||||||
}
|
}
|
||||||
signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor)
|
signature.append(AsmTypes.K_CLASS_ARRAY_TYPE.descriptor)
|
||||||
// Serializers vararg
|
// Serializers vararg
|
||||||
fillArray(kSerializerType, subSerializers) { i, serializer ->
|
fillArray(kSerializerType, subSerializers) { i, serializer ->
|
||||||
instantiate(subClasses[i] to serializer, writeSignature = false)
|
val (argType, argSerializer) = subClasses[i] to serializer
|
||||||
|
assert(
|
||||||
|
stackValueSerializerInstance(
|
||||||
|
codegen,
|
||||||
|
module,
|
||||||
|
argType,
|
||||||
|
argSerializer,
|
||||||
|
this,
|
||||||
|
argType.genericIndex
|
||||||
|
) { _, genericType ->
|
||||||
|
// if we encountered generic type parameter in one of subclasses of sealed class, use polymorphism from upper bound
|
||||||
|
assert(
|
||||||
|
stackValueSerializerInstance(
|
||||||
|
codegen,
|
||||||
|
module,
|
||||||
|
(genericType.constructor.declarationDescriptor as TypeParameterDescriptor).representativeUpperBound,
|
||||||
|
module.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer),
|
||||||
|
this
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (argType.isMarkedNullable) wrapStackValueIntoNullableSerializer()
|
||||||
}
|
}
|
||||||
signature.append(kSerializerArrayType.descriptor)
|
signature.append(kSerializerArrayType.descriptor)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -104,8 +104,8 @@ class SerializableCodegenImpl(
|
|||||||
superTypeArguments.forEach {
|
superTypeArguments.forEach {
|
||||||
val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(it).let { if (it == -1) null else it }
|
val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(it).let { if (it == -1) null else it }
|
||||||
val serial = findTypeSerializerOrContext(serializableDescriptor.module, it.type)
|
val serial = findTypeSerializerOrContext(serializableDescriptor.module, it.type)
|
||||||
stackValueSerializerInstance(classCodegen, serializableDescriptor.module, it.type, serial, this, genericIdx) {
|
stackValueSerializerInstance(classCodegen, serializableDescriptor.module, it.type, serial, this, genericIdx) { i, _ ->
|
||||||
load(offsetI + it, kSerializerType)
|
load(offsetI + i, kSerializerType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val superSignature =
|
val superSignature =
|
||||||
|
|||||||
+1
-1
@@ -51,7 +51,7 @@ class SerializableCompanionCodegenImpl(private val classCodegen: ImplementationB
|
|||||||
serial,
|
serial,
|
||||||
this,
|
this,
|
||||||
null
|
null
|
||||||
) {
|
) { it, _ ->
|
||||||
load(it + 1, kSerializerType)
|
load(it + 1, kSerializerType)
|
||||||
}
|
}
|
||||||
areturn(kSerializerType)
|
areturn(kSerializerType)
|
||||||
|
|||||||
Reference in New Issue
Block a user