diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt index 44d5ab74c30..03f5bdb6109 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/common/SerializableCodegen.kt @@ -1,15 +1,16 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlinx.serialization.compiler.backend.common -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.secondaryConstructors +import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlinx.serialization.compiler.resolve.* abstract class SerializableCodegen( @@ -37,7 +38,15 @@ abstract class SerializableCodegen( private fun generateSyntheticMethods() { val serializerDescriptor = serializableDescriptor.classSerializer ?: return if (serializableDescriptor.shouldHaveSpecificSyntheticMethods { SerializerCodegen.getSyntheticSaveMember(serializerDescriptor) }) { - val func = KSerializerDescriptorResolver.createWriteSelfFunctionDescriptor(serializableDescriptor) + val func = + serializableDescriptor.unsubstitutedMemberScope.getContributedFunctions( + Name.identifier(SerialEntityNames.WRITE_SELF_NAME.toString()), + NoLookupLocation.FROM_BACKEND + ).singleOrNull { function -> + function.kind == CallableMemberDescriptor.Kind.SYNTHESIZED && + function.modality == Modality.FINAL && + function.returnType?.isUnit() ?: false + } ?: return generateWriteSelfMethod(func) } } 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 573d30f213c..bd9f278b32a 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -70,7 +70,7 @@ abstract class SerializerCodegen( serializerDescriptor::checkSerializableClassPropertyResult ) { true } - lateinit var localSerializersFieldsDescriptors: List> + var localSerializersFieldsDescriptors: List> = emptyList() protected set // Can be false if user specified inheritance from KSerializer explicitly diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt index 26f224ea283..0e49644af92 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/GeneratorHelpers.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlinx.serialization.compiler.backend.ir import org.jetbrains.kotlin.backend.common.deepCopyWithVariables import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations @@ -59,9 +60,9 @@ interface IrBuilderExtension { return throwMissedFieldExceptionFunc != null && throwMissedFieldExceptionArrayFunc != null } - fun IrClass.contributeFunction(descriptor: FunctionDescriptor, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) { - val f: IrSimpleFunction = searchForDeclaration(descriptor) ?: compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner - // TODO: default parameters + fun IrClass.contributeFunction(descriptor: FunctionDescriptor, ignoreWhenMissing: Boolean = false, bodyGen: IrBlockBodyBuilder.(IrFunction) -> Unit) { + val f: IrSimpleFunction = searchForDeclaration(descriptor) + ?: (if (ignoreWhenMissing) return else compilerContext.symbolTable.referenceSimpleFunction(descriptor).owner) f.body = DeclarationIrBuilder(compilerContext, f.symbol, this.startOffset, this.endOffset).irBlockBody( this.startOffset, this.endOffset @@ -489,7 +490,7 @@ interface IrBuilderExtension { ) }.also { f -> generateOverriddenFunctionSymbols(f, compilerContext.symbolTable) - f.createParameterDeclarations(receiver = null) + f.createParameterDeclarations(descriptor) f.returnType = descriptor.returnType!!.toIrType() f.correspondingPropertySymbol = fieldSymbol.owner.correspondingPropertySymbol } @@ -572,7 +573,7 @@ interface IrBuilderExtension { } fun IrFunction.createParameterDeclarations( - receiver: IrValueParameter?, + descriptor: FunctionDescriptor, overwriteValueParameters: Boolean = false, copyTypeParameters: Boolean = true ) { @@ -589,7 +590,7 @@ interface IrBuilderExtension { if (copyTypeParameters) { assert(typeParameters.isEmpty()) - copyTypeParamsFromDescriptor() + copyTypeParamsFromDescriptor(descriptor) } dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.let { irValueParameter(it) } @@ -601,7 +602,7 @@ interface IrBuilderExtension { valueParameters = descriptor.valueParameters.map { irValueParameter(it) } } - fun IrFunction.copyTypeParamsFromDescriptor() { + fun IrFunction.copyTypeParamsFromDescriptor(descriptor: FunctionDescriptor) { val newTypeParameters = descriptor.typeParameters.map { factory.createTypeParameter( startOffset, endOffset, @@ -991,4 +992,98 @@ interface IrBuilderExtension { return superClasses.singleOrNull { it.kind == ClassKind.CLASS } } + fun IrClass.findWriteSelfMethod(): IrSimpleFunction? = + declarations.filter { it is IrSimpleFunction && it.name == SerialEntityNames.WRITE_SELF_NAME && !it.isFakeOverride } + .takeUnless(Collection<*>::isEmpty)?.single() as IrSimpleFunction? + + fun IrBlockBodyBuilder.serializeAllProperties( + generator: AbstractSerialGenerator, + serializableIrClass: IrClass, + serializableProperties: List, + objectToSerialize: IrValueDeclaration, + localOutput: IrValueDeclaration, + localSerialDesc: IrValueDeclaration, + kOutputClass: ClassDescriptor, + ignoreIndexTo: Int, + initializerAdapter: (IrExpressionBody) -> IrExpression, + genericGetter: ((Int, KotlinType) -> IrExpression)? + ) { + + fun SerializableProperty.irGet(): IrExpression { + val ownerType = objectToSerialize.symbol.owner.type + return getProperty( + irGet( + type = ownerType, + variable = objectToSerialize.symbol + ), getIrPropertyFrom(serializableIrClass) + ) + } + + for ((index, property) in serializableProperties.withIndex()) { + if (index < ignoreIndexTo) continue + // output.writeXxxElementValue(classDesc, index, value) + val elementCall = formEncodeDecodePropertyCall( + generator, + irGet(localOutput), + property, { innerSerial, sti -> + val f = + kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}") + f to listOf( + irGet(localSerialDesc), + irInt(index), + innerSerial, + property.irGet() + ) + }, { + val f = + kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}") + val args: MutableList = mutableListOf(irGet(localSerialDesc), irInt(index)) + if (it.elementMethodPrefix != "Unit") args.add(property.irGet()) + f to args + }, + genericGetter + ) + + // check for call to .shouldEncodeElementDefault + if (!property.optional) { + // emit call right away + +elementCall + } else { + // emit check: + // if (if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) { + // output.encodeIntElement(this.descriptor, i, obj.prop)// block {obj.prop != DEFAULT_VALUE} may contain several statements + val shouldEncodeFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.shouldEncodeDefault) + val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index)) + val partB = irNotEquals(property.irGet(), initializerAdapter(property.irField.initializer!!)) + // Ir infrastructure does not have dedicated symbol for ||, so + // `a || b == if (a) true else b`, see org.jetbrains.kotlin.ir.builders.PrimitivesKt.oror + val condition = irIfThenElse(compilerContext.irBuiltIns.booleanType, partA, irTrue(), partB) + +irIfThen(condition, elementCall) + } + } + } + + fun IrBlockBodyBuilder.formEncodeDecodePropertyCall( + enclosingGenerator: AbstractSerialGenerator, + encoder: IrExpression, + property: SerializableProperty, + whenHaveSerializer: (serializer: IrExpression, sti: SerialTypeInfo) -> FunctionWithArgs, + whenDoNot: (sti: SerialTypeInfo) -> FunctionWithArgs, + genericGetter: ((Int, KotlinType) -> IrExpression)? = null, + returnTypeHint: IrType? = null + ): IrExpression { + val sti = enclosingGenerator.getSerialTypeInfo(property) + val innerSerial = serializerInstance( + enclosingGenerator, + sti.serializer, + property.module, + property.type, + property.genericIndex, + genericGetter + ) + val (functionToCall, args: List) = if (innerSerial != null) whenHaveSerializer(innerSerial, sti) else whenDoNot(sti) + val typeArgs = if (functionToCall.descriptor.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf() + return irInvoke(encoder, functionToCall, typeArguments = typeArgs, valueArguments = args, returnTypeHint = returnTypeHint) + } + } 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 d65caf3adcd..8cc43c95c2f 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 @@ -25,9 +25,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.getOrPutNullable -import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializableCodegen -import org.jetbrains.kotlinx.serialization.compiler.backend.common.isStaticSerializable -import org.jetbrains.kotlinx.serialization.compiler.backend.common.serialName +import org.jetbrains.kotlinx.serialization.compiler.backend.common.* import org.jetbrains.kotlinx.serialization.compiler.diagnostic.serializableAnnotationIsUseless import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext import org.jetbrains.kotlinx.serialization.compiler.resolve.* @@ -284,7 +282,57 @@ class SerializableIrGenerator( } override fun generateWriteSelfMethod(methodDescriptor: FunctionDescriptor) { - // no-op + irClass.contributeFunction(methodDescriptor, ignoreWhenMissing = true) { writeSelfFunction -> + val objectToSerialize = writeSelfFunction.valueParameters[0] + val localOutput = writeSelfFunction.valueParameters[1] + val localSerialDesc = writeSelfFunction.valueParameters[2] + val serializableProperties = properties.serializableProperties + val kOutputClass = serializableDescriptor.getClassFromSerializationPackage(SerialEntityNames.STRUCTURE_ENCODER_CLASS) + + val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = + createPropertyByParamReplacer(irClass, serializableProperties, objectToSerialize, bindingContext) + + // Since writeSelf is a static method, we have to replace all references to this in property initializers + val thisSymbol = irClass.thisReceiver!!.symbol + val initializerAdapter: (IrExpressionBody) -> IrExpression = createInitializerAdapter(irClass, propertyByParamReplacer, thisSymbol to { irGet(objectToSerialize) }) + + // Compute offset of properties in superclass + var ignoreIndexTo = -1 + val superClass = irClass.getSuperClassOrAny() + if (superClass.descriptor.isInternalSerializable) { + ignoreIndexTo = bindingContext.serializablePropertiesFor(superClass.descriptor).size + + // call super.writeSelf + val superWriteSelfF = superClass.findWriteSelfMethod() + if (superWriteSelfF != null) { + val args = mutableListOf(irGet(objectToSerialize), irGet(localOutput), irGet(localSerialDesc)) + + val typeArgsForParent = serializableDescriptor.typeConstructor.supertypes.single { it.toClassDescriptor?.isInternalSerializable == true }.arguments + val parentWriteSelfSerializers = typeArgsForParent.map { arg -> + val genericIdx = serializableDescriptor.defaultType.arguments.indexOf(arg).let { if (it == -1) null else it } + val serial = findTypeSerializerOrContext(serializableDescriptor.module, arg.type) + serializerInstance( + this@SerializableIrGenerator, + serial, + serializableDescriptor.module, + arg.type, + genericIdx + ) { it, _ -> + irGet(writeSelfFunction.valueParameters[3 + it]) + }!! + } + +irInvoke(null, superWriteSelfF.symbol, typeArgsForParent.map { it.type.toIrType() }, args + parentWriteSelfSerializers) + } + } + + serializeAllProperties( + this@SerializableIrGenerator, irClass, serializableProperties, + objectToSerialize, localOutput, localSerialDesc, + kOutputClass, ignoreIndexTo, initializerAdapter + ) { it, _ -> + irGet(writeSelfFunction.valueParameters[3 + it]) + } + } } companion object { @@ -298,8 +346,7 @@ class SerializableIrGenerator( if (serializableClass.isInternalSerializable) { SerializableIrGenerator(irClass, context, bindingContext).generate() irClass.patchDeclarationParents(irClass.parent) - } - else if (serializableClass.serializableAnnotationIsUseless) { + } else if (serializableClass.serializableAnnotationIsUseless) { throw CompilationException( "@Serializable annotation on $serializableClass would be ignored because it is impossible to serialize it automatically. " + "Provide serializer manually via e.g. companion object", null, serializableClass.findPsi() 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 7964f76eb6a..924c60018d4 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 @@ -25,9 +25,9 @@ import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.cast import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerialTypeInfo import org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen -import org.jetbrains.kotlinx.serialization.compiler.backend.common.getSerialTypeInfo import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationDescriptorSerializerPlugin import org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationPluginContext import org.jetbrains.kotlinx.serialization.compiler.resolve.* @@ -196,13 +196,13 @@ open class SerializerIrGenerator( val thisAsReceiverParameter = irClass.thisReceiver!! ctor.valueParameters.forEachIndexed { index, param -> val localSerial = localSerializersFieldsDescriptors[index].second.backingField!! - +irSetField(generateReceiverExpressionForFieldAccess( - thisAsReceiverParameter.symbol, - localSerializersFieldsDescriptors[index].first - ), localSerial, irGet(param)) + +irSetField( + generateReceiverExpressionForFieldAccess( + thisAsReceiverParameter.symbol, + localSerializersFieldsDescriptors[index].first + ), localSerial, irGet(param) + ) } - - } override fun generateChildSerializersGetter(function: FunctionDescriptor) = irClass.contributeFunction(function) { irFun -> @@ -256,69 +256,44 @@ open class SerializerIrGenerator( val objectToSerialize = saveFunc.valueParameters[1] val localOutput = irTemporary(call, "output") - fun SerializableProperty.irGet(): IrExpression { - val ownerType = objectToSerialize.symbol.owner.type - return getProperty( - irGet( - type = ownerType, - variable = objectToSerialize.symbol - ), getIrPropertyFrom(serializableIrClass) - ) - } + val writeSelfFunction = serializableIrClass.findWriteSelfMethod() - // Ignore comparing to default values of properties from superclass, - // because we do not have access to their fields (and initializers), if superclass is in another module. - // In future, IR analogue of JVM's write$Self should be implemented. - val superClass = serializableIrClass.getSuperClassOrAny().descriptor - val ignoreIndexTo = if (superClass.isInternalSerializable) { - bindingContext.serializablePropertiesFor(superClass).size - } else { - -1 - } - - val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = - createPropertyByParamReplacer(serializableIrClass, serializableProperties, objectToSerialize, bindingContext) - - val thisSymbol = serializableIrClass.thisReceiver!!.symbol - val initializerAdapter: (IrExpressionBody) -> IrExpression = - createInitializerAdapter(serializableIrClass, propertyByParamReplacer, thisSymbol to { irGet(objectToSerialize) }) - - // internal serialization via virtual calls? - for ((index, property) in serializableProperties.withIndex()) { - // output.writeXxxElementValue(classDesc, index, value) - val elementCall = formEncodeDecodePropertyCall(irGet(localOutput), saveFunc.dispatchReceiverParameter!!, property, {innerSerial, sti -> - val f = - kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${sti.elementMethodPrefix}Serializable${CallingConventions.elementPostfix}") - f to listOf( - irGet(localSerialDesc), - irInt(index), - innerSerial, - property.irGet() + if (writeSelfFunction != null) { + // extract Tx from KSerializer list + val typeArgs = + localSerializersFieldsDescriptors.map { (_, ir) -> ir.backingField!!.type.cast().arguments.single().typeOrNull } + val args = mutableListOf(irGet(objectToSerialize), irGet(localOutput), irGet(localSerialDesc)) + args.addAll(localSerializersFieldsDescriptors.map { (_, ir) -> + irGetField( + irGet(saveFunc.dispatchReceiverParameter!!), + ir.backingField!! ) - }, { - val f = - kOutputClass.referenceFunctionSymbol("${CallingConventions.encode}${it.elementMethodPrefix}${CallingConventions.elementPostfix}") - val args: MutableList = mutableListOf(irGet(localSerialDesc), irInt(index)) - if (it.elementMethodPrefix != "Unit") args.add(property.irGet()) - f to args }) - - // check for call to .shouldEncodeElementDefault - if (!property.optional || index < ignoreIndexTo) { - // emit call right away - +elementCall + +irInvoke(null, writeSelfFunction.symbol, typeArgs, args) + } else { + // No write$Self, old behaviour: + // Ignore comparing to default values of properties from superclass, + // because we do not have access to their fields (and initializers), if superclass is in another module. + val superClass = serializableIrClass.getSuperClassOrAny().descriptor + val ignoreIndexTo = if (superClass.isInternalSerializable) { + bindingContext.serializablePropertiesFor(superClass).size } else { - // emit check: - // if ( if (output.shouldEncodeElementDefault(this.descriptor, i)) true else {obj.prop != DEFAULT_VALUE} ) { - // output.encodeIntElement(this.descriptor, i, obj.prop) - // block {obj.prop != DEFAULT_VALUE} may contain several statements - val shouldEncodeFunc = kOutputClass.referenceFunctionSymbol(CallingConventions.shouldEncodeDefault) - val partA = irInvoke(irGet(localOutput), shouldEncodeFunc, irGet(localSerialDesc), irInt(index)) - val partB = irNotEquals(property.irGet(), initializerAdapter(property.irField.initializer!!)) - // Ir infrastructure does not have dedicated symbol for ||, so - // `a || b == if (a) true else b`, see org.jetbrains.kotlin.ir.builders.PrimitivesKt.oror - val condition = irIfThenElse(compilerContext.irBuiltIns.booleanType, partA, irTrue(), partB) - +irIfThen(condition, elementCall) + -1 + } + + val propertyByParamReplacer: (ValueParameterDescriptor) -> IrExpression? = + createPropertyByParamReplacer(serializableIrClass, serializableProperties, objectToSerialize, bindingContext) + + val thisSymbol = serializableIrClass.thisReceiver!!.symbol + val initializerAdapter: (IrExpressionBody) -> IrExpression = + createInitializerAdapter(serializableIrClass, propertyByParamReplacer, thisSymbol to { irGet(objectToSerialize) }) + + serializeAllProperties( + this@SerializerIrGenerator, serializableIrClass, serializableProperties, objectToSerialize, + localOutput, localSerialDesc, kOutputClass, ignoreIndexTo, initializerAdapter + ) { it, _ -> + val (_, ir) = localSerializersFieldsDescriptors[it] + irGetField(irGet(saveFunc.dispatchReceiverParameter!!), ir.backingField!!) } } @@ -327,27 +302,25 @@ open class SerializerIrGenerator( +irInvoke(irGet(localOutput), wEndFunc, irGet(localSerialDesc)) } - protected inline fun IrBlockBodyBuilder.formEncodeDecodePropertyCall( + protected fun IrBlockBodyBuilder.formEncodeDecodePropertyCall( encoder: IrExpression, dispatchReceiver: IrValueParameter, property: SerializableProperty, whenHaveSerializer: (serializer: IrExpression, sti: SerialTypeInfo) -> FunctionWithArgs, whenDoNot: (sti: SerialTypeInfo) -> FunctionWithArgs, returnTypeHint: IrType? = null - ): IrExpression { - val sti = getSerialTypeInfo(property) - val innerSerial = serializerInstance( - this@SerializerIrGenerator, - dispatchReceiver, - sti.serializer, - property.module, - property.type, - genericIndex = property.genericIndex - ) - val (functionToCall, args: List) = if (innerSerial != null) whenHaveSerializer(innerSerial, sti) else whenDoNot(sti) - val typeArgs = if (functionToCall.descriptor.typeParameters.isNotEmpty()) listOf(property.type.toIrType()) else listOf() - return irInvoke(encoder, functionToCall, typeArguments = typeArgs, valueArguments = args, returnTypeHint = returnTypeHint) - } + ): IrExpression = formEncodeDecodePropertyCall( + this@SerializerIrGenerator, + encoder, + property, + whenHaveSerializer, + whenDoNot, + { it, _ -> + val (_, ir) = localSerializersFieldsDescriptors[it] + irGetField(irGet(dispatchReceiver), ir.backingField!!) + }, + returnTypeHint + ) // returns null: Any? for boxed types and 0: for primitives private fun IrBuilderWithScope.defaultValueAndType(descriptor: PropertyDescriptor): Pair { 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 4a7c308eb7a..84ab5f929b5 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -39,9 +39,25 @@ open class SerializationResolveExtension @JvmOverloads constructor(val metadataP override fun getSyntheticFunctionNames(thisDescriptor: ClassDescriptor): List = when { thisDescriptor.isSerializableObject || thisDescriptor.isCompanionObject && getSerializableClassDescriptorByCompanion(thisDescriptor) != null -> listOf(SerialEntityNames.SERIALIZER_PROVIDER_NAME) + thisDescriptor.isInternalSerializable && thisDescriptor.platform?.isJvm() == true && !hasCustomizedSerializeMethod(thisDescriptor) -> { + // add write$Self, but only if .serialize was not customized in companion. + // It works not only on JVM, but I see no reason to enable it on other platforms — + // private fields there have no access control, and additional function + // only increases compiled code size. + listOf(SerialEntityNames.WRITE_SELF_NAME) + } else -> emptyList() } + private fun hasCustomizedSerializeMethod(serializableClass: ClassDescriptor): Boolean { + // We cannot check whether companion has @Serializer(MyClass::class) annotation due to recursive resolve problems + // (apparently, resolve MyClass type asks for all function names, which leads us to this function again) + // so we rely on less strict check that companion just has non-empty @Serializer annotation. + // Anyway, I doubt that serializable class companion would ever be serializer for _another_ class. + val companion = serializableClass.companionObjectDescriptor ?: return false + return companion.annotations.hasAnnotation(SerializationAnnotations.serializerAnnotationFqName) + } + override fun generateSyntheticClasses( thisDescriptor: ClassDescriptor, name: Name, @@ -91,6 +107,7 @@ open class SerializationResolveExtension @JvmOverloads constructor(val metadataP ) { KSerializerDescriptorResolver.generateSerializerMethods(thisDescriptor, fromSupertypes, name, result) KSerializerDescriptorResolver.generateCompanionObjectMethods(thisDescriptor, name, result) + KSerializerDescriptorResolver.generateSerializableClassMethods(thisDescriptor, name, result) } override fun generateSyntheticProperties( 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 47698a6facf..798481c08f9 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 @@ -1,5 +1,5 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -217,6 +217,11 @@ object KSerializerDescriptorResolver { } } + fun generateSerializableClassMethods(thisDescriptor: ClassDescriptor, name: Name, result: MutableCollection) { + if (thisDescriptor.isInternalSerializable && name == SerialEntityNames.WRITE_SELF_NAME) + result.add(createWriteSelfFunctionDescriptor(thisDescriptor)) + } + private fun createSerializableClassPropertyDescriptor( companionDescriptor: ClassDescriptor, classDescriptor: ClassDescriptor @@ -490,7 +495,7 @@ object KSerializerDescriptorResolver { if (KotlinBuiltIns.isPrimitiveType(this)) this else this.makeNullable() - fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): FunctionDescriptor { + fun createWriteSelfFunctionDescriptor(thisClass: ClassDescriptor): SimpleFunctionDescriptor { val jvmStaticClass = thisClass.module.findClassAcrossModuleDependencies( ClassId( FqName("kotlin.jvm"), @@ -570,7 +575,7 @@ object KSerializerDescriptorResolver { f.initialize( null, - thisClass.thisAsReceiverParameter, + null, typeArgs, args, returnType, diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt index 67e8d9c59a5..e260436683a 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/codegen/Basic.ir.txt @@ -182,18 +182,10 @@ public final class ListOfUsers$$serializer : java/lang/Object, kotlinx/serializa ALOAD (3) INVOKEINTERFACE (kotlinx/serialization/encoding/Encoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeEncoder;) ASTORE (4) + ALOAD (2) ALOAD (4) ALOAD (3) - ICONST_0 - NEW - DUP - GETSTATIC (INSTANCE, LUser$$serializer;) - CHECKCAST - INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) - CHECKCAST - ALOAD (2) - INVOKEVIRTUAL (ListOfUsers, getList, ()Ljava/util/List;) - INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V) + INVOKESTATIC (ListOfUsers, write$Self, (LListOfUsers;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V) ALOAD (4) ALOAD (3) INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, endStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)V) @@ -293,6 +285,35 @@ public final class ListOfUsers : java/lang/Object { } public final java.util.List getList() + + public final static void write$Self(ListOfUsers self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) { + LABEL (L0) + ALOAD (0) + LDC (self) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + ALOAD (1) + LDC (output) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + ALOAD (2) + LDC (serialDesc) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L1) + LINENUMBER (12) + ALOAD (1) + ALOAD (2) + ICONST_0 + NEW + DUP + GETSTATIC (INSTANCE, LUser$$serializer;) + CHECKCAST + INVOKESPECIAL (kotlinx/serialization/internal/ArrayListSerializer, , (Lkotlinx/serialization/KSerializer;)V) + CHECKCAST + ALOAD (0) + GETFIELD (list, Ljava/util/List;) + INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V) + RETURN + LABEL (L2) + } } public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer { @@ -467,47 +488,15 @@ public final class OptionalUser$$serializer : java/lang/Object, kotlinx/serializ ALOAD (3) INVOKEINTERFACE (kotlinx/serialization/encoding/Encoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeEncoder;) ASTORE (4) + ALOAD (2) ALOAD (4) ALOAD (3) - ICONST_0 - INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, shouldEncodeElementDefault, (Lkotlinx/serialization/descriptors/SerialDescriptor;I)Z) - IFEQ (L2) - ICONST_1 - GOTO (L3) - LABEL (L2) - ALOAD (2) - INVOKEVIRTUAL (OptionalUser, getUser, ()LUser;) - LABEL (L4) - LINENUMBER (10) - NEW - DUP - LDC () - LDC () - INVOKESPECIAL (User, , (Ljava/lang/String;Ljava/lang/String;)V) - INVOKESTATIC (kotlin/jvm/internal/Intrinsics, areEqual, (Ljava/lang/Object;Ljava/lang/Object;)Z) - IFNE (L5) - ICONST_1 - GOTO (L3) - LABEL (L5) - ICONST_0 - LABEL (L3) - IFEQ (L6) - LABEL (L7) - LINENUMBER (9) - ALOAD (4) - ALOAD (3) - ICONST_0 - GETSTATIC (INSTANCE, LUser$$serializer;) - CHECKCAST - ALOAD (2) - INVOKEVIRTUAL (OptionalUser, getUser, ()LUser;) - INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V) - LABEL (L6) + INVOKESTATIC (OptionalUser, write$Self, (LOptionalUser;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V) ALOAD (4) ALOAD (3) INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, endStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)V) RETURN - LABEL (L8) + LABEL (L2) } public void serialize(kotlinx.serialization.encoding.Encoder encoder, java.lang.Object value) { @@ -650,6 +639,59 @@ public final class OptionalUser : java/lang/Object { } public final User getUser() + + public final static void write$Self(OptionalUser self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) { + LABEL (L0) + ALOAD (0) + LDC (self) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + ALOAD (1) + LDC (output) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + ALOAD (2) + LDC (serialDesc) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L1) + LINENUMBER (9) + ALOAD (1) + ALOAD (2) + ICONST_0 + INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, shouldEncodeElementDefault, (Lkotlinx/serialization/descriptors/SerialDescriptor;I)Z) + IFEQ (L2) + ICONST_1 + GOTO (L3) + LABEL (L2) + ALOAD (0) + GETFIELD (user, LUser;) + LABEL (L4) + LINENUMBER (10) + NEW + DUP + LDC () + LDC () + INVOKESPECIAL (User, , (Ljava/lang/String;Ljava/lang/String;)V) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, areEqual, (Ljava/lang/Object;Ljava/lang/Object;)Z) + IFNE (L5) + ICONST_1 + GOTO (L3) + LABEL (L5) + ICONST_0 + LABEL (L3) + IFEQ (L6) + LABEL (L7) + LINENUMBER (9) + ALOAD (1) + ALOAD (2) + ICONST_0 + GETSTATIC (INSTANCE, LUser$$serializer;) + CHECKCAST + ALOAD (0) + GETFIELD (user, LUser;) + INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeSerializableElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILkotlinx/serialization/SerializationStrategy;Ljava/lang/Object;)V) + LABEL (L6) + RETURN + LABEL (L8) + } } public final class User$$serializer : java/lang/Object, kotlinx/serialization/internal/GeneratedSerializer { @@ -849,18 +891,10 @@ public final class User$$serializer : java/lang/Object, kotlinx/serialization/in ALOAD (3) INVOKEINTERFACE (kotlinx/serialization/encoding/Encoder, beginStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)Lkotlinx/serialization/encoding/CompositeEncoder;) ASTORE (4) + ALOAD (2) ALOAD (4) ALOAD (3) - ICONST_0 - ALOAD (2) - INVOKEVIRTUAL (User, getFirstName, ()Ljava/lang/String;) - INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILjava/lang/String;)V) - ALOAD (4) - ALOAD (3) - ICONST_1 - ALOAD (2) - INVOKEVIRTUAL (User, getLastName, ()Ljava/lang/String;) - INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILjava/lang/String;)V) + INVOKESTATIC (User, write$Self, (LUser;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V) ALOAD (4) ALOAD (3) INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, endStructure, (Lkotlinx/serialization/descriptors/SerialDescriptor;)V) @@ -973,4 +1007,33 @@ public final class User : java/lang/Object { public final java.lang.String getFirstName() public final java.lang.String getLastName() + + public final static void write$Self(User self, kotlinx.serialization.encoding.CompositeEncoder output, kotlinx.serialization.descriptors.SerialDescriptor serialDesc) { + LABEL (L0) + ALOAD (0) + LDC (self) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + ALOAD (1) + LDC (output) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + ALOAD (2) + LDC (serialDesc) + INVOKESTATIC (kotlin/jvm/internal/Intrinsics, checkNotNullParameter, (Ljava/lang/Object;Ljava/lang/String;)V) + LABEL (L1) + LINENUMBER (6) + ALOAD (1) + ALOAD (2) + ICONST_0 + ALOAD (0) + GETFIELD (firstName, Ljava/lang/String;) + INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILjava/lang/String;)V) + ALOAD (1) + ALOAD (2) + ICONST_1 + ALOAD (0) + GETFIELD (lastName, Ljava/lang/String;) + INVOKEINTERFACE (kotlinx/serialization/encoding/CompositeEncoder, encodeStringElement, (Lkotlinx/serialization/descriptors/SerialDescriptor;ILjava/lang/String;)V) + RETURN + LABEL (L2) + } } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.kt index 7690dec6678..e2fcbc9d74e 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE - +// WITH_RUNTIME // FILE: test.kt import kotlinx.serialization.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt index ae4b5da28e0..2e220f82da2 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/DuplicateSerialName.txt @@ -7,6 +7,8 @@ package public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: Derived, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit + @kotlin.jvm.JvmStatic public final override /*1*/ /*fake_override*/ fun `write$Self`(/*0*/ self: Parent, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() @@ -36,6 +38,7 @@ package public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: Parent, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.kt index bf721ed6639..7e8a4e795ad 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE - +// WITH_RUNTIME // FILE: test.kt import kotlinx.serialization.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt index 1c4700e479b..257be147901 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NoSuitableCtorInParent.txt @@ -8,6 +8,7 @@ package public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: Derived, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.kt index 4f14242cf2f..6752a185364 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE - +// WITH_RUNTIME // FILE: test.kt import kotlinx.serialization.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt index 0dfb58e9182..8abd459cf5e 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NonSerializable.txt @@ -7,6 +7,7 @@ package public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: Basic, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() @@ -36,6 +37,7 @@ package public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: Inside, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() @@ -72,6 +74,7 @@ public final class NonSerializable { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: WithImplicitType, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.kt index b7f78a94933..d76d8bf3088 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE - +// WITH_RUNTIME // FILE: test.kt import kotlinx.serialization.* import kotlinx.serialization.descriptors.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt index 8dcf020f79e..e3280bb5d5b 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/NullabilityIncompatible.txt @@ -7,6 +7,7 @@ package public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: Foo, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.kt index bb14e4124af..e7a7deb9c78 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE - +// WITH_RUNTIME // FILE: test.kt import kotlinx.serialization.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.txt index d01dabbafa9..0d5dcf807e7 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/ParamIsNotProperty.txt @@ -7,6 +7,7 @@ package public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: Test, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.kt index c36d606989e..d5c71f19500 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE - +// WITH_RUNTIME // FILE: test.kt import kotlinx.serialization.* import kotlinx.serialization.encoding.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt index 1e4d711f84a..8f427ca065c 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/SerializableEnums.txt @@ -23,6 +23,7 @@ public object EnumSerializer : kotlinx.serialization.KSerializer { private constructor `$serializer`() diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.kt index 4a8eb2139d7..c4833e69b3c 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS: -UNUSED_PARAMETER,-UNUSED_VARIABLE - +// WITH_RUNTIME // FILE: test.kt import kotlinx.serialization.* diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt index 4cd20063cf8..86d03badc42 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/diagnostics/Transients.txt @@ -11,6 +11,7 @@ package public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String + @kotlin.jvm.JvmStatic public final /*synthesized*/ fun `write$Self`(/*0*/ self: WithTransients, /*1*/ output: kotlinx.serialization.encoding.CompositeEncoder, /*2*/ serialDesc: kotlinx.serialization.descriptors.SerialDescriptor): kotlin.Unit @kotlin.Deprecated(level = DeprecationLevel.HIDDEN, message = "This synthesized declaration should not be used directly", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public object `$serializer` : kotlinx.serialization.internal.GeneratedSerializer { private constructor `$serializer`()