Support reference array and context serializers
Enum serializers are also instantiated, but won't work on native because of lack of KClass<E: Enum<E>>.enumValues()
This commit is contained in:
+26
-4
@@ -8,6 +8,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir
|
|||||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -25,11 +26,16 @@ import org.jetbrains.kotlin.ir.types.toKotlinType
|
|||||||
import org.jetbrains.kotlin.ir.types.typeWith
|
import org.jetbrains.kotlin.ir.types.typeWith
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
||||||
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.KotlinTypeFactory
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.AbstractSerialGenerator
|
|
||||||
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.jvm.contextSerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
|
||||||
@@ -360,6 +366,21 @@ interface IrBuilderExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.classReference(classType: KotlinType): IrClassReference {
|
||||||
|
val clazz = classType.toClassDescriptor!!
|
||||||
|
val kClass = clazz.module.findClassAcrossModuleDependencies(ClassId(FqName("kotlin.reflect"), Name.identifier("KClass")))!!
|
||||||
|
val returnType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, kClass, listOf(TypeProjectionImpl(Variance.INVARIANT, classType)))
|
||||||
|
return IrClassReferenceImpl(
|
||||||
|
startOffset,
|
||||||
|
endOffset,
|
||||||
|
returnType.toIrType(),
|
||||||
|
compilerContext.externalSymbols.referenceClassifier(clazz),
|
||||||
|
classType.toIrType()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Does not use sti and therefore does not perform encoder calls optimization
|
// Does not use sti and therefore does not perform encoder calls optimization
|
||||||
fun IrBuilderWithScope.serializerTower(generator: SerializerIrGenerator, property: SerializableProperty): IrExpression? {
|
fun IrBuilderWithScope.serializerTower(generator: SerializerIrGenerator, property: SerializableProperty): IrExpression? {
|
||||||
val nullableSerClass =
|
val nullableSerClass =
|
||||||
@@ -395,16 +416,17 @@ interface IrBuilderExtension {
|
|||||||
if (serializerClass.kind == ClassKind.OBJECT) {
|
if (serializerClass.kind == ClassKind.OBJECT) {
|
||||||
return irGetObject(serializerClass)
|
return irGetObject(serializerClass)
|
||||||
} else {
|
} else {
|
||||||
|
// todo: special instantiation of enum serializer according to new design
|
||||||
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
|
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
|
||||||
TODO("enum and context serializer")
|
listOf(classReference(kType))
|
||||||
else kType.arguments.map {
|
else kType.arguments.map {
|
||||||
val argSer = enclosingGenerator.findTypeSerializerOrContext(module, it.type, sourceElement = serializerClass.findPsi())
|
val argSer = enclosingGenerator.findTypeSerializerOrContext(module, it.type, sourceElement = serializerClass.findPsi())
|
||||||
val expr = serializerInstance(enclosingGenerator, serializableDescriptor, argSer, module, it.type, it.type.genericIndex)
|
val expr = serializerInstance(enclosingGenerator, serializableDescriptor, argSer, module, it.type, it.type.genericIndex)
|
||||||
?: return null
|
?: return null
|
||||||
// todo: smth better than constructors[0] ??
|
|
||||||
if (it.type.isMarkedNullable) irInvoke(null, nullableSerClass.constructors.toList()[0], expr) else expr
|
if (it.type.isMarkedNullable) irInvoke(null, nullableSerClass.constructors.toList()[0], expr) else expr
|
||||||
}
|
}
|
||||||
if (serializerClass.classId == referenceArraySerializerId) TODO("reference array serializer")
|
if (serializerClass.classId == referenceArraySerializerId)
|
||||||
|
args = listOf(classReference(kType.arguments[0].type)) + args
|
||||||
val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
|
val serializable = getSerializableClassDescriptorBySerializer(serializerClass)
|
||||||
val ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
|
val ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
|
||||||
requireNotNull(
|
requireNotNull(
|
||||||
|
|||||||
-1
@@ -90,7 +90,6 @@ class SerializableIrGenerator(
|
|||||||
+irIfThenElse(compilerContext.irBuiltIns.unitType, propNotSeenTest, ifNotSeenExpr, assignParamExpr)
|
+irIfThenElse(compilerContext.irBuiltIns.unitType, propNotSeenTest, ifNotSeenExpr, assignParamExpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: transient initializers and init blocks
|
|
||||||
// remaining initalizers of variables
|
// remaining initalizers of variables
|
||||||
val serialDescs = properties.serializableProperties.map { it.descriptor }.toSet()
|
val serialDescs = properties.serializableProperties.map { it.descriptor }.toSet()
|
||||||
irClass.declarations.asSequence()
|
irClass.declarations.asSequence()
|
||||||
|
|||||||
Reference in New Issue
Block a user