Added saving SerialInfo annotations to the enum class
Resolves Kotlin/kotlinx.serialization#2121 Merge-request: KT-MR-8019 Merged-by: Sergey Shanshin <Sergey.Shanshin@jetbrains.com>
This commit is contained in:
committed by
Space Team
parent
88d140527f
commit
5e01669e23
+14
-5
@@ -58,7 +58,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
|
||||
private val enumSerializerFactoryFunc = compilerContext.enumSerializerFactoryFunc
|
||||
|
||||
private val markedEnumSerializerFactoryFunc = compilerContext.markedEnumSerializerFactoryFunc
|
||||
private val annotatedEnumSerializerFactoryFunc = compilerContext.annotatedEnumSerializerFactoryFunc
|
||||
|
||||
fun useFieldMissingOptimization(): Boolean {
|
||||
return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null
|
||||
@@ -558,9 +558,7 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
irCall(enumDescriptor.owner.findEnumValuesMethod()),
|
||||
)
|
||||
|
||||
val enumSerializerFactoryFunc = enumSerializerFactoryFunc
|
||||
val markedEnumSerializerFactoryFunc = markedEnumSerializerFactoryFunc
|
||||
if (enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null) {
|
||||
if (enumSerializerFactoryFunc != null && annotatedEnumSerializerFactoryFunc != null) {
|
||||
// runtime contains enum serializer factory functions
|
||||
val factoryFunc: IrSimpleFunctionSymbol = if (enumDescriptor.owner.isEnumWithSerialInfoAnnotation()) {
|
||||
// need to store SerialInfo annotation in descriptor
|
||||
@@ -577,13 +575,24 @@ abstract class BaseIrGenerator(private val currentClass: IrClass, final override
|
||||
createArrayOfExpression(compilerContext.irBuiltIns.annotationType, annotationsConstructors)
|
||||
}
|
||||
}
|
||||
|
||||
val classAnnotationConstructors = enumDescriptor.owner.annotations.map { a ->
|
||||
a.deepCopyWithVariables()
|
||||
}
|
||||
val classAnnotationsConstructors = copyAnnotationsFrom(classAnnotationConstructors)
|
||||
val classAnnotations = if (classAnnotationsConstructors.isEmpty()) {
|
||||
irNull()
|
||||
} else {
|
||||
createArrayOfExpression(compilerContext.irBuiltIns.annotationType, classAnnotationsConstructors)
|
||||
}
|
||||
val annotationArrayType =
|
||||
compilerContext.irBuiltIns.arrayClass.typeWith(compilerContext.irBuiltIns.annotationType.makeNullable())
|
||||
|
||||
enumArgs += createArrayOfExpression(compilerContext.irBuiltIns.stringType.makeNullable(), entriesNames)
|
||||
enumArgs += createArrayOfExpression(annotationArrayType, entriesAnnotations)
|
||||
enumArgs += classAnnotations
|
||||
|
||||
markedEnumSerializerFactoryFunc
|
||||
annotatedEnumSerializerFactoryFunc
|
||||
} else {
|
||||
enumSerializerFactoryFunc
|
||||
}
|
||||
|
||||
+6
-4
@@ -39,8 +39,8 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.kSerializerType
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.stringArrayType
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.stringType
|
||||
import org.jetbrains.kotlinx.serialization.compiler.diagnostic.VersionReader
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.contextSerializerId
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.enumSerializerId
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializersClassIds.objectSerializerId
|
||||
@@ -416,11 +416,13 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
||||
aconst(null)
|
||||
}
|
||||
checkcast(doubleAnnotationArrayType)
|
||||
// FIXME: same as fillArray above
|
||||
aconst(null)
|
||||
|
||||
invokestatic(
|
||||
enumFactoriesType.internalName,
|
||||
MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(),
|
||||
"(${stringType.descriptor}${javaEnumArray.descriptor}${stringArrayType.descriptor}${doubleAnnotationArrayType.descriptor})${kSerializerType.descriptor}",
|
||||
ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(),
|
||||
"(${stringType.descriptor}${javaEnumArray.descriptor}${stringArrayType.descriptor}${doubleAnnotationArrayType.descriptor}${annotationArrayType.descriptor})${kSerializerType.descriptor}",
|
||||
false
|
||||
)
|
||||
} else {
|
||||
@@ -543,4 +545,4 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-4
@@ -192,11 +192,11 @@ internal fun AbstractSerialGenerator.serializerInstance(
|
||||
packageScope,
|
||||
SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
)
|
||||
val markedEnumSerializerFactoryFunc = DescriptorUtils.getFunctionByNameOrNull(
|
||||
val annotatedEnumSerializerFactoryFunc = DescriptorUtils.getFunctionByNameOrNull(
|
||||
packageScope,
|
||||
SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
SerialEntityNames.ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
)
|
||||
if (enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null) {
|
||||
if (enumSerializerFactoryFunc != null && annotatedEnumSerializerFactoryFunc != null) {
|
||||
// runtime contains enum serializer factory functions
|
||||
val factoryFunc = if (enumDescriptor.isEnumWithSerialInfoAnnotation()) {
|
||||
val enumEntries = enumDescriptor.enumEntries()
|
||||
@@ -218,9 +218,24 @@ internal fun AbstractSerialGenerator.serializerInstance(
|
||||
JsArrayLiteral(annotationsConstructors)
|
||||
}
|
||||
}
|
||||
|
||||
val classAnnotationsConstructors = enumDescriptor.annotationsWithArguments().map { (annotationClass, args, _) ->
|
||||
val argExprs = args.map { arg ->
|
||||
Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
|
||||
}
|
||||
val classRef = context.translateQualifiedReference(annotationClass)
|
||||
JsNew(classRef, argExprs)
|
||||
}
|
||||
val classAnnotations = if (classAnnotationsConstructors.isEmpty()) {
|
||||
JsNullLiteral()
|
||||
} else {
|
||||
JsArrayLiteral(classAnnotationsConstructors)
|
||||
}
|
||||
|
||||
enumArgs += JsArrayLiteral(entriesNames)
|
||||
enumArgs += JsArrayLiteral(entriesAnnotations)
|
||||
markedEnumSerializerFactoryFunc
|
||||
enumArgs += classAnnotations
|
||||
annotatedEnumSerializerFactoryFunc
|
||||
} else {
|
||||
enumSerializerFactoryFunc
|
||||
}
|
||||
|
||||
+14
-3
@@ -36,12 +36,12 @@ import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENCODER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUMS_FILE
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.PLUGIN_EXCEPTIONS_FILE
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_CTOR_MARKER_NAME
|
||||
@@ -329,10 +329,21 @@ internal fun AbstractSerialGenerator.stackValueSerializerInstance(expressionCode
|
||||
}
|
||||
checkcast(doubleAnnotationArrayType)
|
||||
|
||||
val classAnnotationsTuples = classDescriptor.annotationsWithArguments()
|
||||
if (classAnnotationsTuples.isEmpty()) {
|
||||
aconst(null)
|
||||
} else {
|
||||
fillArray(annotationType, classAnnotationsTuples) { _, annotation ->
|
||||
val (annotationClass, args, consParams) = annotation
|
||||
expressionCodegen.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
|
||||
}
|
||||
}
|
||||
checkcast(annotationArrayType)
|
||||
|
||||
invokestatic(
|
||||
enumFactoriesType.internalName,
|
||||
MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(),
|
||||
"(${stringType.descriptor}${javaEnumArray.descriptor}${stringArrayType.descriptor}${doubleAnnotationArrayType.descriptor})${kSerializerType.descriptor}",
|
||||
ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME.asString(),
|
||||
"(${stringType.descriptor}${javaEnumArray.descriptor}${stringArrayType.descriptor}${doubleAnnotationArrayType.descriptor}${annotationArrayType.descriptor})${kSerializerType.descriptor}",
|
||||
false
|
||||
)
|
||||
} else {
|
||||
|
||||
+3
-3
@@ -85,10 +85,10 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
|
||||
)
|
||||
).singleOrNull()
|
||||
|
||||
internal val markedEnumSerializerFactoryFunc = baseContext.referenceFunctions(
|
||||
internal val annotatedEnumSerializerFactoryFunc = baseContext.referenceFunctions(
|
||||
CallableId(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
SerialEntityNames.ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
)
|
||||
).singleOrNull()
|
||||
|
||||
@@ -98,7 +98,7 @@ class SerializationPluginContext(baseContext: IrPluginContext, val metadataPlugi
|
||||
internal val kSerializerClass = referenceClass(SerialEntityNames.KSERIALIZER_CLASS_ID)?.owner
|
||||
|
||||
// evaluated properties
|
||||
override val runtimeHasEnumSerializerFactoryFunctions = enumSerializerFactoryFunc != null && markedEnumSerializerFactoryFunc != null
|
||||
override val runtimeHasEnumSerializerFactoryFunctions = enumSerializerFactoryFunc != null && annotatedEnumSerializerFactoryFunc != null
|
||||
|
||||
override fun referenceClassId(classId: ClassId): IrClassSymbol? = referenceClass(classId)
|
||||
}
|
||||
|
||||
+1
-4
@@ -120,16 +120,13 @@ object SerialEntityNames {
|
||||
val SINGLE_MASK_FIELD_MISSING_FUNC_NAME = Name.identifier("throwMissingFieldException")
|
||||
val ARRAY_MASK_FIELD_MISSING_FUNC_NAME = Name.identifier("throwArrayMissingFieldException")
|
||||
val ENUM_SERIALIZER_FACTORY_FUNC_NAME = Name.identifier("createSimpleEnumSerializer")
|
||||
val MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME = Name.identifier("createMarkedEnumSerializer")
|
||||
val ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME = Name.identifier("createAnnotatedEnumSerializer")
|
||||
val SINGLE_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(SINGLE_MASK_FIELD_MISSING_FUNC_NAME)
|
||||
val ARRAY_MASK_FIELD_MISSING_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ARRAY_MASK_FIELD_MISSING_FUNC_NAME)
|
||||
val CACHED_SERIALIZER_PROPERTY_NAME = Name.identifier(CACHED_SERIALIZER_PROPERTY)
|
||||
val CACHED_CHILD_SERIALIZERS_PROPERTY_NAME = Name.identifier(CACHED_CHILD_SERIALIZERS_PROPERTY)
|
||||
val CACHED_DESCRIPTOR_FIELD_NAME = Name.identifier(CACHED_DESCRIPTOR_FIELD)
|
||||
|
||||
val ENUM_SERIALIZER_FACTORY_FUNC_FQ = SerializationPackages.internalPackageFqName.child(ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||
val MARKED_ENUM_SERIALIZER_FACTORY_FUNC_FQ = SerializationPackages.internalPackageFqName.child(MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||
|
||||
// parameters
|
||||
val dummyParamName = Name.identifier("serializationConstructorMarker")
|
||||
const val typeArgPrefix = "typeSerial"
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.types.typeUtil.representativeUpperBound
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.inheritableSerialInfoFqName
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.metaSerializableAnnotationFqName
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName
|
||||
@@ -141,7 +141,7 @@ val ClassDescriptor.shouldHaveGeneratedSerializer: Boolean
|
||||
val ClassDescriptor.useGeneratedEnumSerializer: Boolean
|
||||
get() {
|
||||
val functions = module.getPackage(SerializationPackages.internalPackageFqName).memberScope.getFunctionNames()
|
||||
return !functions.contains(ENUM_SERIALIZER_FACTORY_FUNC_NAME) || !functions.contains(MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||
return !functions.contains(ENUM_SERIALIZER_FACTORY_FUNC_NAME) || !functions.contains(ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||
}
|
||||
|
||||
fun ClassDescriptor.enumEntries(): List<ClassDescriptor> {
|
||||
|
||||
+3
-3
@@ -49,11 +49,11 @@ class SerializationFirResolveExtension(session: FirSession) : FirDeclarationGene
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
).isNotEmpty()
|
||||
val hasMarkedFactory = session.symbolProvider.getTopLevelCallableSymbols(
|
||||
val hasAnnotatedFactory = session.symbolProvider.getTopLevelCallableSymbols(
|
||||
SerializationPackages.internalPackageFqName,
|
||||
SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
SerialEntityNames.ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
).isNotEmpty()
|
||||
hasFactory && hasMarkedFactory
|
||||
hasFactory && hasAnnotatedFactory
|
||||
}
|
||||
|
||||
override fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>): Set<Name> {
|
||||
|
||||
+4
-4
@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages
|
||||
|
||||
class DependencySerializationInfoProvider(session: FirSession) : FirExtensionSessionComponent(session) {
|
||||
@@ -24,10 +24,10 @@ class DependencySerializationInfoProvider(session: FirSession) : FirExtensionSes
|
||||
val enumSerializerFactory = session.symbolProvider
|
||||
.getTopLevelFunctionSymbols(SerializationPackages.internalPackageFqName, ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||
|
||||
val markedEnumSerializerFactory = session.symbolProvider
|
||||
.getTopLevelFunctionSymbols(SerializationPackages.internalPackageFqName, MARKED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||
val annotatedEnumSerializerFactory = session.symbolProvider
|
||||
.getTopLevelFunctionSymbols(SerializationPackages.internalPackageFqName, ANNOTATED_ENUM_SERIALIZER_FACTORY_FUNC_NAME)
|
||||
|
||||
enumSerializerFactory.isEmpty() || markedEnumSerializerFactory.isEmpty()
|
||||
enumSerializerFactory.isEmpty() || annotatedEnumSerializerFactory.isEmpty()
|
||||
}
|
||||
|
||||
private val classesFromSerializationPackageCache: FirCache<Name, FirClassSymbol<*>, Nothing?> = session.firCachesFactory.createCache { name ->
|
||||
|
||||
Reference in New Issue
Block a user