Do not check 'no ctor parameters' for serializable enums

fixes https://github.com/Kotlin/kotlinx.serialization/issues/742

Do not use serializableIrClass if it is not bound (this may happen
in case we're generating external serializer for library class)

fixes https://github.com/Kotlin/kotlinx.serialization/issues/744
This commit is contained in:
Leonid Startsev
2020-03-06 17:24:19 +03:00
parent 79fef09bf5
commit e20354926b
4 changed files with 14 additions and 20 deletions
@@ -39,6 +39,7 @@ class SerializerForEnumsGenerator(
val encodeEnum = encoderClass.referenceMethod(CallingConventions.encodeEnum) val encodeEnum = encoderClass.referenceMethod(CallingConventions.encodeEnum)
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol) val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
val ordinalProp = serializableIrClass.properties.single { it.name == Name.identifier("ordinal") }.getter!! val ordinalProp = serializableIrClass.properties.single { it.name == Name.identifier("ordinal") }.getter!!
val getOrdinal = irInvoke(irGet(saveFunc.valueParameters[1]), ordinalProp.symbol) val getOrdinal = irInvoke(irGet(saveFunc.valueParameters[1]), ordinalProp.symbol)
val call = irInvoke(irGet(saveFunc.valueParameters[0]), encodeEnum, serialDescGetter, getOrdinal) val call = irInvoke(irGet(saveFunc.valueParameters[0]), encodeEnum, serialDescGetter, getOrdinal)
@@ -54,6 +55,7 @@ class SerializerForEnumsGenerator(
val decode = decoderClass.referenceMethod(CallingConventions.decodeEnum) val decode = decoderClass.referenceMethod(CallingConventions.decodeEnum)
val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol) val serialDescGetter = irGet(descriptorGetterSymbol.owner.returnType, irThis(), descriptorGetterSymbol)
val serializableIrClass = requireNotNull(serializableIrClass) { "Enums do not support external serialization" }
val valuesF = serializableIrClass.functions.single { it.name == DescriptorUtils.ENUM_VALUES } val valuesF = serializableIrClass.functions.single { it.name == DescriptorUtils.ENUM_VALUES }
val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol) val getValues = irInvoke(dispatchReceiver = null, callee = valuesF.symbol)
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2020 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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -40,7 +40,7 @@ object SERIALIZABLE_PLUGIN_ORIGIN : IrDeclarationOriginImpl("SERIALIZER")
open class SerializerIrGenerator(val irClass: IrClass, final override val compilerContext: SerializationPluginContext, bindingContext: BindingContext) : open class SerializerIrGenerator(val irClass: IrClass, final override val compilerContext: SerializationPluginContext, bindingContext: BindingContext) :
SerializerCodegen(irClass.descriptor, bindingContext), IrBuilderExtension { SerializerCodegen(irClass.descriptor, bindingContext), IrBuilderExtension {
protected val serializableIrClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).owner protected val serializableIrClass = compilerContext.symbolTable.referenceClass(serializableDescriptor).takeIf { it.isBound }?.owner
override fun generateSerialDesc() { override fun generateSerialDesc() {
val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return val desc: PropertyDescriptor = generatedSerialDescPropertyDescriptor ?: return
@@ -81,7 +81,7 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS) addElementsContentToDescriptor(serialDescImplClass, localDesc, addFuncS)
// add class annotations // add class annotations
copySerialInfoAnnotationsToDescriptor( copySerialInfoAnnotationsToDescriptor(
serializableIrClass.annotations, serializableIrClass?.annotations.orEmpty(),
localDesc, localDesc,
serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation) serialDescImplClass.referenceMethod(CallingConventions.addClassAnnotation)
) )
@@ -201,7 +201,9 @@ open class SerializerIrGenerator(val irClass: IrClass, final override val compil
override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc -> override fun generateSave(function: FunctionDescriptor) = irClass.contributeFunction(function) { saveFunc ->
val fieldInitializer: (SerializableProperty) -> IrExpression? = val fieldInitializer: (SerializableProperty) -> IrExpression? =
buildInitializersRemapping(serializableIrClass).run { { invoke(it.irField) } } buildInitializersRemapping(
serializableIrClass ?: error("Please provide implementation of .deserialize method for external class")
).run { { invoke(it.irField) } }
fun irThis(): IrExpression = fun irThis(): IrExpression =
IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol) IrGetValueImpl(startOffset, endOffset, saveFunc.dispatchReceiverParameter!!.symbol)
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2020 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. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
@@ -38,7 +38,7 @@ object SerializationPluginErrorsRendering : DefaultErrorMessages.Extension {
) )
MAP.put( MAP.put(
SerializationErrors.PRIMARY_CONSTRUCTOR_PARAMETER_IS_NOT_A_PROPERTY, SerializationErrors.PRIMARY_CONSTRUCTOR_PARAMETER_IS_NOT_A_PROPERTY,
"This class is not serializable automatically because it has primary constructor parameters of which are not properties" "This class is not serializable automatically because it has primary constructor parameters that are not properties"
) )
MAP.put( MAP.put(
SerializationErrors.DUPLICATE_SERIAL_NAME, SerializationErrors.DUPLICATE_SERIAL_NAME,
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * Copyright 2010-2020 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.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlinx.serialization.compiler.resolve package org.jetbrains.kotlinx.serialization.compiler.resolve
@@ -67,7 +56,8 @@ class SerializableProperties(private val serializableClass: ClassDescriptor, val
else else
SerializableProperties(supers, bindingContext).serializableProperties + first + second SerializableProperties(supers, bindingContext).serializableProperties + first + second
} }
isExternallySerializable = primaryConstructorParameters.size == primaryConstructorProperties.size isExternallySerializable =
serializableClass.isSerializableEnum() || primaryConstructorParameters.size == primaryConstructorProperties.size
} }
val serializableConstructorProperties: List<SerializableProperty> = val serializableConstructorProperties: List<SerializableProperty> =