diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCompanionCodegen.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCompanionCodegen.kt index 31b7df76edc..a1f2d31cd05 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCompanionCodegen.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCompanionCodegen.kt @@ -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)!! diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt index 7478e8a1280..88babd03d9c 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializerCodegen.kt @@ -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) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt index afdf503e150..413ffda7ab9 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/TypeUtil.kt @@ -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) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt index 24d48a31a20..141cbc04b7e 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializableIrGenerator.kt @@ -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() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt index 4859b712dcc..12c3779d82f 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/SerializerIrGenerator.kt @@ -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: for primitives - fun IrBuilderWithScope.defaultValueAndType(prop: SerializableProperty): Pair { + private fun IrBuilderWithScope.defaultValueAndType(prop: SerializableProperty): Pair { 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, diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt index 801466d796a..0da0c58ab25 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializableJsTranslator.kt @@ -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 -> diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt index e53a9dfca91..1f716a0c60e 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/js/SerializerJsTranslator.kt @@ -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), diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt index 5b4a2571aba..ee1866f0985 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/JVMCodegenUtil.kt @@ -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) } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt index 5c23c390683..6200b5ba92b 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/jvm/SerializerCodegenImpl.kt @@ -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, ctorParams: List ) { - 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 diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt index 36de6d4a78f..5f23606e44a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationResolveExtension.kt @@ -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 = 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 = 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 ) { - 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 diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt index 23075f44cf9..c95f0cd751d 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializationUtil.kt @@ -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(serialNameAnnotationFqName, "value") + val value = findAnnotationValue(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().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 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, List>> = annotations.asSequence() - .filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(serialInfoFqName) == true } + .filter { it.type.toClassDescriptor?.annotations?.hasAnnotation(SerializationAnnotations.serialInfoFqName) == true } .filterIsInstance() .mapNotNull { annDesc -> annDesc.type.toClassDescriptor?.let { diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt index 9d2c59121f7..ebd83c6afc7 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/KSerializerDescriptorResolver.kt @@ -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) { 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() 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() val typeArgs = mutableListOf() @@ -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() @@ -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) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/NamingConventions.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/NamingConventions.kt new file mode 100644 index 00000000000..4207367536f --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/resolve/NamingConventions.kt @@ -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" +} \ No newline at end of file