Respect @ContextualSerialization on file
Add common ancestor to all serializable generators
This commit is contained in:
committed by
Leonid Startsev
parent
82fa152514
commit
f0e81c6eb8
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlinx.serialization.compiler.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.constants.KClassValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations
|
||||
|
||||
abstract class AbstractSerialGenerator(val bindingContext: BindingContext, val currentDeclaration: ClassDescriptor) {
|
||||
|
||||
private fun getKClassListFromFileAnnotation(annotationFqName: FqName, declarationInFile: DeclarationDescriptor): List<KotlinType> {
|
||||
val annotation = AnnotationsUtils
|
||||
.getContainingFileAnnotations(bindingContext, declarationInFile)
|
||||
.find { it.fqName == annotationFqName }
|
||||
?: return emptyList()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val typeList: List<KClassValue> = annotation.firstArgument()?.value as? List<KClassValue> ?: return emptyList()
|
||||
return typeList.map { it.value }
|
||||
}
|
||||
|
||||
val contextualKClassListInCurrentFile: Set<KotlinType> by lazy {
|
||||
getKClassListFromFileAnnotation(
|
||||
SerializationAnnotations.contextualFqName,
|
||||
currentDeclaration
|
||||
).toSet()
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -25,8 +25,8 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializableProperti
|
||||
|
||||
abstract class SerializableCodegen(
|
||||
protected val serializableDescriptor: ClassDescriptor,
|
||||
private val bindingContext: BindingContext
|
||||
) {
|
||||
bindingContext: BindingContext
|
||||
) : AbstractSerialGenerator(bindingContext, serializableDescriptor) {
|
||||
protected val properties = SerializableProperties(serializableDescriptor, bindingContext)
|
||||
|
||||
fun generate() {
|
||||
|
||||
+4
-2
@@ -19,12 +19,14 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.common
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi2ir.findSingleFunction
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_PROVIDER_NAME
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
|
||||
|
||||
abstract class SerializableCompanionCodegen(
|
||||
protected val companionDescriptor: ClassDescriptor
|
||||
) {
|
||||
protected val companionDescriptor: ClassDescriptor,
|
||||
bindingContext: BindingContext
|
||||
) : AbstractSerialGenerator(bindingContext, companionDescriptor) {
|
||||
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorByCompanion(companionDescriptor)!!
|
||||
|
||||
fun generate() {
|
||||
|
||||
+1
-3
@@ -20,8 +20,6 @@ import org.jetbrains.kotlin.backend.common.CodegenUtil.getMemberToGenerate
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
||||
import org.jetbrains.kotlin.psi.synthetics.findClassDescriptor
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
|
||||
@@ -31,7 +29,7 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescripto
|
||||
abstract class SerializerCodegen(
|
||||
protected val serializerDescriptor: ClassDescriptor,
|
||||
bindingContext: BindingContext
|
||||
) {
|
||||
) : AbstractSerialGenerator(bindingContext, serializerDescriptor) {
|
||||
// protected val serializerDescriptor: ClassDescriptor = declaration.findClassDescriptor(bindingContext)
|
||||
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
|
||||
protected val serialName: String = serializableDescriptor.annotations.serialNameValue ?: serializableDescriptor.fqNameUnsafe.asString()
|
||||
|
||||
+3
-3
@@ -49,7 +49,7 @@ open class SerialTypeInfo(
|
||||
val unit: Boolean = false
|
||||
)
|
||||
|
||||
fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
||||
fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
||||
val T = property.type
|
||||
val serializableWith = property.serializableWith?.toClassDescriptor
|
||||
if (serializableWith != null) return SerialTypeInfo(property, if (property.type.isMarkedNullable) "Nullable" else "", serializableWith)
|
||||
@@ -81,7 +81,7 @@ fun getSerialTypeInfo(property: SerializableProperty): SerialTypeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
fun findTypeSerializerOrContext(
|
||||
fun AbstractSerialGenerator.findTypeSerializerOrContext(
|
||||
module: ModuleDescriptor,
|
||||
kType: KotlinType,
|
||||
annotations: Annotations = kType.annotations,
|
||||
@@ -89,7 +89,7 @@ fun findTypeSerializerOrContext(
|
||||
): ClassDescriptor? {
|
||||
if (kType.isTypeParameter()) return null
|
||||
fun getContextualSerializer() =
|
||||
if (annotations.hasAnnotation(SerializationAnnotations.contextualFqName))
|
||||
if (annotations.hasAnnotation(SerializationAnnotations.contextualFqName) || kType in contextualKClassListInCurrentFile)
|
||||
module.getClassFromSerializationPackage(SpecialBuiltins.contextSerializer)
|
||||
else
|
||||
throw CompilationException(
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ class SerializableCompanionIrGenerator(
|
||||
val irClass: IrClass,
|
||||
override val compilerContext: BackendContext,
|
||||
bindingContext: BindingContext
|
||||
) : SerializableCompanionCodegen(irClass.descriptor), IrBuilderExtension {
|
||||
) : SerializableCompanionCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
|
||||
override val translator: TypeTranslator = compilerContext.createTypeTranslator(serializableDescriptor.module)
|
||||
private val _table = SymbolTable()
|
||||
override val BackendContext.localSymbolTable: SymbolTable
|
||||
|
||||
+2
-1
@@ -32,7 +32,8 @@ import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
class SerializableCompanionJsTranslator(
|
||||
declaration: ClassDescriptor,
|
||||
val translator: DeclarationBodyVisitor,
|
||||
val context: TranslationContext): SerializableCompanionCodegen(declaration) {
|
||||
val context: TranslationContext
|
||||
): SerializableCompanionCodegen(declaration, context.bindingContext()) {
|
||||
|
||||
override fun generateSerializerGetter(methodDescriptor: FunctionDescriptor) {
|
||||
val f = context.buildFunction(methodDescriptor) {jsFun, context ->
|
||||
|
||||
+22
-15
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
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.findTypeSerializerOrContext
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
@@ -90,12 +91,15 @@ internal fun InstructionAdapter.genExceptionThrow(exceptionClass: String, messag
|
||||
athrow()
|
||||
}
|
||||
|
||||
fun InstructionAdapter.genKOutputMethodCall(property: SerializableProperty, classCodegen: ImplementationBodyCodegen, expressionCodegen: ExpressionCodegen,
|
||||
propertyOwnerType: Type, ownerVar: Int, fromClassStartVar: Int? = null) {
|
||||
fun InstructionAdapter.genKOutputMethodCall(
|
||||
property: SerializableProperty, classCodegen: ImplementationBodyCodegen, expressionCodegen: ExpressionCodegen,
|
||||
propertyOwnerType: Type, ownerVar: Int, fromClassStartVar: Int? = null,
|
||||
generator: AbstractSerialGenerator
|
||||
) {
|
||||
val propertyType = classCodegen.typeMapper.mapType(property.type)
|
||||
val sti = getSerialTypeInfo(property, propertyType)
|
||||
val useSerializer = if (fromClassStartVar == null) stackValueSerializerInstanceFromSerializer(classCodegen, sti)
|
||||
else stackValueSerializerInstanceFromClass(classCodegen, sti, fromClassStartVar)
|
||||
val sti = generator.getSerialTypeInfo(property, propertyType)
|
||||
val useSerializer = if (fromClassStartVar == null) stackValueSerializerInstanceFromSerializer(classCodegen, sti, generator)
|
||||
else stackValueSerializerInstanceFromClass(classCodegen, sti, fromClassStartVar, generator)
|
||||
if (!sti.unit) ImplementationBodyCodegen.genPropertyOnStack(
|
||||
this,
|
||||
expressionCodegen.context,
|
||||
@@ -104,11 +108,13 @@ fun InstructionAdapter.genKOutputMethodCall(property: SerializableProperty, clas
|
||||
ownerVar,
|
||||
classCodegen.state
|
||||
)
|
||||
invokeinterface(kOutputType.internalName,
|
||||
invokeinterface(
|
||||
kOutputType.internalName,
|
||||
CallingConventions.encode + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + CallingConventions.elementPostfix,
|
||||
"(" + descType.descriptor + "I" +
|
||||
(if (useSerializer) kSerialSaverType.descriptor else "") +
|
||||
(if (sti.unit) "" else sti.type.descriptor) + ")V")
|
||||
"(" + descType.descriptor + "I" +
|
||||
(if (useSerializer) kSerialSaverType.descriptor else "") +
|
||||
(if (sti.unit) "" else sti.type.descriptor) + ")V"
|
||||
)
|
||||
}
|
||||
|
||||
internal fun InstructionAdapter.buildInternalConstructorDesc(propsStartVar: Int, bitMaskBase: Int, codegen: ClassBodyCodegen, args: List<SerializableProperty>): String {
|
||||
@@ -146,10 +152,11 @@ internal val contextSerializerId = ClassId(packageFqName, Name.identifier(Specia
|
||||
internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(
|
||||
codegen: ClassBodyCodegen,
|
||||
sti: JVMSerialTypeInfo,
|
||||
varIndexStart: Int
|
||||
varIndexStart: Int,
|
||||
serializerCodegen: AbstractSerialGenerator
|
||||
): Boolean {
|
||||
val serializer = sti.serializer
|
||||
return stackValueSerializerInstance(
|
||||
return serializerCodegen.stackValueSerializerInstance(
|
||||
codegen,
|
||||
sti.property.module,
|
||||
sti.property.type,
|
||||
@@ -161,8 +168,8 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(
|
||||
}
|
||||
}
|
||||
|
||||
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo): Boolean {
|
||||
return stackValueSerializerInstance(
|
||||
internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo, serializerCodegen: AbstractSerialGenerator): Boolean {
|
||||
return serializerCodegen.stackValueSerializerInstance(
|
||||
codegen, sti.property.module, sti.property.type,
|
||||
sti.serializer, this, sti.property.genericIndex
|
||||
) { idx ->
|
||||
@@ -173,7 +180,7 @@ internal fun InstructionAdapter.stackValueSerializerInstanceFromSerializer(codeg
|
||||
|
||||
// returns false is cannot not use serializer
|
||||
// use iv == null to check only (do not emit serializer onto stack)
|
||||
internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||
internal fun AbstractSerialGenerator.stackValueSerializerInstance(codegen: ClassBodyCodegen, module: ModuleDescriptor, kType: KotlinType, maybeSerializer: ClassDescriptor?,
|
||||
iv: InstructionAdapter?, genericIndex: Int? = null, genericSerializerFieldGetter: (InstructionAdapter.(Int) -> Unit)? = null): Boolean {
|
||||
if (genericIndex != null) {
|
||||
// get field from serializer object
|
||||
@@ -262,7 +269,7 @@ class JVMSerialTypeInfo(
|
||||
unit: Boolean = false
|
||||
) : SerialTypeInfo(property, nn, serializer, unit)
|
||||
|
||||
fun getSerialTypeInfo(property: SerializableProperty, type: Type): JVMSerialTypeInfo {
|
||||
fun AbstractSerialGenerator.getSerialTypeInfo(property: SerializableProperty, type: Type): JVMSerialTypeInfo {
|
||||
if (property.type.isTypeParameter()) return JVMSerialTypeInfo(
|
||||
property,
|
||||
Type.getType("Ljava/lang/Object;"),
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ class SerializableCodegenImpl(
|
||||
load(outputI, kOutputType)
|
||||
load(serialDescI, descType)
|
||||
iconst(i)
|
||||
genKOutputMethodCall(property, classCodegen, exprCodegen, thisAsmType, thisI, offsetI)
|
||||
genKOutputMethodCall(property, classCodegen, exprCodegen, thisAsmType, thisI, offsetI, generator = this@SerializableCodegenImpl)
|
||||
}
|
||||
|
||||
areturn(Type.VOID_TYPE)
|
||||
|
||||
+2
-1
@@ -18,12 +18,13 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCompanionCodegen
|
||||
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
|
||||
|
||||
class SerializableCompanionCodegenImpl(private val codegen: ImplementationBodyCodegen) :
|
||||
SerializableCompanionCodegen(codegen.descriptor) {
|
||||
SerializableCompanionCodegen(codegen.descriptor, codegen.bindingContext) {
|
||||
|
||||
companion object {
|
||||
fun generateSerializableExtensions(codegen: ImplementationBodyCodegen) {
|
||||
|
||||
+2
-2
@@ -196,7 +196,7 @@ class SerializerCodegenImpl(
|
||||
load(outputVar, kOutputType)
|
||||
load(descVar, descType)
|
||||
iconst(index)
|
||||
genKOutputMethodCall(property, codegen, expressionCodegen, objType, objVar)
|
||||
genKOutputMethodCall(property, codegen, expressionCodegen, objType, objVar, generator = this@SerializerCodegenImpl)
|
||||
}
|
||||
}
|
||||
// output.writeEnd(classDesc)
|
||||
@@ -303,7 +303,7 @@ class SerializerCodegenImpl(
|
||||
iconst(labelNum)
|
||||
|
||||
val sti = getSerialTypeInfo(property, propertyType)
|
||||
val useSerializer = stackValueSerializerInstanceFromSerializer(codegen, sti)
|
||||
val useSerializer = stackValueSerializerInstanceFromSerializer(codegen, sti, this@SerializerCodegenImpl)
|
||||
val unknownSer = (!useSerializer && sti.elementMethodPrefix.isEmpty())
|
||||
if (unknownSer) {
|
||||
aconst(codegen.typeMapper.mapType(property.type))
|
||||
|
||||
Reference in New Issue
Block a user