Custom-serializable enums for JVM

This commit is contained in:
Leonid Startsev
2019-06-18 20:00:16 +03:00
parent e9e7d1479a
commit e76ab06029
12 changed files with 165 additions and 49 deletions
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
@@ -30,7 +29,7 @@ abstract class SerializerCodegen(
bindingContext: BindingContext
) : AbstractSerialGenerator(bindingContext, serializerDescriptor) {
val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
protected val serialName: String = serializableDescriptor.annotations.serialNameValue ?: serializableDescriptor.fqNameUnsafe.asString()
protected val serialName: String = serializableDescriptor.serialName()
protected val properties = bindingContext.serializablePropertiesFor(serializableDescriptor)
protected val serializableProperties = properties.serializableProperties
@@ -96,7 +96,11 @@ fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty): S
fun KotlinType.serialName(): String {
val serializableDescriptor = this.toClassDescriptor!!
return serializableDescriptor.annotations.serialNameValue ?: serializableDescriptor.fqNameUnsafe.asString()
return serializableDescriptor.serialName()
}
fun ClassDescriptor.serialName(): String {
return annotations.serialNameValue ?: fqNameUnsafe.asString()
}
/**
@@ -206,7 +210,9 @@ 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) module.findClassAcrossModuleDependencies(enumSerializerId) else null
return if (classDescriptor.kind == ClassKind.ENUM_CLASS && !classDescriptor.isSerializableEnum())
module.findClassAcrossModuleDependencies(enumSerializerId)
else null
}
internal fun KtPureClassOrObject.bodyPropertiesDescriptorsMap(
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
@@ -176,7 +177,7 @@ class SerializableIrGenerator(
SerializableIrGenerator(irClass, context, bindingContext).generate()
irClass.patchDeclarationParents(irClass.parent)
}
else if (serializableClass.hasSerializableAnnotationWithoutArgs && !serializableClass.hasCompanionObjectAsSerializer) {
else if (serializableClass.serializableAnnotationIsUseless) {
throw CompilationException(
"@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " +
"Provide serializer manually via e.g. companion object", null, serializableClass.findPsi()
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
@@ -164,7 +165,7 @@ class SerializableJsTranslator(
) {
if (serializableClass.isInternalSerializable)
SerializableJsTranslator(declaration, serializableClass, context).generate()
else if (serializableClass.hasSerializableAnnotationWithoutArgs && !serializableClass.hasCompanionObjectAsSerializer) {
else if (serializableClass.serializableAnnotationIsUseless) {
throw CompilationException(
"@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " +
"Provide serializer manually via e.g. companion object", null, serializableClass.findPsi()
@@ -38,6 +38,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MI
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_CTOR_MARKER_NAME
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_FOR_ENUM
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_EXC
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_LOADER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_SAVER_CLASS
@@ -53,6 +54,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
// todo: extract packages constants too?
internal val descType = Type.getObjectType("kotlinx/serialization/$SERIAL_DESCRIPTOR_CLASS")
internal val descImplType = Type.getObjectType("kotlinx/serialization/internal/$SERIAL_DESCRIPTOR_CLASS_IMPL")
internal val descriptorForEnumsType = Type.getObjectType("kotlinx/serialization/internal/$SERIAL_DESCRIPTOR_FOR_ENUM")
internal val generatedSerializerType = Type.getObjectType("kotlinx/serialization/internal/${SerialEntityNames.GENERATED_SERIALIZER_CLASS}")
internal val kOutputType = Type.getObjectType("kotlinx/serialization/$STRUCTURE_ENCODER_CLASS")
internal val encoderType = Type.getObjectType("kotlinx/serialization/$ENCODER_CLASS")
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
@@ -45,7 +46,7 @@ class SerializableCodegenImpl(
val serializableClass = codegen.descriptor
if (serializableClass.isInternalSerializable)
SerializableCodegenImpl(codegen).generate()
else if (serializableClass.hasSerializableAnnotationWithoutArgs && !serializableClass.hasCompanionObjectAsSerializer) {
else if (serializableClass.serializableAnnotationIsUseless) {
throw CompilationException(
"@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " +
"Provide serializer manually via e.g. companion object", null, serializableClass.findPsi()
@@ -18,6 +18,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
@@ -29,16 +30,16 @@ import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class SerializerCodegenImpl(
private val codegen: ImplementationBodyCodegen,
open class SerializerCodegenImpl(
protected val codegen: ImplementationBodyCodegen,
serializableClass: ClassDescriptor
) : SerializerCodegen(codegen.descriptor, codegen.bindingContext) {
private val serialDescField = "\$\$serialDesc"
private val serializerAsmType = codegen.typeMapper.mapClass(codegen.descriptor)
private val serializableAsmType = codegen.typeMapper.mapClass(serializableClass)
protected val serializerAsmType = codegen.typeMapper.mapClass(codegen.descriptor)
protected val serializableAsmType = codegen.typeMapper.mapClass(serializableClass)
// if we have type parameters, descriptor initializing must be performed in constructor
private val staticDescriptor = serializableDescriptor.declaredTypeParameters.isEmpty()
@@ -46,7 +47,12 @@ class SerializerCodegenImpl(
companion object {
fun generateSerializerExtensions(codegen: ImplementationBodyCodegen) {
val serializableClass = getSerializableClassDescriptorBySerializer(codegen.descriptor) ?: return
SerializerCodegenImpl(codegen, serializableClass).generate()
val serializerCodegen = if (serializableClass.isSerializableEnum()) {
SerializerForEnumsCodegen(codegen, serializableClass)
} else {
SerializerCodegenImpl(codegen, serializableClass)
}
serializerCodegen.generate()
}
}
@@ -74,6 +80,23 @@ class SerializerCodegenImpl(
}
private fun ExpressionCodegen.generateSerialDescriptor(descriptorVar: Int, isStatic: Boolean) = with(v) {
instantiateNewDescriptor(isStatic)
store(descriptorVar, descImplType)
// add contents
addElementsContentToDescriptor(descriptorVar)
// add annotations on class itself
addSyntheticAnnotationsToDescriptor(descriptorVar, serializableDescriptor, CallingConventions.addClassAnnotation)
if (isStatic) {
load(descriptorVar, descImplType)
putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
} else {
load(0, serializerAsmType)
load(descriptorVar, descImplType)
putfield(serializerAsmType.internalName, serialDescField, descType.descriptor)
}
}
protected open fun ExpressionCodegen.instantiateNewDescriptor(isStatic: Boolean) = with(v) {
anew(descImplType)
dup()
aconst(serialName)
@@ -88,7 +111,9 @@ class SerializerCodegenImpl(
load(0, serializerAsmType)
}
invokespecial(descImplType.internalName, "<init>", "(Ljava/lang/String;${generatedSerializerType.descriptor})V", false)
store(descriptorVar, descImplType)
}
protected open fun ExpressionCodegen.addElementsContentToDescriptor(descriptorVar: Int) = with(v) {
for (property in serializableProperties) {
if (property.transient) continue
load(descriptorVar, descImplType)
@@ -96,39 +121,24 @@ class SerializerCodegenImpl(
iconst(if (property.optional) 1 else 0)
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;Z)V", false)
// pushing annotations
for ((annotationClass, args, consParams) in property.annotationsWithArguments) {
addSyntheticAnnotationsToDescriptor(descriptorVar, property.descriptor, CallingConventions.addAnnotation)
}
}
protected fun ExpressionCodegen.addSyntheticAnnotationsToDescriptor(descriptorVar: Int, annotated: Annotated, functionToCall: String) =
with(v) {
for ((annotationClass, args, consParams) in annotated.annotationsWithArguments()) {
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
load(descriptorVar, descImplType)
generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
invokevirtual(
descImplType.internalName,
CallingConventions.addAnnotation,
functionToCall,
"(Ljava/lang/annotation/Annotation;)V",
false
)
}
}
// add annotations on class itself
for ((annotationClass, args, consParams) in serializableDescriptor.annotationsWithArguments()) {
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
load(descriptorVar, descImplType)
generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
invokevirtual(
descImplType.internalName,
CallingConventions.addClassAnnotation,
"(Ljava/lang/annotation/Annotation;)V",
false
)
}
if (isStatic) {
load(descriptorVar, descImplType)
putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
} else {
load(0, serializerAsmType)
load(descriptorVar, descImplType)
putfield(serializerAsmType.internalName, serialDescField, descType.descriptor)
}
}
override fun generateSerialDesc() {
var flags = ACC_PRIVATE or ACC_FINAL or ACC_SYNTHETIC
@@ -168,7 +178,7 @@ class SerializerCodegenImpl(
}
// use null to put value on stack, use number to store it to var
private fun InstructionAdapter.stackSerialClassDesc(classDescVar: Int?) {
protected fun InstructionAdapter.stackSerialClassDesc(classDescVar: Int?) {
if (staticDescriptor)
getstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
else {
@@ -0,0 +1,65 @@
package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlinx.serialization.compiler.resolve.CallingConventions
import org.jetbrains.kotlinx.serialization.compiler.resolve.enumEntries
import org.jetbrains.kotlinx.serialization.compiler.resolve.serialNameValue
import org.jetbrains.org.objectweb.asm.Type
class SerializerForEnumsCodegen(
codegen: ImplementationBodyCodegen,
serializableClass: ClassDescriptor
) : SerializerCodegenImpl(codegen, serializableClass) {
override fun generateSave(function: FunctionDescriptor) = codegen.generateMethod(function) { _, _ ->
// fun save(output: KOutput, obj : T)
val outputVar = 1
val objVar = 2
// output.encodeEnum(descriptor, ordinal)
load(outputVar, encoderType)
stackSerialClassDesc(null)
load(objVar, serializableAsmType)
invokevirtual(serializableAsmType.internalName, "ordinal", "()I", false)
invokeinterface(encoderType.internalName, "encodeEnum", "(${descType.descriptor}I)V")
// return
areturn(Type.VOID_TYPE)
}
override fun generateLoad(function: FunctionDescriptor) = codegen.generateMethod(function) { _, _ ->
// fun load(input: KInput): T
val inputVar = 1
val serializableArrayType = Type.getType("[L${serializableAsmType.internalName};")
// T.values()
invokestatic(serializableAsmType.internalName, "values", "()${serializableArrayType.descriptor}", false)
// input.decodeEnum(descriptor)
load(inputVar, decoderType)
stackSerialClassDesc(null)
invokeinterface(decoderType.internalName, "decodeEnum", "(${descType.descriptor})I")
// return
aload(serializableAsmType)
areturn(serializableAsmType)
}
override fun ExpressionCodegen.instantiateNewDescriptor(isStatic: Boolean) = with(v) {
anew(descriptorForEnumsType)
dup()
aconst(serialName)
invokespecial(descriptorForEnumsType.internalName, "<init>", "(Ljava/lang/String;)V", false)
checkcast(descImplType)
}
override fun ExpressionCodegen.addElementsContentToDescriptor(descriptorVar: Int) = with(v) {
val enumEntries = serializableDescriptor.enumEntries()
for (entry in enumEntries) {
load(descriptorVar, descImplType)
// regular .serialName() produces fqName here, which is kinda inconvenient for enum entry
val serialName = entry.annotations.serialNameValue ?: entry.name.toString()
aconst(serialName)
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;)V", false)
// pushing annotations
addSyntheticAnnotationsToDescriptor(descriptorVar, entry, CallingConventions.addAnnotation)
}
}
}
@@ -58,16 +58,18 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
}
if (!descriptor.hasSerializableAnnotationWithoutArgs) return false
if (!descriptor.isInternalSerializable && !descriptor.hasCompanionObjectAsSerializer) {
if (descriptor.serializableAnnotationIsUseless) {
trace.reportOnSerializableAnnotation(descriptor, SerializationErrors.SERIALIZABLE_ANNOTATION_IGNORED)
return false
}
// check that we can instantiate supertype
val superClass = descriptor.getSuperClassOrAny()
if (!superClass.isInternalSerializable && superClass.constructors.singleOrNull { it.valueParameters.size == 0 } == null) {
trace.reportOnSerializableAnnotation(descriptor, SerializationErrors.NON_SERIALIZABLE_PARENT_MUST_HAVE_NOARG_CTOR)
return false
if (!descriptor.isSerializableEnum()) { // enums are inherited from java.lang.Enum and can't be inherited from other classes
val superClass = descriptor.getSuperClassOrAny()
if (!superClass.isInternalSerializable && superClass.constructors.singleOrNull { it.valueParameters.size == 0 } == null) {
trace.reportOnSerializableAnnotation(descriptor, SerializationErrors.NON_SERIALIZABLE_PARENT_MUST_HAVE_NOARG_CTOR)
return false
}
}
return true
}
@@ -232,3 +234,6 @@ open class SerializationPluginDeclarationChecker : DeclarationChecker {
}
}
}
internal val ClassDescriptor.serializableAnnotationIsUseless: Boolean
get() = hasSerializableAnnotationWithoutArgs && !isInternalSerializable && !hasCompanionObjectAsSerializer && !isSerializableEnum()
@@ -18,7 +18,6 @@ package org.jetbrains.kotlinx.serialization.compiler.extensions
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.name.Name
@@ -38,7 +37,7 @@ import java.util.*
open class SerializationResolveExtension : SyntheticResolveExtension {
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> = when {
thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && thisDescriptor.platform?.isJvm() == true -> listOf(SerialEntityNames.IMPL_NAME)
thisDescriptor.isInternalSerializable && !thisDescriptor.hasCompanionObjectAsSerializer ->
(thisDescriptor.shouldHaveGeneratedSerializer) && !thisDescriptor.hasCompanionObjectAsSerializer ->
listOf(SerialEntityNames.SERIALIZER_CLASS_NAME)
else -> listOf()
}
@@ -58,7 +57,7 @@ open class SerializationResolveExtension : SyntheticResolveExtension {
) {
if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && name == SerialEntityNames.IMPL_NAME)
result.add(KSerializerDescriptorResolver.addSerialInfoImplClass(thisDescriptor, declarationProvider, ctx))
else if (thisDescriptor.isInternalSerializable && name == SerialEntityNames.SERIALIZER_CLASS_NAME &&
else if (thisDescriptor.shouldHaveGeneratedSerializer && name == SerialEntityNames.SERIALIZER_CLASS_NAME &&
result.none { it.name == SerialEntityNames.SERIALIZER_CLASS_NAME }
)
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
@@ -66,7 +65,7 @@ open class SerializationResolveExtension : SyntheticResolveExtension {
}
override fun getSyntheticCompanionObjectNameIfNeeded(thisDescriptor: ClassDescriptor): Name? =
if (thisDescriptor.kind == ClassKind.CLASS && thisDescriptor.annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName))
if (thisDescriptor.shouldHaveGeneratedMethodsInCompanion && !thisDescriptor.isSerializableObject)
SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
else null
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
@@ -37,6 +38,7 @@ internal fun isAllowedToHaveAutoGeneratedSerializerMethods(
classDescriptor: ClassDescriptor,
serializableClassDescriptor: ClassDescriptor
): Boolean {
if (serializableClassDescriptor.isSerializableEnum()) return true
// don't generate automatically anything for enums or interfaces or other strange things
if (serializableClassDescriptor.kind != ClassKind.CLASS) return false
// it is either GeneratedSerializer implementation
@@ -105,7 +107,7 @@ val KotlinType?.toClassDescriptor: ClassDescriptor?
}
internal val ClassDescriptor.shouldHaveGeneratedMethodsInCompanion: Boolean
get() = this.isSerializableObject || this.kind == ClassKind.CLASS && annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)
get() = this.isSerializableObject || this.isSerializableEnum() || this.kind == ClassKind.CLASS && annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)
internal val ClassDescriptor.isSerializableObject: Boolean
get() = kind == ClassKind.OBJECT && hasSerializableAnnotationWithoutArgs
@@ -116,6 +118,30 @@ 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
if (annotations.hasAnySerialAnnotation) return true
// check entries
for (enumEntry in enumEntries()) {
if (enumEntry.annotations.hasAnySerialAnnotation) return true
}
return false
}
internal val ClassDescriptor.shouldHaveGeneratedSerializer: Boolean get() = isInternalSerializable || isSerializableEnum()
internal fun ClassDescriptor.enumEntries(): List<ClassDescriptor> {
check(this.kind == ClassKind.ENUM_CLASS)
return unsubstitutedMemberScope.getContributedDescriptors().asSequence()
.filterIsInstance<ClassDescriptor>()
.filter { it.kind == ClassKind.ENUM_ENTRY }
.toList()
}
private val Annotations.hasAnySerialAnnotation: Boolean
get() = serialNameValue != null || any { it.annotationClass?.isSerialInfoAnnotation == true }
internal val ClassDescriptor.hasSerializableAnnotationWithoutArgs: Boolean
get() {
if (!annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)) return false
@@ -152,7 +178,7 @@ internal val ClassDescriptor?.classSerializer: ClassDescriptor?
// can infer @Poly?
polymorphicSerializerIfApplicableAutomatically()?.let { return it }
// default serializable?
if (isInternalSerializable) {
if (shouldHaveGeneratedSerializer) {
// $serializer nested class
return this.unsubstitutedMemberScope
.getDescriptorsFiltered(nameFilter = { it == SerialEntityNames.SERIALIZER_CLASS_NAME })
@@ -194,7 +220,7 @@ internal fun getSerializableClassDescriptorBySerializer(serializerDescriptor: Cl
)
) return null
val classDescriptor = (serializerDescriptor.containingDeclaration as? ClassDescriptor) ?: return null
if (!classDescriptor.isInternalSerializable) return null
if (!classDescriptor.shouldHaveGeneratedSerializer) return null
return classDescriptor
}
@@ -55,6 +55,7 @@ object SerialEntityNames {
const val SERIAL_DESCRIPTOR_CLASS = "SerialDescriptor"
const val SERIAL_DESCRIPTOR_CLASS_IMPL = "SerialClassDescImpl"
const val SERIAL_DESCRIPTOR_FOR_ENUM = "EnumDescriptor"
//exceptions
const val SERIAL_EXC = "SerializationException"