Do not enable PolymorphicSerializer without special annotation
This commit is contained in:
+18
-17
@@ -91,6 +91,22 @@ fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty): S
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns class descriptor for ContextSerializer or PolymorphicSerializer
|
||||
* if [annotations] contains @Contextual or @Polymorphic annotation
|
||||
*/
|
||||
fun analyzeSpecialSerializers(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
annotations: Annotations
|
||||
): ClassDescriptor? = when {
|
||||
annotations.hasAnnotation(SerializationAnnotations.contextualFqName) ->
|
||||
moduleDescriptor.getClassFromSerializationPackage(SpecialBuiltins.contextSerializer)
|
||||
// can be annotation on type usage, e.g. List<@Polymorphic Any>
|
||||
annotations.hasAnnotation(SerializationAnnotations.polymorphicFqName) ->
|
||||
moduleDescriptor.getClassFromSerializationPackage(SpecialBuiltins.polymorphicSerializer)
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun AbstractSerialGenerator.findTypeSerializerOrContext(
|
||||
module: ModuleDescriptor,
|
||||
kType: KotlinType,
|
||||
@@ -100,12 +116,8 @@ fun AbstractSerialGenerator.findTypeSerializerOrContext(
|
||||
if (kType.isTypeParameter()) return null
|
||||
if (kType.isMarkedNullable) return findTypeSerializerOrContext(module, kType.makeNotNullable(), annotations, sourceElement)
|
||||
additionalSerializersInScopeOfCurrentFile[kType]?.let { return it }
|
||||
fun getContextualSerializer() =
|
||||
if (annotations.hasAnnotation(SerializationAnnotations.contextualFqName) || kType in contextualKClassListInCurrentFile)
|
||||
module.getClassFromSerializationPackage(SpecialBuiltins.contextSerializer)
|
||||
else
|
||||
null
|
||||
return getContextualSerializer() ?: findTypeSerializer(module, kType) ?: throw CompilationException(
|
||||
if (kType in contextualKClassListInCurrentFile) return module.getClassFromSerializationPackage(SpecialBuiltins.contextSerializer)
|
||||
return analyzeSpecialSerializers(module, annotations) ?: findTypeSerializer(module, kType) ?: throw CompilationException(
|
||||
"Serializer for element of type $kType has not been found.\n" +
|
||||
"To use context serializer as fallback, explicitly annotate element with @ContextualSerialization",
|
||||
null,
|
||||
@@ -116,7 +128,6 @@ fun AbstractSerialGenerator.findTypeSerializerOrContext(
|
||||
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
||||
val userOverride = kType.overridenSerializer
|
||||
if (userOverride != null) return userOverride.toClassDescriptor
|
||||
if (kType.requiresPolymorphism()) return findPolymorphicSerializer(module)
|
||||
if (kType.isTypeParameter()) return null
|
||||
if (KotlinBuiltIns.isArray(kType)) return module.getClassFromInternalSerializationPackage(SpecialBuiltins.referenceArraySerializer)
|
||||
return kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
|
||||
@@ -170,16 +181,6 @@ fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDe
|
||||
return if (classDescriptor.kind == ClassKind.ENUM_CLASS) module.findClassAcrossModuleDependencies(enumSerializerId) else null
|
||||
}
|
||||
|
||||
fun KotlinType.requiresPolymorphism(): Boolean {
|
||||
return this.toClassDescriptor?.getSuperClassNotAny()?.isInternalSerializable == true
|
||||
|| (this.toClassDescriptor?.modality != Modality.FINAL && this.toClassDescriptor?.unsubstitutedPrimaryConstructor != null) // open not java class
|
||||
|| this.containsTypeProjectionsInTopLevelArguments() // List<*>
|
||||
}
|
||||
|
||||
fun findPolymorphicSerializer(module: ModuleDescriptor): ClassDescriptor {
|
||||
return requireNotNull(module.findClassAcrossModuleDependencies(polymorphicSerializerId)) { "Can't locate polymorphic serializer definition" }
|
||||
}
|
||||
|
||||
fun KtPureClassOrObject.bodyPropertiesDescriptorsMap(bindingContext: BindingContext): Map<PropertyDescriptor, KtProperty> = declarations
|
||||
.asSequence()
|
||||
.filterIsInstance<KtProperty>()
|
||||
|
||||
+1
@@ -22,6 +22,7 @@ object SerializationAnnotations {
|
||||
internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo")
|
||||
|
||||
internal val contextualFqName = FqName("kotlinx.serialization.ContextualSerialization")
|
||||
internal val polymorphicFqName = FqName("kotlinx.serialization.Polymorphic")
|
||||
internal val additionalSerializersFqName = FqName("kotlinx.serialization.UseSerializers")
|
||||
}
|
||||
|
||||
|
||||
+2
-10
@@ -19,13 +19,12 @@ package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.psi.KtDeclarationWithInitializer
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.analyzeSpecialSerializers
|
||||
|
||||
class SerializableProperty(
|
||||
val descriptor: PropertyDescriptor,
|
||||
@@ -36,18 +35,11 @@ class SerializableProperty(
|
||||
val type = descriptor.type
|
||||
val genericIndex = type.genericIndex
|
||||
val module = descriptor.module
|
||||
val serializableWith = extractSerializableWith(descriptor.annotations)
|
||||
val serializableWith = descriptor.serializableWith ?: analyzeSpecialSerializers(module, descriptor.annotations)?.defaultType
|
||||
val optional = !descriptor.annotations.serialRequired && descriptor.declaresDefaultValue
|
||||
val transient = descriptor.annotations.serialTransient || !hasBackingField
|
||||
val annotationsWithArguments: List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
|
||||
descriptor.annotationsWithArguments()
|
||||
|
||||
private fun extractSerializableWith(annotations: Annotations): KotlinType? {
|
||||
descriptor.serializableWith?.let { return it }
|
||||
return if (annotations.hasAnnotation(SerializationAnnotations.contextualFqName))
|
||||
module.getClassFromSerializationPackage(SpecialBuiltins.contextSerializer).defaultType
|
||||
else null
|
||||
}
|
||||
}
|
||||
|
||||
val PropertyDescriptor.declaresDefaultValue: Boolean
|
||||
|
||||
Reference in New Issue
Block a user