Check for name when searching Companion.serializer() function to generate

Name check was forgotten during refactoring, so any user function with
matching signature could be overwritten by the plugin, while correct
function would not have body.

#KT-55682 Fixed
This commit is contained in:
Leonid Startsev
2023-01-02 20:51:11 +01:00
committed by Space Team
parent 0b4f534d35
commit bf60819824
4 changed files with 65 additions and 9 deletions
@@ -35,10 +35,13 @@ class SerializableCompanionIrGenerator(
companion object {
fun getSerializerGetterFunction(serializableIrClass: IrClass): IrSimpleFunction? {
val irClass = if (serializableIrClass.isSerializableObject) serializableIrClass else serializableIrClass.companionObject() ?: return null
val irClass =
if (serializableIrClass.isSerializableObject) serializableIrClass else serializableIrClass.companionObject() ?: return null
return irClass.findDeclaration<IrSimpleFunction> {
(it.valueParameters.size == serializableIrClass.typeParameters.size
&& it.valueParameters.all { p -> p.type.isKSerializer() }) && it.returnType.isKSerializer()
it.name == SerialEntityNames.SERIALIZER_PROVIDER_NAME
&& it.valueParameters.size == serializableIrClass.typeParameters.size
&& it.valueParameters.all { p -> p.type.isKSerializer() }
&& it.returnType.isKSerializer()
}
}
@@ -57,10 +60,12 @@ class SerializableCompanionIrGenerator(
}
fun generate() {
val serializerGetterFunction = getSerializerGetterFunction(serializableIrClass) ?: throw IllegalStateException(
"Can't find synthesized 'Companion.serializer()' function to generate, " +
"probably clash with user-defined function has occurred"
)
val serializerGetterFunction =
getSerializerGetterFunction(serializableIrClass)?.takeIf { it.isFromPlugin(compilerContext.afterK2) }
?: throw IllegalStateException(
"Can't find synthesized 'Companion.serializer()' function to generate, " +
"probably clash with user-defined function has occurred"
)
if (serializableIrClass.isSerializableObject
|| serializableIrClass.isAbstractOrSealedSerializableClass
@@ -115,7 +120,8 @@ class SerializableCompanionIrGenerator(
)
)
val kSerializerIrClass = compilerContext.referenceClass(ClassId(SerializationPackages.packageFqName, SerialEntityNames.KSERIALIZER_NAME))!!.owner
val kSerializerIrClass =
compilerContext.referenceClass(ClassId(SerializationPackages.packageFqName, SerialEntityNames.KSERIALIZER_NAME))!!.owner
val targetIrType =
kSerializerIrClass.defaultType.substitute(mapOf(kSerializerIrClass.typeParameters[0].symbol to compilerContext.irBuiltIns.anyType))
@@ -154,7 +160,8 @@ class SerializableCompanionIrGenerator(
private fun getOrCreateSerializerVarargFactory(): IrSimpleFunction {
irClass.findDeclaration<IrSimpleFunction> {
it.valueParameters.size == 1
it.name == SerialEntityNames.SERIALIZER_PROVIDER_NAME
&& it.valueParameters.size == 1
&& it.valueParameters.first().isVararg
&& it.returnType.isKSerializer()
&& it.isFromPlugin(compilerContext.afterK2)
@@ -0,0 +1,37 @@
// TARGET_BACKEND: JVM_IR
// WITH_STDLIB
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.builtins.*
@Serializable
data class Main(val fields: MainFields) {
companion object {
fun fieldsSerializer(): KSerializer<MainFields> = MainFields.serializer()
}
}
@Serializable
data class MainFields(val firstName: String?)
@Serializable
data class Box<T>(val boxed: T) {
companion object {
fun <T> serializerLike(tSer: KSerializer<T>): KSerializer<List<Box<T>>> = ListSerializer(serializer(tSer))
}
}
fun box(): String {
if (Main.fieldsSerializer().descriptor.toString() != "MainFields(firstName: kotlin.String?)") return "Error1"
if (MainFields.serializer().descriptor.toString() != "MainFields(firstName: kotlin.String?)") return "Error2"
if (Main.serializer().descriptor.toString() != "Main(fields: MainFields)") return "Error3"
val boxListDesc = Box.serializerLike(String.serializer()).descriptor
if (boxListDesc.toString() != "kotlin.collections.ArrayList(Box(boxed: kotlin.String))") return boxListDesc.toString()
val boxDesc = Box.serializer(String.serializer()).descriptor
if (boxDesc.toString() != "Box(boxed: kotlin.String)") return boxDesc.toString()
return "OK"
}
@@ -158,6 +158,12 @@ public class SerializationFirBlackBoxTestGenerated extends AbstractSerialization
public void testUseSerializersChain() throws Exception {
runTest("plugins/kotlinx-serialization/testData/boxIr/useSerializersChain.kt");
}
@Test
@TestMetadata("userDefinedSerializerInCompanion.kt")
public void testUserDefinedSerializerInCompanion() throws Exception {
runTest("plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt");
}
}
@Nested
@@ -156,4 +156,10 @@ public class SerializationIrBoxTestGenerated extends AbstractSerializationIrBoxT
public void testUseSerializersChain() throws Exception {
runTest("plugins/kotlinx-serialization/testData/boxIr/useSerializersChain.kt");
}
@Test
@TestMetadata("userDefinedSerializerInCompanion.kt")
public void testUserDefinedSerializerInCompanion() throws Exception {
runTest("plugins/kotlinx-serialization/testData/boxIr/userDefinedSerializerInCompanion.kt");
}
}