diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt index b20b40da889..5d57da867e0 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.resolve.BindingContext @@ -46,7 +47,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext: override val BackendContext.localSymbolTable: SymbolTable get() = _table - private val serializableIrClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor) + private val serializableIrClass = compilerContext.externalSymbols.referenceClass(serializableDescriptor).owner override fun generateSerialDesc() { val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return @@ -97,9 +98,21 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext: for (classProp in orderedProperties) { if (classProp.transient) continue +addFieldCall(classProp.name) - // serialDesc.pushAnnotation(...) todo + // add property annotations + copySerialInfoAnnotationsToDescriptor( + classProp.irField.correspondingProperty?.annotations.orEmpty(), + irGet(localDesc), + serialDescImplClass.referenceMethod(CallingConventions.addAnnotation) + ) } + // add class annotations + copySerialInfoAnnotationsToDescriptor( + serializableIrClass.annotations, + irGet(localDesc), + serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation) + ) + // save local descriptor to field +irSetField( generateReceiverExpressionForFieldAccess( thisAsReceiverParameter.symbol, @@ -114,6 +127,17 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext: } } + private fun IrBlockBodyBuilder.copySerialInfoAnnotationsToDescriptor( + annotations: List, + receiver: IrExpression, + method: IrFunctionSymbol + ) { + annotations.forEach { annotationCall -> + if ((annotationCall.descriptor as? ClassConstructorDescriptor)?.constructedClass?.isSerialInfoAnnotation == true) + +irInvoke(receiver, method, annotationCall) + } + } + override fun generateGenericFieldsAndConstructor(typedConstructorDescriptor: ClassConstructorDescriptor) = irClass.contributeCtor(typedConstructorDescriptor) { ctor -> // generate call to primary ctor to init serialClassDesc and super() @@ -159,7 +183,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext: override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc -> val fieldInitializer: (SerializableProperty) -> IrExpression? = - buildInitializersRemapping(serializableIrClass.owner).run { { invoke(it.irField) } } + buildInitializersRemapping(serializableIrClass).run { { invoke(it.irField) } } fun irThis(): IrExpression = IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol) @@ -374,7 +398,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext: var args: List = localProps.map { it.get() } val ctor: IrConstructorSymbol = if (serializableDescriptor.isInternalSerializable) { val ctorDesc = serializableIrClass - .owner.constructors.single { it.origin == SERIALIZABLE_PLUGIN_ORIGIN } + .constructors.single { it.origin == SERIALIZABLE_PLUGIN_ORIGIN } args = listOf(irGet(bitMasks[0])) + args + irNull() ctorDesc.symbol } else { diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt index a525b4c020c..f7e51a58cc3 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS +import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.packageFqName fun isAllowedToHaveAutoGeneratedSerializerMethods(classDescriptor: ClassDescriptor): Boolean { @@ -73,6 +74,9 @@ internal val DeclarationDescriptor.serializableWith: KotlinType? internal val DeclarationDescriptor.serializerForClass: KotlinType? get() = annotations.findAnnotationKotlinTypeValue(SerializationAnnotations.serializerAnnotationFqName, module, "forClass") +internal val ClassDescriptor.isSerialInfoAnnotation: Boolean + get() = annotations.hasAnnotation(serialInfoFqName) + val Annotations.serialNameValue: String? get() { val value = findAnnotationConstantValue(SerializationAnnotations.serialNameAnnotationFqName, "value") @@ -227,7 +231,7 @@ fun ClassDescriptor.toSimpleType(nullable: Boolean = true) = KotlinTypeFactory.s fun Annotated.annotationsWithArguments(): List, List>> = annotations.asSequence() - .filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(SerializationAnnotations.serialInfoFqName) == true } + .filter { it.type.toClassDescriptor?.isSerialInfoAnnotation == true } .filterIsInstance() .mapNotNull { annDesc -> annDesc.type.toClassDescriptor?.let {