Extract naming conventions

This commit is contained in:
Leonid Startsev
2018-07-18 17:17:54 +03:00
parent 8cd5966c4a
commit 2e50e4e816
13 changed files with 248 additions and 181 deletions
@@ -19,11 +19,11 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.common
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi2ir.findSingleFunction import org.jetbrains.kotlin.psi2ir.findSingleFunction
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.SERIALIZER_PROVIDER_NAME import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_PROVIDER_NAME
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorByCompanion
abstract class SerializableCompanionCodegen( abstract class SerializableCompanionCodegen(
protected val companionDescriptor: ClassDescriptor /*declaration: KtPureClassOrObject*/ protected val companionDescriptor: ClassDescriptor
) { ) {
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorByCompanion(companionDescriptor)!! protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorByCompanion(companionDescriptor)!!
@@ -28,8 +28,11 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor
abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContext: BindingContext) { abstract class SerializerCodegen(
protected val serializerDescriptor: ClassDescriptor = declaration.findClassDescriptor(bindingContext) protected val serializerDescriptor: ClassDescriptor,
bindingContext: BindingContext
) {
// protected val serializerDescriptor: ClassDescriptor = declaration.findClassDescriptor(bindingContext)
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!! protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
protected val serialName: String = serializableDescriptor.annotations.serialNameValue ?: serializableDescriptor.fqNameUnsafe.asString() protected val serialName: String = serializableDescriptor.annotations.serialNameValue ?: serializableDescriptor.fqNameUnsafe.asString()
protected val properties = SerializableProperties(serializableDescriptor, bindingContext) protected val properties = SerializableProperties(serializableDescriptor, bindingContext)
@@ -66,7 +69,7 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
return !found return !found
} }
protected val serialDescPropertyDescriptor = getPropertyToGenerate(serializerDescriptor, KSerializerDescriptorResolver.SERIAL_DESC_FIELD, protected val serialDescPropertyDescriptor = getPropertyToGenerate(serializerDescriptor, SerialEntityNames.SERIAL_DESC_FIELD,
serializerDescriptor::checkSerializableClassPropertyResult) serializerDescriptor::checkSerializableClassPropertyResult)
protected abstract fun generateSerialDesc() protected abstract fun generateSerialDesc()
@@ -86,7 +89,7 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
} }
private fun generateSaveIfNeeded(): Boolean { private fun generateSaveIfNeeded(): Boolean {
val function = getMemberToGenerate(serializerDescriptor, KSerializerDescriptorResolver.SAVE, val function = getMemberToGenerate(serializerDescriptor, SerialEntityNames.SAVE,
serializerDescriptor::checkSaveMethodResult, serializerDescriptor::checkSaveMethodParameters) serializerDescriptor::checkSaveMethodResult, serializerDescriptor::checkSaveMethodParameters)
?: return false ?: return false
generateSave(function) generateSave(function)
@@ -94,7 +97,7 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
} }
private fun generateLoadIfNeeded(): Boolean { private fun generateLoadIfNeeded(): Boolean {
val function = getMemberToGenerate(serializerDescriptor, KSerializerDescriptorResolver.LOAD, val function = getMemberToGenerate(serializerDescriptor, SerialEntityNames.LOAD,
serializerDescriptor::checkLoadMethodResult, serializerDescriptor::checkLoadMethodParameters) serializerDescriptor::checkLoadMethodResult, serializerDescriptor::checkLoadMethodParameters)
?: return false ?: return false
generateLoad(function) generateLoad(function)
@@ -35,6 +35,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.polymorphicSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.internalPackageFqName
open class SerialTypeInfo( open class SerialTypeInfo(
val property: SerializableProperty, val property: SerializableProperty,
@@ -84,7 +85,7 @@ fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescri
if (userOverride != null) return userOverride.toClassDescriptor if (userOverride != null) return userOverride.toClassDescriptor
if (kType.requiresPolymorphism()) return findPolymorphicSerializer(module) if (kType.requiresPolymorphism()) return findPolymorphicSerializer(module)
if (kType.isTypeParameter()) return null if (kType.isTypeParameter()) return null
if (KotlinBuiltIns.isArray(kType)) return module.getClassFromInternalSerializationPackage("ReferenceArraySerializer") if (KotlinBuiltIns.isArray(kType)) return module.getClassFromInternalSerializationPackage(SpecialBuiltins.referenceArraySerializer)
return kType.typeSerializer.toClassDescriptor // check for serializer defined on the type 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)
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
@@ -49,7 +50,7 @@ class SerializableIrGenerator(
// Missing field exception parts // Missing field exception parts
val exceptionCtor = val exceptionCtor =
serializableDescriptor.getClassFromSerializationPackage("MissingFieldException") serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC)
.unsubstitutedPrimaryConstructor!! .unsubstitutedPrimaryConstructor!!
val exceptionCtorRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor) val exceptionCtorRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor)
val exceptionType = exceptionCtor.returnType.toIrType() val exceptionType = exceptionCtor.returnType.toIrType()
@@ -35,6 +35,10 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerialize
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_DECODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_ENCODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.UNKNOWN_FIELD_EXC
// Is creating synthetic origin is a good idea or not? // Is creating synthetic origin is a good idea or not?
object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER") object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER")
@@ -47,11 +51,11 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
override fun generateSerialDesc() { override fun generateSerialDesc() {
val desc: PropertyDescriptor = serialDescPropertyDescriptor ?: return val desc: PropertyDescriptor = serialDescPropertyDescriptor ?: return
val serialDescImplClass = serializerDescriptor val serialDescImplClass = serializerDescriptor
.getClassFromInternalSerializationPackage("SerialClassDescImpl") .getClassFromInternalSerializationPackage(SERIAL_DESCRIPTOR_CLASS_IMPL)
val serialDescImplConstructor = serialDescImplClass val serialDescImplConstructor = serialDescImplClass
.unsubstitutedPrimaryConstructor!! .unsubstitutedPrimaryConstructor!!
val addFuncS = serialDescImplClass.referenceMethod("addElement") val addFuncS = serialDescImplClass.referenceMethod(CallingConventions.addElement)
val thisAsReceiverParameter = irClass.thisReceiver!! val thisAsReceiverParameter = irClass.thisReceiver!!
lateinit var prop: IrProperty lateinit var prop: IrProperty
@@ -121,7 +125,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
genericIndex: Int? = null genericIndex: Int? = null
): IrExpression? { ): IrExpression? {
val nullableSerClass = val nullableSerClass =
compilerContext.symbolTable.referenceClass(module.getClassFromInternalSerializationPackage("NullableSerializer")) compilerContext.symbolTable.referenceClass(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
if (serializerClass == null) { if (serializerClass == null) {
if (genericIndex == null) return null if (genericIndex == null) return null
return TODO("Saved serializer for generic argument") return TODO("Saved serializer for generic argument")
@@ -162,14 +166,14 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
fun irThis(): IrExpression = fun irThis(): IrExpression =
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol) IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
val kOutputClass = serializerDescriptor.getClassFromSerializationPackage("StructureEncoder") val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_ENCODER_CLASS)
val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(serialDescPropertyDescriptor?.getter!!) val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(serialDescPropertyDescriptor?.getter!!)
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc") val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
// fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder // fun beginStructure(desc: SerialDescriptor, vararg typeParams: KSerializer<*>): StructureEncoder
val beginFunc = kOutputClass.referenceMethod("beginStructure") // todo: retrieve from actual encoder instead val beginFunc = kOutputClass.referenceMethod(CallingConventions.begin) // todo: retrieve from actual encoder instead
val call = irCall(beginFunc).mapValueParametersIndexed { i, parameterDescriptor -> val call = irCall(beginFunc).mapValueParametersIndexed { i, parameterDescriptor ->
if (i == 0) irGet(localSerialDesc) else IrVarargImpl( if (i == 0) irGet(localSerialDesc) else IrVarargImpl(
@@ -194,7 +198,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex) val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
if (innerSerial == null) { if (innerSerial == null) {
val writeFunc = val writeFunc =
kOutputClass.referenceMethod("encode${sti.elementMethodPrefix}ElementValue") kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
+irInvoke( +irInvoke(
irGet(localOutput), irGet(localOutput),
writeFunc, writeFunc,
@@ -205,7 +209,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
irGetField(irGet(serialObjectSymbol), compilerContext.symbolTable.referenceField(property.descriptor).owner) irGetField(irGet(serialObjectSymbol), compilerContext.symbolTable.referenceField(property.descriptor).owner)
) )
} else { } else {
val writeFunc = kOutputClass.referenceMethod("encode${sti.elementMethodPrefix}SerializableElementValue") val writeFunc = kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
+irInvoke( +irInvoke(
irGet(localOutput), irGet(localOutput),
writeFunc, writeFunc,
@@ -220,12 +224,12 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
} }
// output.writeEnd(serialClassDesc) // output.writeEnd(serialClassDesc)
val wEndFunc = kOutputClass.referenceMethod("endStructure") val wEndFunc = kOutputClass.referenceMethod(CallingConventions.end)
+irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc)) +irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc))
} }
// returns null: Any? for boxed types and 0: <number type> for primitives // returns null: Any? for boxed types and 0: <number type> for primitives
fun IrBuilderWithScope.defaultValueAndType(prop: SerializableProperty): Pair<IrExpression, KotlinType> { private fun IrBuilderWithScope.defaultValueAndType(prop: SerializableProperty): Pair<IrExpression, KotlinType> {
val kType = prop.descriptor.returnType!! val kType = prop.descriptor.returnType!!
val T = kType.toIrType() val T = kType.toIrType()
val defaultPrimitive: IrExpression? = when { val defaultPrimitive: IrExpression? = when {
@@ -251,7 +255,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
fun IrVariable.get() = irGet(this) fun IrVariable.get() = irGet(this)
val inputClass = serializerDescriptor.getClassFromSerializationPackage("StructureDecoder") val inputClass = serializerDescriptor.getClassFromSerializationPackage(STRUCTURE_DECODER_CLASS)
val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(serialDescPropertyDescriptor?.getter!!) val descriptorGetterSymbol = compilerContext.symbolTable.referenceFunction(serialDescPropertyDescriptor?.getter!!)
val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc") val localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
@@ -278,7 +282,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
} }
//input = input.beginStructure(...) //input = input.beginStructure(...)
val beginFunc = inputClass.referenceMethod("beginStructure") val beginFunc = inputClass.referenceMethod(CallingConventions.begin)
val call = irInvoke( val call = irInvoke(
irGet(loadFunc.valueParameters[0]), irGet(loadFunc.valueParameters[0]),
beginFunc, beginFunc,
@@ -290,7 +294,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
+irWhile().also { loop -> +irWhile().also { loop ->
loop.condition = flagVar.get() loop.condition = flagVar.get()
loop.body = irBlock { loop.body = irBlock {
val readElementF = inputClass.referenceMethod("decodeElement") val readElementF = inputClass.referenceMethod(CallingConventions.decodeElementIndex)
+irSetVar(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get())) +irSetVar(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get()))
+irWhen { +irWhen {
// if index == -2 (READ_ALL) todo... // if index == -2 (READ_ALL) todo...
@@ -305,8 +309,8 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex) val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
// todo: update // todo: update
val decodeFuncToCall = val decodeFuncToCall =
(if (innerSerial != null) "decode${sti.elementMethodPrefix}SerializableElementValue" (if (innerSerial != null) "${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}"
else "decode${sti.elementMethodPrefix}ElementValue") else "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
.let { .let {
inputClass.referenceMethod(it) inputClass.referenceMethod(it)
} }
@@ -326,7 +330,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
// throw exception on unknown field // throw exception on unknown field
val exceptionCtor = val exceptionCtor =
serializableDescriptor.getClassFromSerializationPackage("UnknownFieldException") serializableDescriptor.getClassFromSerializationPackage(UNKNOWN_FIELD_EXC)
.unsubstitutedPrimaryConstructor!! .unsubstitutedPrimaryConstructor!!
val excClassRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor) val excClassRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor)
+elseBranch( +elseBranch(
@@ -344,7 +348,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
} }
//input.endStructure(...) //input.endStructure(...)
val endFunc = inputClass.referenceMethod("endStructure") val endFunc = inputClass.referenceMethod(CallingConventions.end)
+irInvoke( +irInvoke(
localInput.get(), localInput.get(),
endFunc, endFunc,
@@ -32,6 +32,7 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableC
import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers import org.jetbrains.kotlinx.serialization.compiler.backend.common.anonymousInitializers
import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap import org.jetbrains.kotlinx.serialization.compiler.backend.common.bodyPropertiesDescriptorsMap
import org.jetbrains.kotlinx.serialization.compiler.backend.common.primaryPropertiesDescriptorsMap import org.jetbrains.kotlinx.serialization.compiler.backend.common.primaryPropertiesDescriptorsMap
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage import org.jetbrains.kotlinx.serialization.compiler.resolve.getClassFromSerializationPackage
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
@@ -49,7 +50,7 @@ class SerializableJsTranslator(
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) { override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) {
val missingExceptionClassRef = serializableDescriptor.getClassFromSerializationPackage("MissingFieldException") val missingExceptionClassRef = serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC)
.let { context.translateQualifiedReference(it) } .let { context.translateQualifiedReference(it) }
val f = context.buildFunction(constructorDescriptor) { jsFun, context -> val f = context.buildFunction(constructorDescriptor) { jsFun, context ->
@@ -40,7 +40,9 @@ import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.contextSerialize
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.enumSerializerId
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.referenceArraySerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_ENCODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.typeArgPrefix
class SerializerJsTranslator(declaration: KtPureClassOrObject, class SerializerJsTranslator(declaration: KtPureClassOrObject,
val translator: DeclarationBodyVisitor, val translator: DeclarationBodyVisitor,
@@ -55,7 +57,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
override fun generateSerialDesc() { override fun generateSerialDesc() {
val desc = serialDescPropertyDescriptor ?: return val desc = serialDescPropertyDescriptor ?: return
val serialDescImplClass = serializerDescriptor val serialDescImplClass = serializerDescriptor
.getClassFromInternalSerializationPackage("SerialClassDescImpl") .getClassFromInternalSerializationPackage(SERIAL_DESCRIPTOR_CLASS_IMPL)
val serialDescImplConstructor = serialDescImplClass val serialDescImplConstructor = serialDescImplClass
.unsubstitutedPrimaryConstructor!! .unsubstitutedPrimaryConstructor!!
@@ -65,9 +67,9 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
translator.addInitializerStatement(assgmnt.makeStmt()) translator.addInitializerStatement(assgmnt.makeStmt())
// adding elements via serialDesc.addElement(...) // adding elements via serialDesc.addElement(...)
val addFunc = serialDescImplClass.getFuncDesc("addElement").single() val addFunc = serialDescImplClass.getFuncDesc(CallingConventions.addElement).single()
val pushFunc = serialDescImplClass.getFuncDesc("pushAnnotation").single() val pushFunc = serialDescImplClass.getFuncDesc(CallingConventions.addAnnotation).single()
val pushClassFunc = serialDescImplClass.getFuncDesc("pushClassAnnotation").single() val pushClassFunc = serialDescImplClass.getFuncDesc(CallingConventions.addClassAnnotation).single()
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor), JsThisRef()) val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor), JsThisRef())
for (prop in orderedProperties) { for (prop in orderedProperties) {
@@ -120,9 +122,9 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
} }
override fun generateSave(function: FunctionDescriptor) = generateFunction(function) { jsFun, ctx -> override fun generateSave(function: FunctionDescriptor) = generateFunction(function) { jsFun, ctx ->
val kOutputClass = serializerDescriptor.getClassFromSerializationPackage("StructureEncoder") val kOutputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS)
val wBeginFunc = ctx.getNameForDescriptor( val wBeginFunc = ctx.getNameForDescriptor(
kOutputClass.getFuncDesc("beginStructure").single { it.valueParameters.size == 2 }) kOutputClass.getFuncDesc(CallingConventions.begin).single { it.valueParameters.size == 2 })
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor!!), JsThisRef()) val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor!!), JsThisRef())
// output.writeBegin(desc, []) // output.writeBegin(desc, [])
@@ -148,7 +150,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex) val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
if (innerSerial == null) { if (innerSerial == null) {
val writeFunc = val writeFunc =
kOutputClass.getFuncDesc("encode${sti.elementMethodPrefix}ElementValue").single() kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}").single()
.let { ctx.getNameForDescriptor(it) } .let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(writeFunc, localOutputRef), +JsInvocation(JsNameRef(writeFunc, localOutputRef),
serialClassDescRef, serialClassDescRef,
@@ -157,7 +159,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
} }
else { else {
val writeFunc = val writeFunc =
kOutputClass.getFuncDesc("encode${sti.elementMethodPrefix}SerializableElementValue").single() kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single()
.let { ctx.getNameForDescriptor(it) } .let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(writeFunc, localOutputRef), +JsInvocation(JsNameRef(writeFunc, localOutputRef),
serialClassDescRef, serialClassDescRef,
@@ -168,13 +170,13 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
} }
// output.writeEnd(serialClassDesc) // output.writeEnd(serialClassDesc)
val wEndFunc = kOutputClass.getFuncDesc("endStructure").single() val wEndFunc = kOutputClass.getFuncDesc(CallingConventions.end).single()
.let { ctx.getNameForDescriptor(it) } .let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(wEndFunc, localOutputRef), serialClassDescRef).makeStmt() +JsInvocation(JsNameRef(wEndFunc, localOutputRef), serialClassDescRef).makeStmt()
} }
private fun serializerInstance(serializerClass: ClassDescriptor?, module: ModuleDescriptor, kType: KotlinType, genericIndex: Int? = null): JsExpression? { private fun serializerInstance(serializerClass: ClassDescriptor?, module: ModuleDescriptor, kType: KotlinType, genericIndex: Int? = null): JsExpression? {
val nullableSerClass = context.translateQualifiedReference(module.getClassFromInternalSerializationPackage("NullableSerializer")) val nullableSerClass = context.translateQualifiedReference(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
if (serializerClass == null) { if (serializerClass == null) {
if (genericIndex == null) return null if (genericIndex == null) return null
return JsNameRef(context.scope().declareName("$typeArgPrefix$genericIndex"), JsThisRef()) return JsNameRef(context.scope().declareName("$typeArgPrefix$genericIndex"), JsThisRef())
@@ -209,7 +211,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
override fun generateLoad(function: FunctionDescriptor) = generateFunction(function) { jsFun, context -> override fun generateLoad(function: FunctionDescriptor) = generateFunction(function) { jsFun, context ->
val inputClass = serializerDescriptor.getClassFromSerializationPackage("StructureDecoder") val inputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_DECODER_CLASS)
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor!!), JsThisRef()) val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor!!), JsThisRef())
// var index = -1, readAll = false // var index = -1, readAll = false
@@ -234,7 +236,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
JsNameRef(context.scope().declareName("$typeArgPrefix$idx"), JsThisRef()) JsNameRef(context.scope().declareName("$typeArgPrefix$idx"), JsThisRef())
} }
val inputVar = JsNameRef(jsFun.scope.declareFreshName("input")) val inputVar = JsNameRef(jsFun.scope.declareFreshName("input"))
val readBeginF = inputClass.getFuncDesc("beginStructure").single() val readBeginF = inputClass.getFuncDesc(CallingConventions.begin).single()
val call = JsInvocation(JsNameRef(context.getNameForDescriptor(readBeginF), JsNameRef(jsFun.parameters[0].name)), val call = JsInvocation(JsNameRef(context.getNameForDescriptor(readBeginF), JsNameRef(jsFun.parameters[0].name)),
serialClassDescRef, JsArrayLiteral(typeParams)) serialClassDescRef, JsArrayLiteral(typeParams))
+JsVars(JsVars.JsVar(inputVar.name, call)) +JsVars(JsVars.JsVar(inputVar.name, call))
@@ -244,7 +246,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val loopRef = JsNameRef(loop.name) val loopRef = JsNameRef(loop.name)
jsWhile(JsBooleanLiteral(true), { jsWhile(JsBooleanLiteral(true), {
// index = input.readElement(classDesc) // index = input.readElement(classDesc)
val readElementF = context.getNameForDescriptor(inputClass.getFuncDesc("decodeElement").single()) val readElementF = context.getNameForDescriptor(inputClass.getFuncDesc(CallingConventions.decodeElementIndex).single())
+JsAstUtils.assignment( +JsAstUtils.assignment(
indexVar, indexVar,
JsInvocation(JsNameRef(readElementF, inputVar), serialClassDescRef) JsInvocation(JsNameRef(readElementF, inputVar), serialClassDescRef)
@@ -267,9 +269,9 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val call: JsExpression = if (innerSerial == null) { val call: JsExpression = if (innerSerial == null) {
val unknownSer = (sti.elementMethodPrefix.isEmpty()) val unknownSer = (sti.elementMethodPrefix.isEmpty())
val readFunc = val readFunc =
inputClass.getFuncDesc("decode${sti.elementMethodPrefix}ElementValue") inputClass.getFuncDesc("${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
// if readElementValue, must have 3 parameters, if readXXXElementValue - 2 // if readElementValue, must have 3 parameters, if readXXXElementValue - 2
.single { !unknownSer || (it is FunctionDescriptor && it.valueParameters.size == 3) } .single { !unknownSer || (it.valueParameters.size == 3) }
.let { context.getNameForDescriptor(it) } .let { context.getNameForDescriptor(it) }
val readArgs = mutableListOf(serialClassDescRef, JsIntLiteral(i)) val readArgs = mutableListOf(serialClassDescRef, JsIntLiteral(i))
if (unknownSer) readArgs.add(createGetKClassExpression(property.type.toClassDescriptor!!)) if (unknownSer) readArgs.add(createGetKClassExpression(property.type.toClassDescriptor!!))
@@ -278,10 +280,10 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
else { else {
val notSeenTest = propNotSeenTest(bitMasks[i / 32], i) val notSeenTest = propNotSeenTest(bitMasks[i / 32], i)
val readFunc = val readFunc =
inputClass.getFuncDesc("decode${sti.elementMethodPrefix}SerializableElementValue").single() inputClass.getFuncDesc("${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single()
.let { context.getNameForDescriptor(it) } .let { context.getNameForDescriptor(it) }
val updateFunc = val updateFunc =
inputClass.getFuncDesc("update${sti.elementMethodPrefix}SerializableElementValue").single() inputClass.getFuncDesc("${CallingConventions.update}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single()
.let { context.getNameForDescriptor(it) } .let { context.getNameForDescriptor(it) }
JsConditional(notSeenTest, JsConditional(notSeenTest,
JsInvocation(JsNameRef(readFunc, inputVar), JsInvocation(JsNameRef(readFunc, inputVar),
@@ -338,7 +340,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
} }
// default: throw // default: throw
default { default {
val excClassRef = serializableDescriptor.getClassFromSerializationPackage("UnknownFieldException") val excClassRef = serializableDescriptor.getClassFromSerializationPackage(SerialEntityNames.UNKNOWN_FIELD_EXC)
.let { context.translateQualifiedReference(it) } .let { context.translateQualifiedReference(it) }
+JsThrow(JsNew(excClassRef, listOf(indexVar))) +JsThrow(JsNew(excClassRef, listOf(indexVar)))
} }
@@ -346,7 +348,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
}, loop) }, loop)
// input.readEnd(desc) // input.readEnd(desc)
val readEndF = inputClass.getFuncDesc("endStructure").single() val readEndF = inputClass.getFuncDesc(CallingConventions.end).single()
.let { context.getNameForDescriptor(it) } .let { context.getNameForDescriptor(it) }
+JsInvocation( +JsInvocation(
JsNameRef(readEndF, inputVar), JsNameRef(readEndF, inputVar),
@@ -30,24 +30,38 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerialTypeInfo import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerialTypeInfo
import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer import org.jetbrains.kotlinx.serialization.compiler.backend.common.findTypeSerializer
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.MISSING_FIELD_EXC
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_CTOR_MARKER_NAME
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_DESCRIPTOR_CLASS_IMPL
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_EXC
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_LOADER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIAL_SAVER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_DECODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.STRUCTURE_ENCODER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.UNKNOWN_FIELD_EXC
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.typeArgPrefix
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.internalPackageFqName
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.packageFqName
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
internal val descType = Type.getObjectType("kotlinx/serialization/SerialDescriptor") // todo: extract packages constants too?
internal val descImplType = Type.getObjectType("kotlinx/serialization/internal/SerialClassDescImpl") internal val descType = Type.getObjectType("kotlinx/serialization/$SERIAL_DESCRIPTOR_CLASS")
internal val kOutputType = Type.getObjectType("kotlinx/serialization/StructureEncoder") internal val descImplType = Type.getObjectType("kotlinx/serialization/internal/$SERIAL_DESCRIPTOR_CLASS_IMPL")
internal val kInputType = Type.getObjectType("kotlinx/serialization/StructureDecoder") internal val kOutputType = Type.getObjectType("kotlinx/serialization/$STRUCTURE_ENCODER_CLASS")
internal val kInputType = Type.getObjectType("kotlinx/serialization/$STRUCTURE_DECODER_CLASS")
internal val kSerialSaverType = Type.getObjectType("kotlinx/serialization/SerializationStrategy") internal val kSerialSaverType = Type.getObjectType("kotlinx/serialization/$SERIAL_SAVER_CLASS")
internal val kSerialLoaderType = Type.getObjectType("kotlinx/serialization/DeserializationStrategy") internal val kSerialLoaderType = Type.getObjectType("kotlinx/serialization/$SERIAL_LOADER_CLASS")
internal val kSerializerType = Type.getObjectType("kotlinx/serialization/KSerializer") internal val kSerializerType = Type.getObjectType("kotlinx/serialization/$KSERIALIZER_CLASS")
internal val kSerializerArrayType = Type.getObjectType("[Lkotlinx/serialization/KSerializer;") internal val kSerializerArrayType = Type.getObjectType("[Lkotlinx/serialization/$KSERIALIZER_CLASS;")
internal val serializationExceptionName = "kotlinx/serialization/SerializationException" internal val serializationExceptionName = "kotlinx/serialization/$SERIAL_EXC"
internal val serializationExceptionMissingFieldName = "kotlinx/serialization/MissingFieldException" internal val serializationExceptionMissingFieldName = "kotlinx/serialization/$MISSING_FIELD_EXC"
internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/UnknownFieldException" internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/$UNKNOWN_FIELD_EXC"
val OPT_MASK_TYPE: Type = Type.INT_TYPE val OPT_MASK_TYPE: Type = Type.INT_TYPE
val OPT_MASK_BITS = 32 val OPT_MASK_BITS = 32
@@ -78,7 +92,7 @@ fun InstructionAdapter.genKOutputMethodCall(property: SerializableProperty, clas
else stackValueSerializerInstanceFromClass(classCodegen, sti, fromClassStartVar) else stackValueSerializerInstanceFromClass(classCodegen, sti, fromClassStartVar)
if (!sti.unit) classCodegen.genPropertyOnStack(this, expressionCodegen.context, property.descriptor, propertyOwnerType, ownerVar) if (!sti.unit) classCodegen.genPropertyOnStack(this, expressionCodegen.context, property.descriptor, propertyOwnerType, ownerVar)
invokeinterface(kOutputType.internalName, invokeinterface(kOutputType.internalName,
"encode" + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue", CallingConventions.encode + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + CallingConventions.elementPostfix,
"(" + descType.descriptor + "I" + "(" + descType.descriptor + "I" +
(if (useSerializer) kSerialSaverType.descriptor else "") + (if (useSerializer) kSerialSaverType.descriptor else "") +
(if (sti.unit) "" else sti.type.descriptor) + ")V") (if (sti.unit) "" else sti.type.descriptor) + ")V")
@@ -94,7 +108,7 @@ internal fun InstructionAdapter.buildInternalConstructorDesc(propsStartVar: Int,
load(propVar, propertyType) load(propVar, propertyType)
propVar += propertyType.size propVar += propertyType.size
} }
constructorDesc.append("Lkotlinx/serialization/SerializationConstructorMarker;)V") constructorDesc.append("Lkotlinx/serialization/$SERIAL_CTOR_MARKER_NAME;)V")
aconst(null) aconst(null)
return constructorDesc.toString() return constructorDesc.toString()
} }
@@ -110,10 +124,10 @@ internal fun ImplementationBodyCodegen.generateMethod(function: FunctionDescript
} }
internal val enumSerializerId = ClassId(internalPackageFqName, Name.identifier("EnumSerializer")) internal val enumSerializerId = ClassId(internalPackageFqName, Name.identifier(SpecialBuiltins.enumSerializer))
internal val polymorphicSerializerId = ClassId(packageFqName, Name.identifier("PolymorphicSerializer")) internal val polymorphicSerializerId = ClassId(packageFqName, Name.identifier(SpecialBuiltins.polymorphicSerializer))
internal val referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier("ReferenceArraySerializer")) internal val referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier(SpecialBuiltins.referenceArraySerializer))
internal val contextSerializerId = ClassId(packageFqName, Name.identifier("ContextSerializer")) internal val contextSerializerId = ClassId(packageFqName, Name.identifier(SpecialBuiltins.contextSerializer))
internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo, varIndexStart: Int): Boolean { internal fun InstructionAdapter.stackValueSerializerInstanceFromClass(codegen: ClassBodyCodegen, sti: JVMSerialTypeInfo, varIndexStart: Int): Boolean {
@@ -184,7 +198,7 @@ internal fun stackValueSerializerInstance(codegen: ClassBodyCodegen, module: Mod
assert(stackValueSerializerInstance(codegen, module, argType, argSerializer, this, argType.genericIndex, genericSerializerFieldGetter)) assert(stackValueSerializerInstance(codegen, module, argType, argSerializer, this, argType.genericIndex, genericSerializerFieldGetter))
// wrap into nullable serializer if argType is nullable // wrap into nullable serializer if argType is nullable
if (argType.isMarkedNullable) { if (argType.isMarkedNullable) {
invokestatic("kotlinx/serialization/internal/BuiltinSerializersKt", "makeNullable", invokestatic("kotlinx/serialization/internal/BuiltinSerializersKt", "makeNullable", // todo: extract?
"(" + kSerializerType.descriptor + ")" + kSerializerType.descriptor, false) "(" + kSerializerType.descriptor + ")" + kSerializerType.descriptor, false)
} }
@@ -22,11 +22,8 @@ import org.jetbrains.kotlin.psi.ValueArgument
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.resolve.KSerializerDescriptorResolver import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.typeArgPrefix import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.typeArgPrefix
import org.jetbrains.kotlinx.serialization.compiler.resolve.annotationsWithArguments
import org.jetbrains.kotlinx.serialization.compiler.resolve.getSerializableClassDescriptorBySerializer
import org.jetbrains.kotlinx.serialization.compiler.resolve.isInternalSerializable
import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes.* import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
@@ -85,13 +82,18 @@ class SerializerCodegenImpl(
if (property.transient) continue if (property.transient) continue
load(classDescVar, descImplType) load(classDescVar, descImplType)
aconst(property.name) aconst(property.name)
invokevirtual(descImplType.internalName, "addElement", "(Ljava/lang/String;)V", false) invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;)V", false)
// pushing annotations // pushing annotations
for ((annotationClass, args, consParams) in property.annotationsWithArguments) { for ((annotationClass, args, consParams) in property.annotationsWithArguments) {
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet") if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
load(classDescVar, descImplType) load(classDescVar, descImplType)
expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams) expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
invokevirtual(descImplType.internalName, "pushAnnotation", "(Ljava/lang/annotation/Annotation;)V", false) invokevirtual(
descImplType.internalName,
CallingConventions.addAnnotation,
"(Ljava/lang/annotation/Annotation;)V",
false
)
} }
} }
// add annotations on class itself // add annotations on class itself
@@ -99,7 +101,12 @@ class SerializerCodegenImpl(
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet") if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
load(classDescVar, descImplType) load(classDescVar, descImplType)
expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams) expr.generateSyntheticAnnotationOnStack(annotationClass, args, consParams)
invokevirtual(descImplType.internalName, "pushClassAnnotation", "(Ljava/lang/annotation/Annotation;)V", false) invokevirtual(
descImplType.internalName,
CallingConventions.addClassAnnotation,
"(Ljava/lang/annotation/Annotation;)V",
false
)
} }
load(classDescVar, descImplType) load(classDescVar, descImplType)
putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor) putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
@@ -111,7 +118,8 @@ class SerializerCodegenImpl(
args: List<ValueArgument>, args: List<ValueArgument>,
ctorParams: List<ValueParameterDescriptor> ctorParams: List<ValueParameterDescriptor>
) { ) {
val implType = codegen.typeMapper.mapType(annotationClass).internalName + "\$" + KSerializerDescriptorResolver.IMPL_NAME.identifier val implType =
codegen.typeMapper.mapType(annotationClass).internalName + "\$" + SerialEntityNames.IMPL_NAME.identifier
with(v) { with(v) {
// new Annotation$Impl(...) // new Annotation$Impl(...)
anew(Type.getObjectType(implType)) anew(Type.getObjectType(implType))
@@ -155,7 +163,8 @@ class SerializerCodegenImpl(
load(outputVar, kOutputType) load(outputVar, kOutputType)
load(descVar, descType) load(descVar, descType)
genArrayOfTypeParametersSerializers() genArrayOfTypeParametersSerializers()
invokeinterface(kOutputType.internalName, "beginStructure", invokeinterface(
kOutputType.internalName, CallingConventions.begin,
"(" + descType.descriptor + kSerializerArrayType.descriptor + "(" + descType.descriptor + kSerializerArrayType.descriptor +
")" + kOutputType.descriptor) ")" + kOutputType.descriptor)
store(outputVar, kOutputType) store(outputVar, kOutputType)
@@ -171,7 +180,8 @@ class SerializerCodegenImpl(
sig.append(kSerializerType.descriptor) sig.append(kSerializerType.descriptor)
} }
sig.append(")V") sig.append(")V")
invokevirtual(objType.internalName, KSerializerDescriptorResolver.WRITE_SELF_NAME.asString(), invokevirtual(
objType.internalName, SerialEntityNames.WRITE_SELF_NAME.asString(),
sig.toString(), false) sig.toString(), false)
} }
else { else {
@@ -190,7 +200,8 @@ class SerializerCodegenImpl(
// output.writeEnd(classDesc) // output.writeEnd(classDesc)
load(outputVar, kOutputType) load(outputVar, kOutputType)
load(descVar, descType) load(descVar, descType)
invokeinterface(kOutputType.internalName, "endStructure", invokeinterface(
kOutputType.internalName, CallingConventions.end,
"(" + descType.descriptor + ")V") "(" + descType.descriptor + ")V")
// return // return
areturn(Type.VOID_TYPE) areturn(Type.VOID_TYPE)
@@ -245,7 +256,8 @@ class SerializerCodegenImpl(
load(inputVar, kInputType) load(inputVar, kInputType)
load(descVar, descType) load(descVar, descType)
genArrayOfTypeParametersSerializers() genArrayOfTypeParametersSerializers()
invokeinterface(kInputType.internalName, "beginStructure", invokeinterface(
kInputType.internalName, CallingConventions.begin,
"(" + descType.descriptor + kSerializerArrayType.descriptor + "(" + descType.descriptor + kSerializerArrayType.descriptor +
")" + kInputType.descriptor) ")" + kInputType.descriptor)
store(inputVar, kInputType) store(inputVar, kInputType)
@@ -254,7 +266,8 @@ class SerializerCodegenImpl(
visitLabel(readElementLabel) visitLabel(readElementLabel)
load(inputVar, kInputType) load(inputVar, kInputType)
load(descVar, descType) load(descVar, descType)
invokeinterface(kInputType.internalName, "decodeElement", invokeinterface(
kInputType.internalName, CallingConventions.decodeElementIndex,
"(" + descType.descriptor + ")I") "(" + descType.descriptor + ")I")
store(indexVar, Type.INT_TYPE) store(indexVar, Type.INT_TYPE)
// switch(index) // switch(index)
@@ -297,7 +310,7 @@ class SerializerCodegenImpl(
fun produceCall(update: Boolean) { fun produceCall(update: Boolean) {
invokeinterface(kInputType.internalName, invokeinterface(kInputType.internalName,
(if (update) "update" else "decode") + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue", (if (update) CallingConventions.update else CallingConventions.decode) + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + CallingConventions.elementPostfix,
"(" + descType.descriptor + "I" + "(" + descType.descriptor + "I" +
(if (useSerializer) kSerialLoaderType.descriptor else "") (if (useSerializer) kSerialLoaderType.descriptor else "")
+ (if (unknownSer) AsmTypes.K_CLASS_TYPE.descriptor else "") + (if (unknownSer) AsmTypes.K_CLASS_TYPE.descriptor else "")
@@ -351,7 +364,7 @@ class SerializerCodegenImpl(
visitLabel(readEndLabel) visitLabel(readEndLabel)
load(inputVar, kInputType) load(inputVar, kInputType)
load(descVar, descType) load(descVar, descType)
invokeinterface(kInputType.internalName, "endStructure", invokeinterface(kInputType.internalName, CallingConventions.end,
"(" + descType.descriptor + ")V") "(" + descType.descriptor + ")V")
if (!serializableDescriptor.isInternalSerializable) { if (!serializableDescriptor.isInternalSerializable) {
//validate all required (constructor) fields //validate all required (constructor) fields
@@ -27,19 +27,20 @@ import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlinx.serialization.compiler.resolve.* import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName
import java.util.* import java.util.*
class SerializationResolveExtension : SyntheticResolveExtension { class SerializationResolveExtension : SyntheticResolveExtension {
override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> = when { override fun getSyntheticNestedClassNames(thisDescriptor: ClassDescriptor): List<Name> = when {
thisDescriptor.annotations.hasAnnotation(serialInfoFqName) -> listOf(KSerializerDescriptorResolver.IMPL_NAME) thisDescriptor.annotations.hasAnnotation(serialInfoFqName) -> listOf(SerialEntityNames.IMPL_NAME)
thisDescriptor.isInternalSerializable && !thisDescriptor.hasCompanionObjectAsSerializer -> thisDescriptor.isInternalSerializable && !thisDescriptor.hasCompanionObjectAsSerializer ->
listOf(KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME) listOf(SerialEntityNames.SERIALIZER_CLASS_NAME)
else -> listOf() else -> listOf()
} }
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> = when { override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> = when {
thisDescriptor.isCompanionObject && getSerializableClassDescriptorByCompanion(thisDescriptor) != null -> thisDescriptor.isCompanionObject && getSerializableClassDescriptorByCompanion(thisDescriptor) != null ->
listOf(KSerializerDescriptorResolver.SERIALIZER_PROVIDER_NAME) listOf(SerialEntityNames.SERIALIZER_PROVIDER_NAME)
else -> emptyList() else -> emptyList()
} }
@@ -50,10 +51,10 @@ class SerializationResolveExtension : SyntheticResolveExtension {
declarationProvider: ClassMemberDeclarationProvider, declarationProvider: ClassMemberDeclarationProvider,
result: MutableSet<ClassDescriptor> result: MutableSet<ClassDescriptor>
) { ) {
if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && name == KSerializerDescriptorResolver.IMPL_NAME) if (thisDescriptor.annotations.hasAnnotation(serialInfoFqName) && name == SerialEntityNames.IMPL_NAME)
result.add(KSerializerDescriptorResolver.addSerialInfoImplClass(thisDescriptor, declarationProvider, ctx)) result.add(KSerializerDescriptorResolver.addSerialInfoImplClass(thisDescriptor, declarationProvider, ctx))
else if (thisDescriptor.isInternalSerializable && name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME && else if (thisDescriptor.isInternalSerializable && name == SerialEntityNames.SERIALIZER_CLASS_NAME &&
result.none { it.name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME } result.none { it.name == SerialEntityNames.SERIALIZER_CLASS_NAME }
) )
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx)) result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
return return
@@ -30,23 +30,16 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.descType import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.packageFqName
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.internalPackageFqName
internal val packageFqName = FqName("kotlinx.serialization")
internal val internalPackageFqName = FqName("kotlinx.serialization.internal")
// ---- kotlin.serialization.KSerializer
internal val kSerializerName = Name.identifier("KSerializer")
internal val kSerializerConstructorMarkerName = Name.identifier("SerializationConstructorMarker")
internal val kSerializerFqName = packageFqName.child(kSerializerName)
fun isKSerializer(type: KotlinType?): Boolean = fun isKSerializer(type: KotlinType?): Boolean =
type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, kSerializerFqName) type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, SerialEntityNames.KSERIALIZER_NAME_FQ)
fun ClassDescriptor.getKSerializerDescriptor(): ClassDescriptor = fun ClassDescriptor.getKSerializerDescriptor(): ClassDescriptor =
module.findClassAcrossModuleDependencies(ClassId(packageFqName, kSerializerName))!! module.findClassAcrossModuleDependencies(ClassId(packageFqName, SerialEntityNames.KSERIALIZER_NAME))!!
fun ClassDescriptor.getKSerializerType(argument: SimpleType): SimpleType { fun ClassDescriptor.getKSerializerType(argument: SimpleType): SimpleType {
@@ -61,61 +54,23 @@ internal fun extractKSerializerArgumentFromImplementation(implementationClass: C
return kSerializerSupertype.arguments.first().type return kSerializerSupertype.arguments.first().type
} }
// ---- java.io.Serializable
internal val javaIOPackageFqName = FqName("java.io")
internal val javaSerializableName = Name.identifier("Serializable")
internal val javaSerializableFqName = javaIOPackageFqName.child(javaSerializableName)
fun isJavaSerializable(type: KotlinType?): Boolean =
type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, javaSerializableFqName)
fun ClassDescriptor.getJavaSerializableDescriptor(): ClassDescriptor? =
module.findClassAcrossModuleDependencies(ClassId(javaIOPackageFqName, javaSerializableName))
// null on JS frontend
fun ClassDescriptor.getJavaSerializableType(): SimpleType? =
getJavaSerializableDescriptor()?.let { KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, it, emptyList()) }
// ---- kotlin.serialization.Serializable(with=xxx)
internal val serializableAnnotationFqName = FqName("kotlinx.serialization.Serializable")
internal val Annotations.serializableWith: KotlinType? internal val Annotations.serializableWith: KotlinType?
get() = findAnnotationValue(serializableAnnotationFqName, "with") get() = findAnnotationValue(SerializationAnnotations.serializableAnnotationFqName, "with")
// ---- kotlin.serialization.Serializer(forClass=xxx)
internal val serializerAnnotationFqName = FqName("kotlinx.serialization.Serializer")
internal val Annotations.serializerForClass: KotlinType? internal val Annotations.serializerForClass: KotlinType?
get() = findAnnotationValue(serializerAnnotationFqName, "forClass") get() = findAnnotationValue(SerializationAnnotations.serializerAnnotationFqName, "forClass")
// ---- kotlin.serialization.SerialName(value=xxx)
internal val serialNameAnnotationFqName = FqName("kotlinx.serialization.SerialName")
val Annotations.serialNameValue: String? val Annotations.serialNameValue: String?
get() { get() {
val value = findAnnotationValue<String?>(serialNameAnnotationFqName, "value") val value = findAnnotationValue<String?>(SerializationAnnotations.serialNameAnnotationFqName, "value")
return value return value
} }
// ---- kotlin.serialization.Optional
internal val serialOptionalFqName = FqName("kotlinx.serialization.Optional")
val Annotations.serialOptional: Boolean val Annotations.serialOptional: Boolean
get() = hasAnnotation(serialOptionalFqName) get() = hasAnnotation(SerializationAnnotations.serialOptionalFqName)
// ---- kotlin.serialization.Transient
internal val serialTransientFqName = FqName("kotlinx.serialization.Transient")
val Annotations.serialTransient: Boolean val Annotations.serialTransient: Boolean
get() = hasAnnotation(serialTransientFqName) get() = hasAnnotation(SerializationAnnotations.serialTransientFqName)
internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo")
// ---------------------------------------- // ----------------------------------------
@@ -126,10 +81,10 @@ val KotlinType?.toClassDescriptor: ClassDescriptor?
val ClassDescriptor.isInternalSerializable: Boolean //todo normal checking val ClassDescriptor.isInternalSerializable: Boolean //todo normal checking
get() { get() {
if (!annotations.hasAnnotation(serializableAnnotationFqName)) return false if (!annotations.hasAnnotation(SerializationAnnotations.serializableAnnotationFqName)) return false
// If provided descriptor is lazy, carefully look at psi in order not to trigger full resolve which may be recursive. // If provided descriptor is lazy, carefully look at psi in order not to trigger full resolve which may be recursive.
// Otherwise, this descriptor is deserialized from another module and it is OK to check value right away. // Otherwise, this descriptor is deserialized from another module and it is OK to check value right away.
val lazyDesc = annotations.findAnnotation(serializableAnnotationFqName) val lazyDesc = annotations.findAnnotation(SerializationAnnotations.serializableAnnotationFqName)
as? LazyAnnotationDescriptor ?: return (annotations.serializableWith == null) as? LazyAnnotationDescriptor ?: return (annotations.serializableWith == null)
val psi = lazyDesc.annotationEntry val psi = lazyDesc.annotationEntry
return psi.valueArguments.isEmpty() return psi.valueArguments.isEmpty()
@@ -146,7 +101,7 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
if (hasCompanionObjectAsSerializer) return companionObjectDescriptor?.defaultType if (hasCompanionObjectAsSerializer) return companionObjectDescriptor?.defaultType
// $serializer nested class // $serializer nested class
return this.unsubstitutedMemberScope return this.unsubstitutedMemberScope
.getDescriptorsFiltered(nameFilter = {it == SERIALIZER_CLASS_NAME}) .getDescriptorsFiltered(nameFilter = {it == SerialEntityNames.SERIALIZER_CLASS_NAME})
.filterIsInstance<ClassDescriptor>().singleOrNull()?.defaultType .filterIsInstance<ClassDescriptor>().singleOrNull()?.defaultType
} }
return null return null
@@ -158,7 +113,7 @@ internal val ClassDescriptor.hasCompanionObjectAsSerializer: Boolean
internal fun checkSerializerNullability(classType: KotlinType, serializerType: KotlinType): KotlinType { internal fun checkSerializerNullability(classType: KotlinType, serializerType: KotlinType): KotlinType {
val castedToKSerial = requireNotNull( val castedToKSerial = requireNotNull(
serializerType.supertypes().find { isKSerializer(it) }, serializerType.supertypes().find { isKSerializer(it) },
{ "KSerializer is not a supertype of $serializerType" } { "${KSERIALIZER_CLASS} is not a supertype of $serializerType" }
) )
if (!classType.isMarkedNullable && castedToKSerial.arguments.first().type.isMarkedNullable) if (!classType.isMarkedNullable && castedToKSerial.arguments.first().type.isMarkedNullable)
throw IllegalStateException("Can't serialize non-nullable field of type ${classType} with nullable serializer ${serializerType}") throw IllegalStateException("Can't serialize non-nullable field of type ${classType} with nullable serializer ${serializerType}")
@@ -186,7 +141,7 @@ fun getSerializableClassDescriptorByCompanion(thisDescriptor: ClassDescriptor):
fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? { fun getSerializableClassDescriptorBySerializer(serializerDescriptor: ClassDescriptor): ClassDescriptor? {
val serializerForClass = serializerDescriptor.annotations.serializerForClass val serializerForClass = serializerDescriptor.annotations.serializerForClass
if (serializerForClass != null) return serializerForClass.toClassDescriptor if (serializerForClass != null) return serializerForClass.toClassDescriptor
if (serializerDescriptor.name != SERIALIZER_CLASS_NAME) return null if (serializerDescriptor.name != SerialEntityNames.SERIALIZER_CLASS_NAME) return null
val classDescriptor = (serializerDescriptor.containingDeclaration as? ClassDescriptor) ?: return null val classDescriptor = (serializerDescriptor.containingDeclaration as? ClassDescriptor) ?: return null
if (!classDescriptor.isInternalSerializable) return null if (!classDescriptor.isInternalSerializable) return null
return classDescriptor return classDescriptor
@@ -218,7 +173,7 @@ inline fun <reified R> Annotations.findAnnotationValue(annotationFqName: FqName,
// Search utils // Search utils
fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor = fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor =
module.findClassAcrossModuleDependencies(ClassId(packageFqName, kSerializerConstructorMarkerName))!! module.findClassAcrossModuleDependencies(ClassId(packageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME))!!
fun ModuleDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) = fun ModuleDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) =
requireNotNull( requireNotNull(
@@ -240,7 +195,7 @@ fun ClassDescriptor.toSimpleType(nullable: Boolean = true) = KotlinTypeFactory.s
fun Annotated.annotationsWithArguments(): List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> = fun Annotated.annotationsWithArguments(): List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
annotations.asSequence() annotations.asSequence()
.filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(serialInfoFqName) == true } .filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(SerializationAnnotations.serialInfoFqName) == true }
.filterIsInstance<LazyAnnotationDescriptor>() .filterIsInstance<LazyAnnotationDescriptor>()
.mapNotNull { annDesc -> .mapNotNull { annDesc ->
annDesc.type.toClassDescriptor?.let { annDesc.type.toClassDescriptor?.let {
@@ -34,26 +34,14 @@ import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.typeUtil.createProjection import org.jetbrains.kotlin.types.typeUtil.createProjection
import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.SERIALIZER_CLASS_NAME
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.IMPL_NAME
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.typeArgPrefix
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName
import java.util.* import java.util.*
object KSerializerDescriptorResolver { object KSerializerDescriptorResolver {
val SERIAL_DESC_FIELD = "serialClassDesc"
val SAVE = "serialize"
val LOAD = "deserialize"
val SERIALIZER_CLASS = "\$serializer"
internal val typeArgPrefix = "typeSerial"
val SERIAL_DESC_FIELD_NAME = Name.identifier(SERIAL_DESC_FIELD)
val SAVE_NAME = Name.identifier(SAVE)
val LOAD_NAME = Name.identifier(LOAD)
val DUMMY_PARAM_NAME = Name.identifier("serializationConstructorMarker")
val WRITE_SELF_NAME = Name.identifier("write\$Self") //todo: add it as a supertype to synthetic resolving
val IMPL_NAME = Name.identifier("Impl")
val SERIALIZER_CLASS_NAME = Name.identifier(SERIALIZER_CLASS)
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
fun isSerialInfoImpl(thisDescriptor: ClassDescriptor): Boolean { fun isSerialInfoImpl(thisDescriptor: ClassDescriptor): Boolean {
return thisDescriptor.name == IMPL_NAME return thisDescriptor.name == IMPL_NAME
&& thisDescriptor.containingDeclaration is LazyClassDescriptor && thisDescriptor.containingDeclaration is LazyClassDescriptor
@@ -128,7 +116,7 @@ object KSerializerDescriptorResolver {
name: Name, name: Name,
result: MutableSet<PropertyDescriptor>) { result: MutableSet<PropertyDescriptor>) {
val classDescriptor = getSerializableClassDescriptorBySerializer(thisDescriptor) ?: return val classDescriptor = getSerializableClassDescriptorBySerializer(thisDescriptor) ?: return
if (name == SERIAL_DESC_FIELD_NAME && result.none(thisDescriptor::checkSerializableClassPropertyResult) && if (name == SerialEntityNames.SERIAL_DESC_FIELD_NAME && result.none(thisDescriptor::checkSerializableClassPropertyResult) &&
fromSupertypes.none { thisDescriptor.checkSerializableClassPropertyResult(it) && it.modality == Modality.FINAL }) fromSupertypes.none { thisDescriptor.checkSerializableClassPropertyResult(it) && it.modality == Modality.FINAL })
result.add(createSerializableClassPropertyDescriptor(thisDescriptor, classDescriptor)) result.add(createSerializableClassPropertyDescriptor(thisDescriptor, classDescriptor))
@@ -142,7 +130,7 @@ object KSerializerDescriptorResolver {
) { ) {
val classDescriptor = getSerializableClassDescriptorByCompanion(thisDescriptor) ?: return val classDescriptor = getSerializableClassDescriptorByCompanion(thisDescriptor) ?: return
if (name == SERIALIZER_PROVIDER_NAME && result.none { it.valueParameters.size == classDescriptor.declaredTypeParameters.size }) { if (name == SerialEntityNames.SERIALIZER_PROVIDER_NAME && result.none { it.valueParameters.size == classDescriptor.declaredTypeParameters.size }) {
result.add(createSerializerGetterDescriptor(thisDescriptor, classDescriptor)) result.add(createSerializerGetterDescriptor(thisDescriptor, classDescriptor))
} }
} }
@@ -159,25 +147,25 @@ object KSerializerDescriptorResolver {
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL } fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
} }
if (name == SAVE_NAME && if (name == SerialEntityNames.SAVE_NAME &&
shouldAddSerializerFunction { classDescriptor.checkSaveMethodParameters(it.valueParameters) }) { shouldAddSerializerFunction { classDescriptor.checkSaveMethodParameters(it.valueParameters) }) {
result.add(createSaveFunctionDescriptor(thisDescriptor, classDescriptor)) result.add(createSaveFunctionDescriptor(thisDescriptor, classDescriptor))
} }
if (name == LOAD_NAME && if (name == SerialEntityNames.LOAD_NAME &&
shouldAddSerializerFunction { classDescriptor.checkLoadMethodParameters(it.valueParameters) }) { shouldAddSerializerFunction { classDescriptor.checkLoadMethodParameters(it.valueParameters) }) {
result.add(createLoadFunctionDescriptor(thisDescriptor, classDescriptor)) result.add(createLoadFunctionDescriptor(thisDescriptor, classDescriptor))
} }
} }
fun createSerializableClassPropertyDescriptor(companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor): PropertyDescriptor = fun createSerializableClassPropertyDescriptor(companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor): PropertyDescriptor =
doCreateSerializerProperty(companionDescriptor, classDescriptor, SERIAL_DESC_FIELD_NAME) doCreateSerializerProperty(companionDescriptor, classDescriptor, SerialEntityNames.SERIAL_DESC_FIELD_NAME)
fun createSaveFunctionDescriptor(companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor): SimpleFunctionDescriptor = fun createSaveFunctionDescriptor(companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
doCreateSerializerFunction(companionDescriptor, classDescriptor, SAVE_NAME) doCreateSerializerFunction(companionDescriptor, classDescriptor, SerialEntityNames.SAVE_NAME)
fun createLoadFunctionDescriptor(companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor): SimpleFunctionDescriptor = fun createLoadFunctionDescriptor(companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
doCreateSerializerFunction(companionDescriptor, classDescriptor, LOAD_NAME) doCreateSerializerFunction(companionDescriptor, classDescriptor, SerialEntityNames.LOAD_NAME)
private fun doCreateSerializerProperty( private fun doCreateSerializerProperty(
companionDescriptor: ClassDescriptor, companionDescriptor: ClassDescriptor,
@@ -221,7 +209,7 @@ object KSerializerDescriptorResolver {
) )
val serializableClassOnImplSite = extractKSerializerArgumentFromImplementation(companionDescriptor) val serializableClassOnImplSite = extractKSerializerArgumentFromImplementation(companionDescriptor)
?: throw AssertionError("Serializer does not implement KSerializer??") ?: throw AssertionError("Serializer does not implement ${SerialEntityNames.KSERIALIZER_CLASS}??")
val typeParam = listOf(createProjection(serializableClassOnImplSite, Variance.INVARIANT, null)) val typeParam = listOf(createProjection(serializableClassOnImplSite, Variance.INVARIANT, null))
val functionFromSerializer = companionDescriptor.getKSerializerDescriptor().getMemberScope(typeParam) val functionFromSerializer = companionDescriptor.getKSerializerDescriptor().getMemberScope(typeParam)
@@ -265,7 +253,7 @@ object KSerializerDescriptorResolver {
consParams.add(ValueParameterDescriptorImpl(functionDescriptor, null, i++, prop.annotations, prop.name, prop.type.makeNullableIfNotPrimitive(), false, false, consParams.add(ValueParameterDescriptorImpl(functionDescriptor, null, i++, prop.annotations, prop.name, prop.type.makeNullableIfNotPrimitive(), false, false,
false, null, functionDescriptor.source)) false, null, functionDescriptor.source))
} }
consParams.add(ValueParameterDescriptorImpl(functionDescriptor, null, i++, Annotations.EMPTY, DUMMY_PARAM_NAME, markerType, false, consParams.add(ValueParameterDescriptorImpl(functionDescriptor, null, i++, Annotations.EMPTY, SerialEntityNames.dummyParamName, markerType, false,
false, false, null, functionDescriptor.source)) false, false, null, functionDescriptor.source))
functionDescriptor.initialize( functionDescriptor.initialize(
@@ -287,7 +275,7 @@ object KSerializerDescriptorResolver {
false, false,
classDescriptor.source classDescriptor.source
) )
val serializerClass = classDescriptor.getClassFromSerializationPackage("KSerializer") val serializerClass = classDescriptor.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)
val targs = mutableListOf<TypeParameterDescriptor>() val targs = mutableListOf<TypeParameterDescriptor>()
val args = serializableDescriptor.declaredTypeParameters.mapIndexed { index, param -> val args = serializableDescriptor.declaredTypeParameters.mapIndexed { index, param ->
val targ = TypeParameterDescriptorImpl.createWithDefaultBound( val targ = TypeParameterDescriptorImpl.createWithDefaultBound(
@@ -314,11 +302,11 @@ object KSerializerDescriptorResolver {
val f = SimpleFunctionDescriptorImpl.create( val f = SimpleFunctionDescriptorImpl.create(
thisClass, thisClass,
Annotations.EMPTY, Annotations.EMPTY,
SERIALIZER_PROVIDER_NAME, SerialEntityNames.SERIALIZER_PROVIDER_NAME,
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
thisClass.source thisClass.source
) )
val serializerClass = thisClass.getClassFromSerializationPackage("KSerializer") val serializerClass = thisClass.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)
val args = mutableListOf<ValueParameterDescriptor>() val args = mutableListOf<ValueParameterDescriptor>()
val typeArgs = mutableListOf<TypeParameterDescriptor>() val typeArgs = mutableListOf<TypeParameterDescriptor>()
@@ -368,7 +356,7 @@ object KSerializerDescriptorResolver {
else this.makeNullable() else this.makeNullable()
fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): FunctionDescriptor { fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): FunctionDescriptor {
val f = SimpleFunctionDescriptorImpl.create(thisClass, Annotations.EMPTY, WRITE_SELF_NAME, CallableMemberDescriptor.Kind.SYNTHESIZED, thisClass.source) val f = SimpleFunctionDescriptorImpl.create(thisClass, Annotations.EMPTY, SerialEntityNames.WRITE_SELF_NAME, CallableMemberDescriptor.Kind.SYNTHESIZED, thisClass.source)
val returnType = f.builtIns.unitType val returnType = f.builtIns.unitType
val args = mutableListOf<ValueParameterDescriptor>() val args = mutableListOf<ValueParameterDescriptor>()
@@ -379,7 +367,7 @@ object KSerializerDescriptorResolver {
i++, i++,
Annotations.EMPTY, Annotations.EMPTY,
Name.identifier("output"), Name.identifier("output"),
thisClass.getClassFromSerializationPackage("StructureEncoder").toSimpleType(false), thisClass.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS).toSimpleType(false),
false, false,
false, false,
false, false,
@@ -393,7 +381,7 @@ object KSerializerDescriptorResolver {
i++, i++,
Annotations.EMPTY, Annotations.EMPTY,
Name.identifier("serialDesc"), Name.identifier("serialDesc"),
thisClass.getClassFromSerializationPackage("SerialDescriptor").toSimpleType(false), thisClass.getClassFromSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS).toSimpleType(false),
false, false,
false, false,
false, false,
@@ -401,7 +389,7 @@ object KSerializerDescriptorResolver {
f.source) f.source)
) )
val kSerialClassDesc = thisClass.getClassFromSerializationPackage("KSerializer") val kSerialClassDesc = thisClass.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)
thisClass.declaredTypeParameters.forEach { thisClass.declaredTypeParameters.forEach {
val typeArgument = TypeProjectionImpl(it.defaultType) val typeArgument = TypeProjectionImpl(it.defaultType)
@@ -0,0 +1,84 @@
package org.jetbrains.kotlinx.serialization.compiler.resolve
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
object SerializationPackages {
internal val packageFqName = FqName("kotlinx.serialization")
internal val internalPackageFqName = FqName("kotlinx.serialization.internal")
internal val builtinsPackageFqName = FqName("kotlinx.serialization.builtins")
}
object SerializationAnnotations {
internal val serializableAnnotationFqName = FqName("kotlinx.serialization.Serializable")
internal val serializerAnnotationFqName = FqName("kotlinx.serialization.Serializer")
internal val serialNameAnnotationFqName = FqName("kotlinx.serialization.SerialName")
internal val serialOptionalFqName = FqName("kotlinx.serialization.Optional")
internal val serialTransientFqName = FqName("kotlinx.serialization.Transient")
internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo")
}
object SerialEntityNames {
const val KSERIALIZER_CLASS = "KSerializer"
const val SERIAL_DESC_FIELD = "descriptor"
const val SAVE = "serialize"
const val LOAD = "deserialize"
const val SERIALIZER_CLASS = "\$serializer"
// classes
val KSERIALIZER_NAME = Name.identifier(KSERIALIZER_CLASS)
val SERIAL_CTOR_MARKER_NAME = Name.identifier("SerializationConstructorMarker")
val KSERIALIZER_NAME_FQ = SerializationPackages.packageFqName.child(KSERIALIZER_NAME)
val SERIALIZER_CLASS_NAME = Name.identifier(SERIALIZER_CLASS)
val IMPL_NAME = Name.identifier("Impl")
const val ENCODER_CLASS = "Encoder"
const val STRUCTURE_ENCODER_CLASS = "StructureEncoder"
const val DECODER_CLASS = "Decoder"
const val STRUCTURE_DECODER_CLASS = "StructureDecoder"
const val SERIAL_SAVER_CLASS = "SerializationStrategy"
const val SERIAL_LOADER_CLASS = "SerializationStrategy"
const val SERIAL_DESCRIPTOR_CLASS = "SerialDescriptor"
const val SERIAL_DESCRIPTOR_CLASS_IMPL = "SerialClassDescImpl"
//exceptions
const val SERIAL_EXC = "SerializationException"
const val MISSING_FIELD_EXC = "MissingFieldException"
const val UNKNOWN_FIELD_EXC = "UnknownFieldException"
// functions
val SERIAL_DESC_FIELD_NAME = Name.identifier(SERIAL_DESC_FIELD)
val SAVE_NAME = Name.identifier(SAVE)
val LOAD_NAME = Name.identifier(LOAD)
val WRITE_SELF_NAME = Name.identifier("write\$Self")
val SERIALIZER_PROVIDER_NAME = Name.identifier("serializer")
// parameters
val dummyParamName = Name.identifier("serializationConstructorMarker")
internal const val typeArgPrefix = "typeSerial"
}
object SpecialBuiltins {
const val referenceArraySerializer = "ReferenceArraySerializer"
const val enumSerializer = "EnumSerializer"
const val polymorphicSerializer = "PolymorphicSerializer"
const val contextSerializer = "ContextSerializer"
const val nullableSerializer = "NullableSerializer"
}
object CallingConventions {
const val begin = "beginStructure"
const val end = "endStructure"
const val decode = "decode"
const val update = "update"
const val encode = "encode"
const val decodeElementIndex = "decodeElement"
const val elementPostfix = "ElementValue"
const val addElement = "addElement"
const val addAnnotation = "pushAnnotation"
const val addClassAnnotation = "pushClassAnnotation"
}