From f101e17dfa41604ebf5388cad98fef3614f69f25 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Thu, 11 Oct 2018 17:53:37 +0300 Subject: [PATCH] Support reference array and context serializers Enum serializers are also instantiated, but won't work on native because of lack of KClass>.enumValues() --- .../compiler/backend/ir/GeneratorHelpers.kt | 30 ++++++++++++++++--- .../backend/ir/SerializableIrGenerator.kt | 1 - 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index a1cc641dcd0..5b90ba16155 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -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( diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt index 89d77348445..79e76011ee6 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt @@ -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()