Support for @UseSerializers annotation
This commit is contained in:
+14
@@ -14,7 +14,10 @@ import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.isKSerializer
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.toClassDescriptor
|
||||
|
||||
abstract class AbstractSerialGenerator(val bindingContext: BindingContext, val currentDeclaration: ClassDescriptor) {
|
||||
|
||||
@@ -34,4 +37,15 @@ abstract class AbstractSerialGenerator(val bindingContext: BindingContext, val c
|
||||
currentDeclaration
|
||||
).toSet()
|
||||
}
|
||||
|
||||
val additionalSerializersInScopeOfCurrentFile: Map<KotlinType, ClassDescriptor> by lazy {
|
||||
getKClassListFromFileAnnotation(SerializationAnnotations.additionalSerializersFqName, currentDeclaration)
|
||||
.associateBy(
|
||||
{
|
||||
it.supertypes().find(::isKSerializer)?.arguments?.firstOrNull()?.type
|
||||
?: throw AssertionError("Argument for ${SerializationAnnotations.additionalSerializersFqName} does not implement KSerializer")
|
||||
},
|
||||
{ it.toClassDescriptor!! }
|
||||
)
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -49,14 +49,18 @@ open class SerialTypeInfo(
|
||||
val unit: Boolean = false
|
||||
)
|
||||
|
||||
fun AbstractSerialGenerator.findAddOnSerializer(propertyType: KotlinType): ClassDescriptor? =
|
||||
additionalSerializersInScopeOfCurrentFile[propertyType]
|
||||
|
||||
@Suppress("FunctionName", "LocalVariableName")
|
||||
fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
||||
fun SerializableInfo(serializer: ClassDescriptor?) =
|
||||
SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializer)
|
||||
|
||||
val T = property.type
|
||||
T.overridenSerializer?.toClassDescriptor?.let { return SerializableInfo(it) }
|
||||
property.serializableWith?.toClassDescriptor?.let { return SerializableInfo(it) }
|
||||
T.overridenSerializer?.toClassDescriptor?.let { return SerializableInfo(it) }
|
||||
findAddOnSerializer(T)?.let { return SerializableInfo(it) }
|
||||
return when {
|
||||
T.isTypeParameter() -> SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", null)
|
||||
T.isPrimitiveNumberType() or T.isBoolean() -> SerialTypeInfo(
|
||||
@@ -91,6 +95,7 @@ fun AbstractSerialGenerator.findTypeSerializerOrContext(
|
||||
annotations: Annotations = kType.annotations,
|
||||
sourceElement: PsiElement? = null
|
||||
): ClassDescriptor? {
|
||||
additionalSerializersInScopeOfCurrentFile[kType]?.let { return it }
|
||||
if (kType.isTypeParameter()) return null
|
||||
fun getContextualSerializer() =
|
||||
if (annotations.hasAnnotation(SerializationAnnotations.contextualFqName) || kType in contextualKClassListInCurrentFile)
|
||||
|
||||
+14
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.AbstractSerialGenerator
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerialTypeInfo
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findAddOnSerializer
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializerOrContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.DECODER_CLASS
|
||||
@@ -109,6 +110,7 @@ fun InstructionAdapter.genKOutputMethodCall(
|
||||
ownerVar,
|
||||
classCodegen.state
|
||||
)
|
||||
StackValue.coerce(propertyType, sti.type, this)
|
||||
invokeinterface(
|
||||
kOutputType.internalName,
|
||||
CallingConventions.encode + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + CallingConventions.elementPostfix,
|
||||
@@ -309,6 +311,18 @@ class JVMSerialTypeInfo(
|
||||
) : SerialTypeInfo(property, nn, serializer, unit)
|
||||
|
||||
fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty, type: Type): JVMSerialTypeInfo {
|
||||
fun SerializableInfo(serializer: ClassDescriptor?) =
|
||||
JVMSerialTypeInfo(
|
||||
property,
|
||||
Type.getType("Ljava/lang/Object;"),
|
||||
if (property.type.isMarkedNullable) "Nullable" else "",
|
||||
serializer
|
||||
)
|
||||
|
||||
property.serializableWith?.toClassDescriptor?.let { return SerializableInfo(it) }
|
||||
property.type.overridenSerializer?.toClassDescriptor?.let { return SerializableInfo(it) }
|
||||
findAddOnSerializer(property.type)?.let { return SerializableInfo(it) }
|
||||
|
||||
if (property.type.isTypeParameter()) return JVMSerialTypeInfo(
|
||||
property,
|
||||
Type.getType("Ljava/lang/Object;"),
|
||||
|
||||
+1
@@ -385,6 +385,7 @@ class SerializerCodegenImpl(
|
||||
genValidateProperty(index, ::bitMaskOff)
|
||||
ificmpeq(readLabel)
|
||||
load(propVar, propertyType)
|
||||
StackValue.coerce(propertyType, sti.type, this)
|
||||
produceCall(true)
|
||||
goTo(endL)
|
||||
visitLabel(readLabel)
|
||||
|
||||
+1
@@ -22,6 +22,7 @@ object SerializationAnnotations {
|
||||
internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo")
|
||||
|
||||
internal val contextualFqName = FqName("kotlinx.serialization.ContextualSerialization")
|
||||
internal val additionalSerializersFqName = FqName("kotlinx.serialization.UseSerializers")
|
||||
}
|
||||
|
||||
object SerialEntityNames {
|
||||
|
||||
Reference in New Issue
Block a user