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:
Leonid Startsev
2018-10-11 17:53:37 +03:00
parent ef42201b05
commit f101e17dfa
2 changed files with 26 additions and 5 deletions
@@ -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.lower.createIrBuilder
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
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.util.*
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.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module
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.kotlinx.serialization.compiler.backend.common.AbstractSerialGenerator
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.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
fun IrBuilderWithScope.serializerTower(generator: SerializerIrGenerator, property: SerializableProperty): IrExpression? {
val nullableSerClass =
@@ -395,16 +416,17 @@ interface IrBuilderExtension {
if (serializerClass.kind == ClassKind.OBJECT) {
return irGetObject(serializerClass)
} else {
// todo: special instantiation of enum serializer according to new design
var args = if (serializerClass.classId == enumSerializerId || serializerClass.classId == contextSerializerId)
TODO("enum and context serializer")
listOf(classReference(kType))
else kType.arguments.map {
val argSer = enclosingGenerator.findTypeSerializerOrContext(module, it.type, sourceElement = serializerClass.findPsi())
val expr = serializerInstance(enclosingGenerator, serializableDescriptor, argSer, module, it.type, it.type.genericIndex)
?: return null
// todo: smth better than constructors[0] ??
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 ctor = if (serializable?.declaredTypeParameters?.isNotEmpty() == true) {
requireNotNull(
@@ -90,7 +90,6 @@ class SerializableIrGenerator(
+irIfThenElse(compilerContext.irBuiltIns.unitType, propNotSeenTest, ifNotSeenExpr, assignParamExpr)
}
// todo: transient initializers and init blocks
// remaining initalizers of variables
val serialDescs = properties.serializableProperties.map { it.descriptor }.toSet()
irClass.declarations.asSequence()