Skip to content

Commit

Permalink
Added saving SerialInfo annotations to the enum class
Browse files Browse the repository at this point in the history
  • Loading branch information
shanshin committed Dec 17, 2022
1 parent 0e4e537 commit c2e33d2
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -543,4 +545,4 @@ class SerializationJvmIrIntrinsicSupport(val jvmBackendContext: JvmBackendContex
}
return true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ 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) {
val useGeneratedEnumSerializer by session.firCachesFactory.createLazyValue {
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 ->
Expand Down

0 comments on commit c2e33d2

Please sign in to comment.