Use a correct type for SERIALIZER_TYPE_INCOMPATIBLE diagnostic.

This diagnostic used an incorrect type for rendering (outer class type instead of a property type)
and didn't expand type argument of `KSerializer`.

Also add an additional test case for generic parameters.

#KT-63570 Fixed
This commit is contained in:
Leonid Startsev
2023-11-24 16:16:51 +01:00
committed by Space Team
parent 1260d03561
commit 51e3e9af94
7 changed files with 112 additions and 2 deletions
@@ -564,14 +564,14 @@ object FirSerializationPluginClassChecker : FirClassChecker() {
serializerType: ConeKotlinType,
reporter: DiagnosticReporter
) {
val serializerForType = serializerType.serializerForType(session) ?: return
val serializerForType = serializerType.serializerForType(session)?.fullyExpandedType(session) ?: return
val declarationTypeClassId = declarationType.classId
if (declarationTypeClassId == null || declarationTypeClassId != serializerForType.classId) {
reporter.reportOn(
source ?: containingClassSymbol.serializableOrMetaAnnotationSource,
FirSerializationErrors.SERIALIZER_TYPE_INCOMPATIBLE,
containingClassSymbol.defaultType(),
declarationType,
serializerType,
serializerForType
)
@@ -40,3 +40,11 @@ class Foo6(@Serializable(with = NullableBazSerializer::class) val i: <!SERIALIZE
@Serializable
class Foo7(@Serializable(with = NullableBazSerializer::class) val i: <!SERIALIZER_TYPE_INCOMPATIBLE!>Bar?<!>)
// It is OK to report, because subclasses can't generally be deserialized (as `deserialize()` signature returns base class)
@Serializable
@Suppress("FINAL_UPPER_BOUND")
class Foo8<Br: Bar>(@Serializable(BarSerializer::class) val b: <!SERIALIZER_TYPE_INCOMPATIBLE("Br; BarSerializer; Bar")!>Br<!>)
@Serializable
class Foo9<T>(@Serializable(BarSerializer::class) val b: <!SERIALIZER_TYPE_INCOMPATIBLE("T; BarSerializer; Bar")!>T<!>)
@@ -40,3 +40,11 @@ class Foo6(@Serializable(with = NullableBazSerializer::class) val i: <!SERIALIZE
@Serializable
class Foo7(@Serializable(with = NullableBazSerializer::class) val i: <!SERIALIZER_TYPE_INCOMPATIBLE!>Bar?<!>)
// It is OK to report, because subclasses can't generally be deserialized (as `deserialize()` signature returns base class)
@Serializable
@Suppress("FINAL_UPPER_BOUND")
class Foo8<Br: Bar>(@Serializable(BarSerializer::class) val b: <!SERIALIZER_TYPE_INCOMPATIBLE("Br; BarSerializer; Bar")!>Br<!>)
@Serializable
class Foo9<T>(@Serializable(BarSerializer::class) val b: <!SERIALIZER_TYPE_INCOMPATIBLE("T; BarSerializer; Bar")!>T<!>)
@@ -0,0 +1,41 @@
// FIR_DISABLE_LAZY_RESOLVE_CHECKS
// WITH_STDLIB
// MODULE: lib
// FILE: libtest.kt
import kotlinx.serialization.*
import java.util.*
typealias MyDate = java.util.Date
// MODULE: main(lib)
// FILE: test.kt
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
internal object MyDateSerializer : KSerializer<MyDate> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("uuid", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder) = TODO()
override fun serialize(
encoder: Encoder,
value: MyDate
) = encoder.encodeString(value.toString())
}
@Serializable
data class Session(
@Serializable(MyDateSerializer::class) val date: MyDate,
@Serializable(MyDateSerializer::class) val alsoDate: java.util.Date,
// The only difference with FIR is how RENDER_TYPE works:
@Serializable(MyDateSerializer::class) val s: <!SERIALIZER_TYPE_INCOMPATIBLE("kotlin.String; MyDateSerializer; java.util.Date")!>String<!>,
val sl: List<<!SERIALIZER_TYPE_INCOMPATIBLE("@Serializable(...) kotlin.String; MyDateSerializer; java.util.Date")!>@Serializable(MyDateSerializer::class) String<!>>
)
@@ -0,0 +1,41 @@
// FIR_DISABLE_LAZY_RESOLVE_CHECKS
// WITH_STDLIB
// MODULE: lib
// FILE: libtest.kt
import kotlinx.serialization.*
import java.util.*
typealias MyDate = java.util.Date
// MODULE: main(lib)
// FILE: test.kt
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
internal object MyDateSerializer : KSerializer<MyDate> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("uuid", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder) = TODO()
override fun serialize(
encoder: Encoder,
value: MyDate
) = encoder.encodeString(value.toString())
}
@Serializable
data class Session(
@Serializable(MyDateSerializer::class) val date: MyDate,
@Serializable(MyDateSerializer::class) val alsoDate: java.util.Date,
// The only difference with FIR is how RENDER_TYPE works:
@Serializable(MyDateSerializer::class) val s: <!SERIALIZER_TYPE_INCOMPATIBLE("String; MyDateSerializer; MyDate /* = Date */")!>String<!>,
val sl: List<@Serializable(MyDateSerializer::class) <!SERIALIZER_TYPE_INCOMPATIBLE("String; MyDateSerializer; MyDate /* = Date */")!>String<!>>
)
@@ -164,6 +164,12 @@ public class SerializationFirPsiDiagnosticTestGenerated extends AbstractSerializ
runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt");
}
@Test
@TestMetadata("SerializerTypeIncompatibleViaTypealias.kt")
public void testSerializerTypeIncompatibleViaTypealias() throws Exception {
runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.kt");
}
@Test
@TestMetadata("Transients.kt")
public void testTransients() throws Exception {
@@ -162,6 +162,12 @@ public class SerializationPluginDiagnosticTestGenerated extends AbstractSerializ
runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatible.kt");
}
@Test
@TestMetadata("SerializerTypeIncompatibleViaTypealias.kt")
public void testSerializerTypeIncompatibleViaTypealias() throws Exception {
runTest("plugins/kotlinx-serialization/testData/diagnostics/SerializerTypeIncompatibleViaTypealias.kt");
}
@Test
@TestMetadata("Transients.kt")
public void testTransients() throws Exception {