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.FunctionDescriptor
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
abstract class SerializableCompanionCodegen(
protected val companionDescriptor: ClassDescriptor /*declaration: KtPureClassOrObject*/
protected val companionDescriptor: ClassDescriptor
) {
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.KSerializerDescriptorResolver.createTypedSerializerConstructorDescriptor
abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContext: BindingContext) {
protected val serializerDescriptor: ClassDescriptor = declaration.findClassDescriptor(bindingContext)
abstract class SerializerCodegen(
protected val serializerDescriptor: ClassDescriptor,
bindingContext: BindingContext
) {
// protected val serializerDescriptor: ClassDescriptor = declaration.findClassDescriptor(bindingContext)
protected val serializableDescriptor: ClassDescriptor = getSerializableClassDescriptorBySerializer(serializerDescriptor)!!
protected val serialName: String = serializableDescriptor.annotations.serialNameValue ?: serializableDescriptor.fqNameUnsafe.asString()
protected val properties = SerializableProperties(serializableDescriptor, bindingContext)
@@ -66,7 +69,7 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
return !found
}
protected val serialDescPropertyDescriptor = getPropertyToGenerate(serializerDescriptor, KSerializerDescriptorResolver.SERIAL_DESC_FIELD,
protected val serialDescPropertyDescriptor = getPropertyToGenerate(serializerDescriptor, SerialEntityNames.SERIAL_DESC_FIELD,
serializerDescriptor::checkSerializableClassPropertyResult)
protected abstract fun generateSerialDesc()
@@ -86,7 +89,7 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
}
private fun generateSaveIfNeeded(): Boolean {
val function = getMemberToGenerate(serializerDescriptor, KSerializerDescriptorResolver.SAVE,
val function = getMemberToGenerate(serializerDescriptor, SerialEntityNames.SAVE,
serializerDescriptor::checkSaveMethodResult, serializerDescriptor::checkSaveMethodParameters)
?: return false
generateSave(function)
@@ -94,7 +97,7 @@ abstract class SerializerCodegen(declaration: KtPureClassOrObject, bindingContex
}
private fun generateLoadIfNeeded(): Boolean {
val function = getMemberToGenerate(serializerDescriptor, KSerializerDescriptorResolver.LOAD,
val function = getMemberToGenerate(serializerDescriptor, SerialEntityNames.LOAD,
serializerDescriptor::checkLoadMethodResult, serializerDescriptor::checkLoadMethodParameters)
?: return false
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.referenceArraySerializerId
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationPackages.internalPackageFqName
open class SerialTypeInfo(
val property: SerializableProperty,
@@ -84,7 +85,7 @@ fun findTypeSerializer(module: ModuleDescriptor, kType: KotlinType): ClassDescri
if (userOverride != null) return userOverride.toClassDescriptor
if (kType.requiresPolymorphism()) return findPolymorphicSerializer(module)
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
?: findStandardKotlinTypeSerializer(module, kType) // otherwise see if there is a standard serializer
?: findEnumTypeSerializer(module, kType)
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.util.OperatorNameConventions
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.isInternalSerializable
@@ -49,7 +50,7 @@ class SerializableIrGenerator(
// Missing field exception parts
val exceptionCtor =
serializableDescriptor.getClassFromSerializationPackage("MissingFieldException")
serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC)
.unsubstitutedPrimaryConstructor!!
val exceptionCtorRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor)
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.referenceArraySerializerId
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?
object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER")
@@ -47,11 +51,11 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
override fun generateSerialDesc() {
val desc: PropertyDescriptor = serialDescPropertyDescriptor ?: return
val serialDescImplClass = serializerDescriptor
.getClassFromInternalSerializationPackage("SerialClassDescImpl")
.getClassFromInternalSerializationPackage(SERIAL_DESCRIPTOR_CLASS_IMPL)
val serialDescImplConstructor = serialDescImplClass
.unsubstitutedPrimaryConstructor!!
val addFuncS = serialDescImplClass.referenceMethod("addElement")
val addFuncS = serialDescImplClass.referenceMethod(CallingConventions.addElement)
val thisAsReceiverParameter = irClass.thisReceiver!!
lateinit var prop: IrProperty
@@ -121,7 +125,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
genericIndex: Int? = null
): IrExpression? {
val nullableSerClass =
compilerContext.symbolTable.referenceClass(module.getClassFromInternalSerializationPackage("NullableSerializer"))
compilerContext.symbolTable.referenceClass(module.getClassFromInternalSerializationPackage(SpecialBuiltins.nullableSerializer))
if (serializerClass == null) {
if (genericIndex == null) return null
return TODO("Saved serializer for generic argument")
@@ -162,14 +166,14 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
fun irThis(): IrExpression =
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 localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
// 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 ->
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)
if (innerSerial == null) {
val writeFunc =
kOutputClass.referenceMethod("encode${sti.elementMethodPrefix}ElementValue")
kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
+irInvoke(
irGet(localOutput),
writeFunc,
@@ -205,7 +209,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
irGetField(irGet(serialObjectSymbol), compilerContext.symbolTable.referenceField(property.descriptor).owner)
)
} else {
val writeFunc = kOutputClass.referenceMethod("encode${sti.elementMethodPrefix}SerializableElementValue")
val writeFunc = kOutputClass.referenceMethod("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}")
+irInvoke(
irGet(localOutput),
writeFunc,
@@ -220,12 +224,12 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
}
// output.writeEnd(serialClassDesc)
val wEndFunc = kOutputClass.referenceMethod("endStructure")
val wEndFunc = kOutputClass.referenceMethod(CallingConventions.end)
+irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc))
}
// 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 T = kType.toIrType()
val defaultPrimitive: IrExpression? = when {
@@ -251,7 +255,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
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 localSerialDesc = irTemporary(irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol), "desc")
@@ -278,7 +282,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
}
//input = input.beginStructure(...)
val beginFunc = inputClass.referenceMethod("beginStructure")
val beginFunc = inputClass.referenceMethod(CallingConventions.begin)
val call = irInvoke(
irGet(loadFunc.valueParameters[0]),
beginFunc,
@@ -290,7 +294,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
+irWhile().also { loop ->
loop.condition = flagVar.get()
loop.body = irBlock {
val readElementF = inputClass.referenceMethod("decodeElement")
val readElementF = inputClass.referenceMethod(CallingConventions.decodeElementIndex)
+irSetVar(indexVar.symbol, irInvoke(localInput.get(), readElementF, localSerialDesc.get()))
+irWhen {
// 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)
// todo: update
val decodeFuncToCall =
(if (innerSerial != null) "decode${sti.elementMethodPrefix}SerializableElementValue"
else "decode${sti.elementMethodPrefix}ElementValue")
(if (innerSerial != null) "${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}"
else "${CallingConventions.decode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}")
.let {
inputClass.referenceMethod(it)
}
@@ -326,7 +330,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
// throw exception on unknown field
val exceptionCtor =
serializableDescriptor.getClassFromSerializationPackage("UnknownFieldException")
serializableDescriptor.getClassFromSerializationPackage(UNKNOWN_FIELD_EXC)
.unsubstitutedPrimaryConstructor!!
val excClassRef = compilerContext.symbolTable.referenceConstructor(exceptionCtor)
+elseBranch(
@@ -344,7 +348,7 @@ class SerializerIrGenerator(val irClass: IrClass, override val compilerContext:
}
//input.endStructure(...)
val endFunc = inputClass.referenceMethod("endStructure")
val endFunc = inputClass.referenceMethod(CallingConventions.end)
+irInvoke(
localInput.get(),
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.bodyPropertiesDescriptorsMap
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.isInternalSerializable
@@ -49,7 +50,7 @@ class SerializableJsTranslator(
override fun generateInternalConstructor(constructorDescriptor: ClassConstructorDescriptor) {
val missingExceptionClassRef = serializableDescriptor.getClassFromSerializationPackage("MissingFieldException")
val missingExceptionClassRef = serializableDescriptor.getClassFromSerializationPackage(MISSING_FIELD_EXC)
.let { context.translateQualifiedReference(it) }
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.referenceArraySerializerId
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,
val translator: DeclarationBodyVisitor,
@@ -55,7 +57,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
override fun generateSerialDesc() {
val desc = serialDescPropertyDescriptor ?: return
val serialDescImplClass = serializerDescriptor
.getClassFromInternalSerializationPackage("SerialClassDescImpl")
.getClassFromInternalSerializationPackage(SERIAL_DESCRIPTOR_CLASS_IMPL)
val serialDescImplConstructor = serialDescImplClass
.unsubstitutedPrimaryConstructor!!
@@ -65,9 +67,9 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
translator.addInitializerStatement(assgmnt.makeStmt())
// adding elements via serialDesc.addElement(...)
val addFunc = serialDescImplClass.getFuncDesc("addElement").single()
val pushFunc = serialDescImplClass.getFuncDesc("pushAnnotation").single()
val pushClassFunc = serialDescImplClass.getFuncDesc("pushClassAnnotation").single()
val addFunc = serialDescImplClass.getFuncDesc(CallingConventions.addElement).single()
val pushFunc = serialDescImplClass.getFuncDesc(CallingConventions.addAnnotation).single()
val pushClassFunc = serialDescImplClass.getFuncDesc(CallingConventions.addClassAnnotation).single()
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor), JsThisRef())
for (prop in orderedProperties) {
@@ -120,9 +122,9 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
}
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(
kOutputClass.getFuncDesc("beginStructure").single { it.valueParameters.size == 2 })
kOutputClass.getFuncDesc(CallingConventions.begin).single { it.valueParameters.size == 2 })
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor!!), JsThisRef())
// output.writeBegin(desc, [])
@@ -148,7 +150,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val innerSerial = serializerInstance(sti.serializer, property.module, property.type, property.genericIndex)
if (innerSerial == null) {
val writeFunc =
kOutputClass.getFuncDesc("encode${sti.elementMethodPrefix}ElementValue").single()
kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}${CallingConventions.elementPostfix}").single()
.let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(writeFunc, localOutputRef),
serialClassDescRef,
@@ -157,7 +159,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
}
else {
val writeFunc =
kOutputClass.getFuncDesc("encode${sti.elementMethodPrefix}SerializableElementValue").single()
kOutputClass.getFuncDesc("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single()
.let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(writeFunc, localOutputRef),
serialClassDescRef,
@@ -168,13 +170,13 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
}
// output.writeEnd(serialClassDesc)
val wEndFunc = kOutputClass.getFuncDesc("endStructure").single()
val wEndFunc = kOutputClass.getFuncDesc(CallingConventions.end).single()
.let { ctx.getNameForDescriptor(it) }
+JsInvocation(JsNameRef(wEndFunc, localOutputRef), serialClassDescRef).makeStmt()
}
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 (genericIndex == null) return null
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 ->
val inputClass = serializerDescriptor.getClassFromSerializationPackage("StructureDecoder")
val inputClass = serializerDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_DECODER_CLASS)
val serialClassDescRef = JsNameRef(context.getNameForDescriptor(serialDescPropertyDescriptor!!), JsThisRef())
// var index = -1, readAll = false
@@ -234,7 +236,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
JsNameRef(context.scope().declareName("$typeArgPrefix$idx"), JsThisRef())
}
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)),
serialClassDescRef, JsArrayLiteral(typeParams))
+JsVars(JsVars.JsVar(inputVar.name, call))
@@ -244,7 +246,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val loopRef = JsNameRef(loop.name)
jsWhile(JsBooleanLiteral(true), {
// index = input.readElement(classDesc)
val readElementF = context.getNameForDescriptor(inputClass.getFuncDesc("decodeElement").single())
val readElementF = context.getNameForDescriptor(inputClass.getFuncDesc(CallingConventions.decodeElementIndex).single())
+JsAstUtils.assignment(
indexVar,
JsInvocation(JsNameRef(readElementF, inputVar), serialClassDescRef)
@@ -267,9 +269,9 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
val call: JsExpression = if (innerSerial == null) {
val unknownSer = (sti.elementMethodPrefix.isEmpty())
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
.single { !unknownSer || (it is FunctionDescriptor && it.valueParameters.size == 3) }
.single { !unknownSer || (it.valueParameters.size == 3) }
.let { context.getNameForDescriptor(it) }
val readArgs = mutableListOf(serialClassDescRef, JsIntLiteral(i))
if (unknownSer) readArgs.add(createGetKClassExpression(property.type.toClassDescriptor!!))
@@ -278,10 +280,10 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
else {
val notSeenTest = propNotSeenTest(bitMasks[i / 32], i)
val readFunc =
inputClass.getFuncDesc("decode${sti.elementMethodPrefix}SerializableElementValue").single()
inputClass.getFuncDesc("${CallingConventions.decode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single()
.let { context.getNameForDescriptor(it) }
val updateFunc =
inputClass.getFuncDesc("update${sti.elementMethodPrefix}SerializableElementValue").single()
inputClass.getFuncDesc("${CallingConventions.update}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}").single()
.let { context.getNameForDescriptor(it) }
JsConditional(notSeenTest,
JsInvocation(JsNameRef(readFunc, inputVar),
@@ -338,7 +340,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
}
// default: throw
default {
val excClassRef = serializableDescriptor.getClassFromSerializationPackage("UnknownFieldException")
val excClassRef = serializableDescriptor.getClassFromSerializationPackage(SerialEntityNames.UNKNOWN_FIELD_EXC)
.let { context.translateQualifiedReference(it) }
+JsThrow(JsNew(excClassRef, listOf(indexVar)))
}
@@ -346,7 +348,7 @@ class SerializerJsTranslator(declaration: KtPureClassOrObject,
}, loop)
// input.readEnd(desc)
val readEndF = inputClass.getFuncDesc("endStructure").single()
val readEndF = inputClass.getFuncDesc(CallingConventions.end).single()
.let { context.getNameForDescriptor(it) }
+JsInvocation(
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.findTypeSerializer
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.commons.InstructionAdapter
internal val descType = Type.getObjectType("kotlinx/serialization/SerialDescriptor")
internal val descImplType = Type.getObjectType("kotlinx/serialization/internal/SerialClassDescImpl")
internal val kOutputType = Type.getObjectType("kotlinx/serialization/StructureEncoder")
internal val kInputType = Type.getObjectType("kotlinx/serialization/StructureDecoder")
// todo: extract packages constants too?
internal val descType = Type.getObjectType("kotlinx/serialization/$SERIAL_DESCRIPTOR_CLASS")
internal val descImplType = Type.getObjectType("kotlinx/serialization/internal/$SERIAL_DESCRIPTOR_CLASS_IMPL")
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 kSerialLoaderType = Type.getObjectType("kotlinx/serialization/DeserializationStrategy")
internal val kSerializerType = Type.getObjectType("kotlinx/serialization/KSerializer")
internal val kSerializerArrayType = Type.getObjectType("[Lkotlinx/serialization/KSerializer;")
internal val kSerialSaverType = Type.getObjectType("kotlinx/serialization/$SERIAL_SAVER_CLASS")
internal val kSerialLoaderType = Type.getObjectType("kotlinx/serialization/$SERIAL_LOADER_CLASS")
internal val kSerializerType = Type.getObjectType("kotlinx/serialization/$KSERIALIZER_CLASS")
internal val kSerializerArrayType = Type.getObjectType("[Lkotlinx/serialization/$KSERIALIZER_CLASS;")
internal val serializationExceptionName = "kotlinx/serialization/SerializationException"
internal val serializationExceptionMissingFieldName = "kotlinx/serialization/MissingFieldException"
internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/UnknownFieldException"
internal val serializationExceptionName = "kotlinx/serialization/$SERIAL_EXC"
internal val serializationExceptionMissingFieldName = "kotlinx/serialization/$MISSING_FIELD_EXC"
internal val serializationExceptionUnknownIndexName = "kotlinx/serialization/$UNKNOWN_FIELD_EXC"
val OPT_MASK_TYPE: Type = Type.INT_TYPE
val OPT_MASK_BITS = 32
@@ -78,7 +92,7 @@ fun InstructionAdapter.genKOutputMethodCall(property: SerializableProperty, clas
else stackValueSerializerInstanceFromClass(classCodegen, sti, fromClassStartVar)
if (!sti.unit) classCodegen.genPropertyOnStack(this, expressionCodegen.context, property.descriptor, propertyOwnerType, ownerVar)
invokeinterface(kOutputType.internalName,
"encode" + sti.elementMethodPrefix + (if (useSerializer) "Serializable" else "") + "ElementValue",
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")
@@ -94,7 +108,7 @@ internal fun InstructionAdapter.buildInternalConstructorDesc(propsStartVar: Int,
load(propVar, propertyType)
propVar += propertyType.size
}
constructorDesc.append("Lkotlinx/serialization/SerializationConstructorMarker;)V")
constructorDesc.append("Lkotlinx/serialization/$SERIAL_CTOR_MARKER_NAME;)V")
aconst(null)
return constructorDesc.toString()
}
@@ -110,10 +124,10 @@ internal fun ImplementationBodyCodegen.generateMethod(function: FunctionDescript
}
internal val enumSerializerId = ClassId(internalPackageFqName, Name.identifier("EnumSerializer"))
internal val polymorphicSerializerId = ClassId(packageFqName, Name.identifier("PolymorphicSerializer"))
internal val referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier("ReferenceArraySerializer"))
internal val contextSerializerId = ClassId(packageFqName, Name.identifier("ContextSerializer"))
internal val enumSerializerId = ClassId(internalPackageFqName, Name.identifier(SpecialBuiltins.enumSerializer))
internal val polymorphicSerializerId = ClassId(packageFqName, Name.identifier(SpecialBuiltins.polymorphicSerializer))
internal val referenceArraySerializerId = ClassId(internalPackageFqName, Name.identifier(SpecialBuiltins.referenceArraySerializer))
internal val contextSerializerId = ClassId(packageFqName, Name.identifier(SpecialBuiltins.contextSerializer))
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))
// wrap into nullable serializer if argType is nullable
if (argType.isMarkedNullable) {
invokestatic("kotlinx/serialization/internal/BuiltinSerializersKt", "makeNullable",
invokestatic("kotlinx/serialization/internal/BuiltinSerializersKt", "makeNullable", // todo: extract?
"(" + 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.diagnostics.OtherOrigin
import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.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.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.typeArgPrefix
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
@@ -85,13 +82,18 @@ class SerializerCodegenImpl(
if (property.transient) continue
load(classDescVar, descImplType)
aconst(property.name)
invokevirtual(descImplType.internalName, "addElement", "(Ljava/lang/String;)V", false)
invokevirtual(descImplType.internalName, CallingConventions.addElement, "(Ljava/lang/String;)V", false)
// pushing annotations
for ((annotationClass, args, consParams) in property.annotationsWithArguments) {
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
load(classDescVar, descImplType)
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
@@ -99,7 +101,12 @@ class SerializerCodegenImpl(
if (args.size != consParams.size) throw IllegalArgumentException("Can't use arguments with defaults for serializable annotations yet")
load(classDescVar, descImplType)
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)
putstatic(serializerAsmType.internalName, serialDescField, descType.descriptor)
@@ -111,7 +118,8 @@ class SerializerCodegenImpl(
args: List<ValueArgument>,
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) {
// new Annotation$Impl(...)
anew(Type.getObjectType(implType))
@@ -155,7 +163,8 @@ class SerializerCodegenImpl(
load(outputVar, kOutputType)
load(descVar, descType)
genArrayOfTypeParametersSerializers()
invokeinterface(kOutputType.internalName, "beginStructure",
invokeinterface(
kOutputType.internalName, CallingConventions.begin,
"(" + descType.descriptor + kSerializerArrayType.descriptor +
")" + kOutputType.descriptor)
store(outputVar, kOutputType)
@@ -171,7 +180,8 @@ class SerializerCodegenImpl(
sig.append(kSerializerType.descriptor)
}
sig.append(")V")
invokevirtual(objType.internalName, KSerializerDescriptorResolver.WRITE_SELF_NAME.asString(),
invokevirtual(
objType.internalName, SerialEntityNames.WRITE_SELF_NAME.asString(),
sig.toString(), false)
}
else {
@@ -190,7 +200,8 @@ class SerializerCodegenImpl(
// output.writeEnd(classDesc)
load(outputVar, kOutputType)
load(descVar, descType)
invokeinterface(kOutputType.internalName, "endStructure",
invokeinterface(
kOutputType.internalName, CallingConventions.end,
"(" + descType.descriptor + ")V")
// return
areturn(Type.VOID_TYPE)
@@ -245,7 +256,8 @@ class SerializerCodegenImpl(
load(inputVar, kInputType)
load(descVar, descType)
genArrayOfTypeParametersSerializers()
invokeinterface(kInputType.internalName, "beginStructure",
invokeinterface(
kInputType.internalName, CallingConventions.begin,
"(" + descType.descriptor + kSerializerArrayType.descriptor +
")" + kInputType.descriptor)
store(inputVar, kInputType)
@@ -254,7 +266,8 @@ class SerializerCodegenImpl(
visitLabel(readElementLabel)
load(inputVar, kInputType)
load(descVar, descType)
invokeinterface(kInputType.internalName, "decodeElement",
invokeinterface(
kInputType.internalName, CallingConventions.decodeElementIndex,
"(" + descType.descriptor + ")I")
store(indexVar, Type.INT_TYPE)
// switch(index)
@@ -297,7 +310,7 @@ class SerializerCodegenImpl(
fun produceCall(update: Boolean) {
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" +
(if (useSerializer) kSerialLoaderType.descriptor else "")
+ (if (unknownSer) AsmTypes.K_CLASS_TYPE.descriptor else "")
@@ -351,7 +364,7 @@ class SerializerCodegenImpl(
visitLabel(readEndLabel)
load(inputVar, kInputType)
load(descVar, descType)
invokeinterface(kInputType.internalName, "endStructure",
invokeinterface(kInputType.internalName, CallingConventions.end,
"(" + descType.descriptor + ")V")
if (!serializableDescriptor.isInternalSerializable) {
//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.types.KotlinType
import org.jetbrains.kotlinx.serialization.compiler.resolve.*
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerializationAnnotations.serialInfoFqName
import java.util.*
class SerializationResolveExtension : SyntheticResolveExtension {
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 ->
listOf(KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME)
listOf(SerialEntityNames.SERIALIZER_CLASS_NAME)
else -> listOf()
}
override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List<Name> = when {
thisDescriptor.isCompanionObject && getSerializableClassDescriptorByCompanion(thisDescriptor) != null ->
listOf(KSerializerDescriptorResolver.SERIALIZER_PROVIDER_NAME)
listOf(SerialEntityNames.SERIALIZER_PROVIDER_NAME)
else -> emptyList()
}
@@ -50,10 +51,10 @@ class SerializationResolveExtension : SyntheticResolveExtension {
declarationProvider: ClassMemberDeclarationProvider,
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))
else if (thisDescriptor.isInternalSerializable && name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME &&
result.none { it.name == KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME }
else if (thisDescriptor.isInternalSerializable && name == SerialEntityNames.SERIALIZER_CLASS_NAME &&
result.none { it.name == SerialEntityNames.SERIALIZER_CLASS_NAME }
)
result.add(KSerializerDescriptorResolver.addSerializerImplClass(thisDescriptor, declarationProvider, ctx))
return
@@ -30,23 +30,16 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlinx.serialization.compiler.backend.jvm.descType
import org.jetbrains.kotlinx.serialization.compiler.resolve.KSerializerDescriptorResolver.SERIALIZER_CLASS_NAME
import org.jetbrains.kotlinx.serialization.compiler.resolve.SerialEntityNames.KSERIALIZER_CLASS
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 =
type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, kSerializerFqName)
type != null && KotlinBuiltIns.isConstructedFromGivenClass(type, SerialEntityNames.KSERIALIZER_NAME_FQ)
fun ClassDescriptor.getKSerializerDescriptor(): ClassDescriptor =
module.findClassAcrossModuleDependencies(ClassId(packageFqName, kSerializerName))!!
module.findClassAcrossModuleDependencies(ClassId(packageFqName, SerialEntityNames.KSERIALIZER_NAME))!!
fun ClassDescriptor.getKSerializerType(argument: SimpleType): SimpleType {
@@ -61,61 +54,23 @@ internal fun extractKSerializerArgumentFromImplementation(implementationClass: C
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?
get() = findAnnotationValue(serializableAnnotationFqName, "with")
// ---- kotlin.serialization.Serializer(forClass=xxx)
internal val serializerAnnotationFqName = FqName("kotlinx.serialization.Serializer")
get() = findAnnotationValue(SerializationAnnotations.serializableAnnotationFqName, "with")
internal val Annotations.serializerForClass: KotlinType?
get() = findAnnotationValue(serializerAnnotationFqName, "forClass")
// ---- kotlin.serialization.SerialName(value=xxx)
internal val serialNameAnnotationFqName = FqName("kotlinx.serialization.SerialName")
get() = findAnnotationValue(SerializationAnnotations.serializerAnnotationFqName, "forClass")
val Annotations.serialNameValue: String?
get() {
val value = findAnnotationValue<String?>(serialNameAnnotationFqName, "value")
val value = findAnnotationValue<String?>(SerializationAnnotations.serialNameAnnotationFqName, "value")
return value
}
// ---- kotlin.serialization.Optional
internal val serialOptionalFqName = FqName("kotlinx.serialization.Optional")
val Annotations.serialOptional: Boolean
get() = hasAnnotation(serialOptionalFqName)
// ---- kotlin.serialization.Transient
internal val serialTransientFqName = FqName("kotlinx.serialization.Transient")
get() = hasAnnotation(SerializationAnnotations.serialOptionalFqName)
val Annotations.serialTransient: Boolean
get() = hasAnnotation(serialTransientFqName)
internal val serialInfoFqName = FqName("kotlinx.serialization.SerialInfo")
get() = hasAnnotation(SerializationAnnotations.serialTransientFqName)
// ----------------------------------------
@@ -126,10 +81,10 @@ val KotlinType?.toClassDescriptor: ClassDescriptor?
val ClassDescriptor.isInternalSerializable: Boolean //todo normal checking
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.
// 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)
val psi = lazyDesc.annotationEntry
return psi.valueArguments.isEmpty()
@@ -146,7 +101,7 @@ internal val ClassDescriptor?.classSerializer: KotlinType?
if (hasCompanionObjectAsSerializer) return companionObjectDescriptor?.defaultType
// $serializer nested class
return this.unsubstitutedMemberScope
.getDescriptorsFiltered(nameFilter = {it == SERIALIZER_CLASS_NAME})
.getDescriptorsFiltered(nameFilter = {it == SerialEntityNames.SERIALIZER_CLASS_NAME})
.filterIsInstance<ClassDescriptor>().singleOrNull()?.defaultType
}
return null
@@ -158,7 +113,7 @@ internal val ClassDescriptor.hasCompanionObjectAsSerializer: Boolean
internal fun checkSerializerNullability(classType: KotlinType, serializerType: KotlinType): KotlinType {
val castedToKSerial = requireNotNull(
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)
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? {
val serializerForClass = serializerDescriptor.annotations.serializerForClass
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
if (!classDescriptor.isInternalSerializable) return null
return classDescriptor
@@ -218,7 +173,7 @@ inline fun <reified R> Annotations.findAnnotationValue(annotationFqName: FqName,
// Search utils
fun ClassDescriptor.getKSerializerConstructorMarker(): ClassDescriptor =
module.findClassAcrossModuleDependencies(ClassId(packageFqName, kSerializerConstructorMarkerName))!!
module.findClassAcrossModuleDependencies(ClassId(packageFqName, SerialEntityNames.SERIAL_CTOR_MARKER_NAME))!!
fun ModuleDescriptor.getClassFromInternalSerializationPackage(classSimpleName: String) =
requireNotNull(
@@ -240,7 +195,7 @@ fun ClassDescriptor.toSimpleType(nullable: Boolean = true) = KotlinTypeFactory.s
fun Annotated.annotationsWithArguments(): List<Triple<ClassDescriptor, List<ValueArgument>, List<ValueParameterDescriptor>>> =
annotations.asSequence()
.filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(serialInfoFqName) == true }
.filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(SerializationAnnotations.serialInfoFqName) == true }
.filterIsInstance<LazyAnnotationDescriptor>()
.mapNotNull { annDesc ->
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.typeUtil.createProjection
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.*
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 {
return thisDescriptor.name == IMPL_NAME
&& thisDescriptor.containingDeclaration is LazyClassDescriptor
@@ -128,7 +116,7 @@ object KSerializerDescriptorResolver {
name: Name,
result: MutableSet<PropertyDescriptor>) {
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 })
result.add(createSerializableClassPropertyDescriptor(thisDescriptor, classDescriptor))
@@ -142,7 +130,7 @@ object KSerializerDescriptorResolver {
) {
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))
}
}
@@ -159,25 +147,25 @@ object KSerializerDescriptorResolver {
fromSupertypes.none { checkParameters(it) && it.modality == Modality.FINAL }
}
if (name == SAVE_NAME &&
if (name == SerialEntityNames.SAVE_NAME &&
shouldAddSerializerFunction { classDescriptor.checkSaveMethodParameters(it.valueParameters) }) {
result.add(createSaveFunctionDescriptor(thisDescriptor, classDescriptor))
}
if (name == LOAD_NAME &&
if (name == SerialEntityNames.LOAD_NAME &&
shouldAddSerializerFunction { classDescriptor.checkLoadMethodParameters(it.valueParameters) }) {
result.add(createLoadFunctionDescriptor(thisDescriptor, classDescriptor))
}
}
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 =
doCreateSerializerFunction(companionDescriptor, classDescriptor, SAVE_NAME)
doCreateSerializerFunction(companionDescriptor, classDescriptor, SerialEntityNames.SAVE_NAME)
fun createLoadFunctionDescriptor(companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor): SimpleFunctionDescriptor =
doCreateSerializerFunction(companionDescriptor, classDescriptor, LOAD_NAME)
doCreateSerializerFunction(companionDescriptor, classDescriptor, SerialEntityNames.LOAD_NAME)
private fun doCreateSerializerProperty(
companionDescriptor: ClassDescriptor,
@@ -221,7 +209,7 @@ object KSerializerDescriptorResolver {
)
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 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,
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))
functionDescriptor.initialize(
@@ -287,7 +275,7 @@ object KSerializerDescriptorResolver {
false,
classDescriptor.source
)
val serializerClass = classDescriptor.getClassFromSerializationPackage("KSerializer")
val serializerClass = classDescriptor.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)
val targs = mutableListOf<TypeParameterDescriptor>()
val args = serializableDescriptor.declaredTypeParameters.mapIndexed { index, param ->
val targ = TypeParameterDescriptorImpl.createWithDefaultBound(
@@ -314,11 +302,11 @@ object KSerializerDescriptorResolver {
val f = SimpleFunctionDescriptorImpl.create(
thisClass,
Annotations.EMPTY,
SERIALIZER_PROVIDER_NAME,
SerialEntityNames.SERIALIZER_PROVIDER_NAME,
CallableMemberDescriptor.Kind.SYNTHESIZED,
thisClass.source
)
val serializerClass = thisClass.getClassFromSerializationPackage("KSerializer")
val serializerClass = thisClass.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)
val args = mutableListOf<ValueParameterDescriptor>()
val typeArgs = mutableListOf<TypeParameterDescriptor>()
@@ -368,7 +356,7 @@ object KSerializerDescriptorResolver {
else this.makeNullable()
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 args = mutableListOf<ValueParameterDescriptor>()
@@ -379,7 +367,7 @@ object KSerializerDescriptorResolver {
i++,
Annotations.EMPTY,
Name.identifier("output"),
thisClass.getClassFromSerializationPackage("StructureEncoder").toSimpleType(false),
thisClass.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS).toSimpleType(false),
false,
false,
false,
@@ -393,7 +381,7 @@ object KSerializerDescriptorResolver {
i++,
Annotations.EMPTY,
Name.identifier("serialDesc"),
thisClass.getClassFromSerializationPackage("SerialDescriptor").toSimpleType(false),
thisClass.getClassFromSerializationPackage(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS).toSimpleType(false),
false,
false,
false,
@@ -401,7 +389,7 @@ object KSerializerDescriptorResolver {
f.source)
)
val kSerialClassDesc = thisClass.getClassFromSerializationPackage("KSerializer")
val kSerialClassDesc = thisClass.getClassFromSerializationPackage(SerialEntityNames.KSERIALIZER_CLASS)
thisClass.declaredTypeParameters.forEach {
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"
}