Fix for Kotlin/kotlinx.serialization/118
Fix for Kotlin/kotlinx.serialization/123: resolve annotation parameters in-place Fix for Kotlin/kotlinx.serialization/125 Now polymorphic serializer required by all modalities expect final
This commit is contained in:
+5
-11
@@ -75,9 +75,10 @@ fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescriptor? {
|
||||||
return if (kType.requiresPolymorphism()) findPolymorphicSerializer(module)
|
if (kType.requiresPolymorphism()) return findPolymorphicSerializer(module)
|
||||||
else if (kType.isTypeParameter()) return null
|
if (kType.isTypeParameter()) return null
|
||||||
else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
|
if (KotlinBuiltIns.isArray(kType)) return module.findClassAcrossModuleDependencies(referenceArraySerializerId)
|
||||||
|
return kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
|
||||||
?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer
|
?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer
|
||||||
?: findEnumTypeSerializer(module, kType)
|
?: findEnumTypeSerializer(module, kType)
|
||||||
?: module.findClassAcrossModuleDependencies(contextSerializerId)
|
?: module.findClassAcrossModuleDependencies(contextSerializerId)
|
||||||
@@ -116,7 +117,7 @@ fun findEnumTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDe
|
|||||||
|
|
||||||
fun KotlinType.requiresPolymorphism(): Boolean {
|
fun KotlinType.requiresPolymorphism(): Boolean {
|
||||||
return this.toClassDescriptor?.getSuperClassNotAny()?.isInternalSerializable == true
|
return this.toClassDescriptor?.getSuperClassNotAny()?.isInternalSerializable == true
|
||||||
|| (this.toClassDescriptor?.modality == Modality.OPEN && this.toClassDescriptor?.unsubstitutedPrimaryConstructor != null) // open not java class
|
|| (this.toClassDescriptor?.modality != Modality.FINAL && this.toClassDescriptor?.unsubstitutedPrimaryConstructor != null) // open not java class
|
||||||
|| this.containsTypeProjectionsInTopLevelArguments() // List<*>
|
|| this.containsTypeProjectionsInTopLevelArguments() // List<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,10 +143,3 @@ fun KtPureClassOrObject.anonymousInitializers() = declarations
|
|||||||
.filterIsInstance<KtAnonymousInitializer>()
|
.filterIsInstance<KtAnonymousInitializer>()
|
||||||
.mapNotNull { it.body }
|
.mapNotNull { it.body }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
fun SerializableProperty.annotationVarsAndDesc(annotationClass: ClassDescriptor): Pair<List<ValueArgument>, List<ValueParameterDescriptor>> {
|
|
||||||
val args: List<ValueArgument> = (this.descriptor.annotations.findAnnotation(annotationClass.fqNameSafe) as? LazyAnnotationDescriptor)?.annotationEntry?.valueArguments.orEmpty()
|
|
||||||
val consParams = annotationClass.unsubstitutedPrimaryConstructor?.valueParameters.orEmpty()
|
|
||||||
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
|
|
||||||
return args to consParams
|
|
||||||
}
|
|
||||||
+1
-3
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
|
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerializerId
|
||||||
@@ -75,8 +74,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
|
|||||||
val call = JsInvocation(JsNameRef(context.getNameForDescriptor(addFunc), serialClassDescRef), JsStringLiteral(prop.name))
|
val call = JsInvocation(JsNameRef(context.getNameForDescriptor(addFunc), serialClassDescRef), JsStringLiteral(prop.name))
|
||||||
translator.addInitializerStatement(call.makeStmt())
|
translator.addInitializerStatement(call.makeStmt())
|
||||||
// serialDesc.pushAnnotation(...)
|
// serialDesc.pushAnnotation(...)
|
||||||
for (annotationClass in prop.annotations) {
|
for ((annotationClass , args, _) in prop.annotationsWithArguments) {
|
||||||
val (args, _) = prop.annotationVarsAndDesc(annotationClass)
|
|
||||||
val argExprs = args.map { arg ->
|
val argExprs = args.map { arg ->
|
||||||
Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
|
Translation.translateAsExpression(arg.getArgumentExpression()!!, context)
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-5
@@ -252,11 +252,12 @@ fun getSerialTypeInfo(property: SerializableProperty, type: Type): JVMSerialType
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType, asmType: Type): ClassDescriptor? {
|
fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType, asmType: Type): ClassDescriptor? {
|
||||||
return if (kType.requiresPolymorphism()) findPolymorphicSerializer(module)
|
if (kType.requiresPolymorphism()) return findPolymorphicSerializer(module)
|
||||||
else kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
|
if (KotlinBuiltIns.isArray(kType)) return module.findClassAcrossModuleDependencies(referenceArraySerializerId)
|
||||||
?: findStandardAsmTypeSerializer(module, asmType) // otherwise see if there is a standard serializer
|
return kType.typeSerializer.toClassDescriptor // check for serializer defined on the type
|
||||||
?: findEnumTypeSerializer(module, kType)
|
?: findStandardAsmTypeSerializer(module, asmType) // otherwise see if there is a standard serializer
|
||||||
?: module.findClassAcrossModuleDependencies(contextSerializerId)
|
?: findEnumTypeSerializer(module, kType)
|
||||||
|
?: module.findClassAcrossModuleDependencies(contextSerializerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findStandardAsmTypeSerializer(module: ModuleDescriptor, asmType: Type): ClassDescriptor? {
|
fun findStandardAsmTypeSerializer(module: ModuleDescriptor, asmType: Type): ClassDescriptor? {
|
||||||
|
|||||||
+1
-3
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.annotationVarsAndDesc
|
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix
|
||||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
|
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
|
||||||
@@ -89,14 +88,13 @@ class SerializerCodegenImpl(
|
|||||||
aconst(property.name)
|
aconst(property.name)
|
||||||
invokevirtual(descImplType.internalName, "addElement", "(Ljava/lang/String;)V", false)
|
invokevirtual(descImplType.internalName, "addElement", "(Ljava/lang/String;)V", false)
|
||||||
// pushing annotations
|
// pushing annotations
|
||||||
for (annotationClass in property.annotations) {
|
for ((annotationClass, args, consParams) in property.annotationsWithArguments) {
|
||||||
load(classDescVar, descImplType)
|
load(classDescVar, descImplType)
|
||||||
val implType = codegen.typeMapper.mapType(annotationClass).internalName + "\$" + KSerializerDescriptorResolver.IMPL_NAME.identifier
|
val implType = codegen.typeMapper.mapType(annotationClass).internalName + "\$" + KSerializerDescriptorResolver.IMPL_NAME.identifier
|
||||||
// new Annotation$Impl(...)
|
// new Annotation$Impl(...)
|
||||||
anew(Type.getObjectType(implType))
|
anew(Type.getObjectType(implType))
|
||||||
dup()
|
dup()
|
||||||
val sb = StringBuilder("(")
|
val sb = StringBuilder("(")
|
||||||
val (args, consParams) = property.annotationVarsAndDesc(annotationClass)
|
|
||||||
for (i in consParams.indices) {
|
for (i in consParams.indices) {
|
||||||
val decl = args[i]
|
val decl = args[i]
|
||||||
val desc = consParams[i]
|
val desc = consParams[i]
|
||||||
|
|||||||
+14
-3
@@ -16,8 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
package org.jetbrains.kotlinx.serialization.compiler.resolve
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.ValueArgument
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
|
||||||
|
|
||||||
class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructorParameterWithDefault: Boolean) {
|
class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructorParameterWithDefault: Boolean) {
|
||||||
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
|
val name = descriptor.annotations.serialNameValue ?: descriptor.name.asString()
|
||||||
@@ -27,7 +31,14 @@ class SerializableProperty(val descriptor: PropertyDescriptor, val isConstructor
|
|||||||
val serializableWith = descriptor.annotations.serializableWith?.let { checkSerializerNullability(type, it) }
|
val serializableWith = descriptor.annotations.serializableWith?.let { checkSerializerNullability(type, it) }
|
||||||
val optional = descriptor.annotations.serialOptional
|
val optional = descriptor.annotations.serialOptional
|
||||||
val transient = descriptor.annotations.serialTransient
|
val transient = descriptor.annotations.serialTransient
|
||||||
val annotations = descriptor.annotations
|
val annotationsWithArguments: List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
|
||||||
.mapNotNull { it.type.toClassDescriptor }
|
descriptor.annotations.asSequence()
|
||||||
.filter { it.annotations.hasAnnotation(serialInfoFqName) }
|
.filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(serialInfoFqName) == true }
|
||||||
|
.filterIsInstance<LazyAnnotationDescriptor>()
|
||||||
|
.mapNotNull { annDesc ->
|
||||||
|
annDesc.type.toClassDescriptor?.let {
|
||||||
|
Triple(it, annDesc.annotationEntry.valueArguments, it.unsubstitutedPrimaryConstructor?.valueParameters.orEmpty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.toList()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user