Add .serializer() to enum companion and object with custom serializer

Fixes Kotlin/kotlinx.serialization#1386
This commit is contained in:
Sergey Shanshin
2021-05-26 16:07:59 +03:00
committed by GitHub
parent f431b4b171
commit 16dbafced1
6 changed files with 21 additions and 17 deletions
@@ -43,7 +43,7 @@ fun AbstractSerialGenerator.findAddOnSerializer(propertyType: KotlinType, module
return null
}
fun KotlinType.isSerializableObject() =
fun KotlinType.isGeneratedSerializableObject() =
toClassDescriptor?.run { kind == ClassKind.OBJECT && hasSerializableAnnotationWithoutArgs } == true
@Suppress("FunctionName", "LocalVariableName")
@@ -151,7 +151,7 @@ fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescri
if (userOverride != null) return userOverride.toClassDescriptor
if (kType.isTypeParameter()) return null
if (KotlinBuiltIns.isArray(kType)) return module.getClassFromInternalSerializationPackage(SpecialBuiltins.referenceArraySerializer)
if (kType.isSerializableObject()) return module.getClassFromInternalSerializationPackage(SpecialBuiltins.objectSerializer)
if (kType.isGeneratedSerializableObject()) return module.getClassFromInternalSerializationPackage(SpecialBuiltins.objectSerializer)
val stdSer = findStandardKotlinTypeSerializer(module, kType) // see if there is a standard serializer
?: findEnumTypeSerializer(module, kType)
if (stdSer != null) return stdSer
@@ -216,7 +216,7 @@ fun findStandardKotlinTypeSerializer(module: ModuleDescriptor, kType: KotlinType
fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
val classDescriptor = kType.toClassDescriptor ?: return null
return if (classDescriptor.kind == ClassKind.ENUM_CLASS && !classDescriptor.isSerializableEnum())
return if (classDescriptor.kind == ClassKind.ENUM_CLASS && !classDescriptor.isInternallySerializableEnum())
module.findClassAcrossModuleDependencies(enumSerializerId)
else null
}
@@ -572,7 +572,7 @@ open class SerializerIrGenerator(
) {
val serializableDesc = getSerializableClassDescriptorBySerializer(irClass.symbol.descriptor) ?: return
val generator = when {
serializableDesc.isSerializableEnum() -> SerializerForEnumsGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
serializableDesc.isInternallySerializableEnum() -> SerializerForEnumsGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
serializableDesc.isInlineClass() -> SerializerForInlineClassGenerator(irClass, context, bindingContext, serialInfoJvmGenerator)
else -> SerializerIrGenerator(irClass, context, bindingContext, metadataPlugin, serialInfoJvmGenerator)
}
@@ -373,11 +373,11 @@ open class SerializerJsTranslator(
metadataPlugin: SerializationDescriptorSerializerPlugin?
) {
val serializableDesc = getSerializableClassDescriptorBySerializer(descriptor) ?: return
if (serializableDesc.isSerializableEnum()) {
if (serializableDesc.isInternallySerializableEnum()) {
SerializerForEnumsTranslator(descriptor, translator, context).generate()
} else {
SerializerJsTranslator(descriptor, translator, context, metadataPlugin).generate()
}
}
}
}
}
@@ -38,7 +38,7 @@ open class SerializerCodegenImpl(
companion object {
fun generateSerializerExtensions(codegen: ImplementationBodyCodegen, metadataPlugin: SerializationDescriptorSerializerPlugin?) {
val serializableClass = getSerializableClassDescriptorBySerializer(codegen.descriptor) ?: return
val serializerCodegen = if (serializableClass.isSerializableEnum()) {
val serializerCodegen = if (serializableClass.isInternallySerializableEnum()) {
SerializerForEnumsCodegen(codegen, serializableClass)
} else {
SerializerCodegenImpl(codegen, serializableClass, metadataPlugin)
@@ -97,9 +97,12 @@ val KotlinType?.toClassDescriptor: ClassDescriptor?
}
internal val ClassDescriptor.shouldHaveGeneratedMethodsInCompanion: Boolean
get() = this.isSerializableObject || this.isSerializableEnum() || this.kind == ClassKind.CLASS && annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)
get() = this.isSerializableObject || this.isSerializableEnum() || this.kind == ClassKind.CLASS && hasSerializableAnnotation
internal val ClassDescriptor.isSerializableObject: Boolean
get() = kind == ClassKind.OBJECT && hasSerializableAnnotation
internal val ClassDescriptor.isInternallySerializableObject: Boolean
get() = kind == ClassKind.OBJECT && hasSerializableAnnotationWithoutArgs
internal val ClassDescriptor.isInternalSerializable: Boolean //todo normal checking
@@ -108,14 +111,12 @@ internal val ClassDescriptor.isInternalSerializable: Boolean //todo normal check
return hasSerializableAnnotationWithoutArgs
}
internal fun ClassDescriptor.isSerializableEnum(): Boolean {
if (this.kind != ClassKind.ENUM_CLASS) return false
if (hasSerializableAnnotationWithoutArgs) return true
return false
}
internal fun ClassDescriptor.isSerializableEnum(): Boolean = kind == ClassKind.ENUM_CLASS && hasSerializableAnnotation
internal fun ClassDescriptor.isInternallySerializableEnum(): Boolean = kind == ClassKind.ENUM_CLASS && hasSerializableAnnotationWithoutArgs
internal val ClassDescriptor.shouldHaveGeneratedSerializer: Boolean
get() = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN)) || isSerializableEnum()
get() = (isInternalSerializable && (modality == Modality.FINAL || modality == Modality.OPEN)) || isInternallySerializableEnum()
internal fun ClassDescriptor.enumEntries(): List<ClassDescriptor> {
check(this.kind == ClassKind.ENUM_CLASS)
@@ -128,9 +129,12 @@ internal fun ClassDescriptor.enumEntries(): List<ClassDescriptor> {
internal val Annotations.hasAnySerialAnnotation: Boolean
get() = serialNameValue != null || any { it.annotationClass?.isSerialInfoAnnotation == true }
private val ClassDescriptor.hasSerializableAnnotation
get() = annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)
internal val ClassDescriptor.hasSerializableAnnotationWithoutArgs: Boolean
get() {
if (!annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)) return false
if (!hasSerializableAnnotation) return false
// If provided descriptor is lazy, carefully look at psi in order not to trigger full resolve which may be recursive.
// Otherwise, this descriptor is deserialized from another module and it is OK to check value right away.
val psi = findSerializableAnnotationDeclaration() ?: return (serializableWith == null)
@@ -178,7 +182,7 @@ internal val ClassDescriptor?.classSerializer: ClassDescriptor?
}
internal val ClassDescriptor.hasCompanionObjectAsSerializer: Boolean
get() = isSerializableObject || companionObjectDescriptor?.serializerForClass == this.defaultType
get() = isInternallySerializableObject || companionObjectDescriptor?.serializerForClass == this.defaultType
// returns only user-overriden Serializer
internal val KotlinType.overridenSerializer: KotlinType?
@@ -68,7 +68,7 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
.let { unsort(serializableClass, it) }
isExternallySerializable =
serializableClass.isSerializableEnum() || primaryConstructorParameters.size == primaryConstructorProperties.size
serializableClass.isInternallySerializableEnum() || primaryConstructorParameters.size == primaryConstructorProperties.size
}