Do not insert @SerializableWith marker annotation if already present

Such situation may happen if generic class is customized by user
with object-kind serializer. In such case, both arguments from
generateSerializerGetter and generateSerializerFactory are objects.
See linked issue for details:

Fixes https://github.com/Kotlin/kotlinx.serialization/issues/749
This commit is contained in:
Leonid Startsev
2020-03-10 15:14:21 +03:00
parent e20354926b
commit 15fa6ea757
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.IrTypeProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.referenceFunction
@@ -24,6 +22,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
@@ -63,12 +62,18 @@ class SerializableCompanionIrGenerator(
Name.identifier(SerialEntityNames.ANNOTATION_MARKER_CLASS)
)
) ?: return
val irSerializableClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).takeIf { it.isBound }?.owner ?: return
val serializableWithAlreadyPresent = irSerializableClass.annotations.any {
it.symbol.descriptor.constructedClass.fqNameSafe == annotationMarkerClass.fqNameSafe
}
if (serializableWithAlreadyPresent) return
val annotationCtor = requireNotNull(annotationMarkerClass.unsubstitutedPrimaryConstructor?.let {
compilerContext.symbolTable.referenceConstructor(it)
})
val annotationType = annotationMarkerClass.defaultType.toIrType()
val irSerializableClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).owner
val annotationCtorCall = IrConstructorCallImpl.fromSymbolDescriptor(startOffset, endOffset, annotationType, annotationCtor).apply {
val serializerType = serializer.toSimpleType(false)
putValueArgument(