diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPreGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPreGenerator.kt index cebff63e5ad..09b984207c6 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPreGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/backend/ir/IrPreGenerator.kt @@ -56,7 +56,7 @@ class IrPreGenerator( dispatchReceiverParameter = null // function is static } - val typeParams = serializerDescriptor.typeParameters.map { + val typeParams = irClass.typeParameters.map { method.addTypeParameter( it.name.asString(), compilerContext.irBuiltIns.anyNType ) diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt index dab892a38a6..faaec7afda1 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/fir/SerializationFirUtils.kt @@ -46,7 +46,7 @@ internal val FirClassSymbol<*>.isInternallySerializableObject: Boolean get() = classKind == ClassKind.OBJECT && hasSerializableAnnotationWithoutArgs internal val FirClassSymbol<*>.isSealedSerializableInterface: Boolean - get() = classKind == ClassKind.INTERFACE && modality == Modality.SEALED && hasSerializableAnnotation + get() = classKind == ClassKind.INTERFACE && rawStatus.modality == Modality.SEALED && hasSerializableAnnotation internal val FirClassSymbol<*>.isInternalSerializable: Boolean get() { diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirBlackBoxTestGenerated.java b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirBlackBoxTestGenerated.java index 2acb1603e16..63ad7828183 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirBlackBoxTestGenerated.java +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirBlackBoxTestGenerated.java @@ -20,6 +20,12 @@ import java.util.regex.Pattern; @TestMetadata("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers") @TestDataPath("$PROJECT_ROOT") public class SerializationFirBlackBoxTestGenerated extends AbstractSerializationFirBlackBoxTest { + @Test + @TestMetadata("abstractAndSealed.kt") + public void testAbstractAndSealed() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.kt"); + } + @Test public void testAllFilesPresentInFirMembers() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirMembersTestGenerated.java b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirMembersTestGenerated.java index ed67b2592d8..ba707c4f942 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirMembersTestGenerated.java +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationFirMembersTestGenerated.java @@ -19,6 +19,12 @@ import java.util.regex.Pattern; @TestMetadata("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers") @TestDataPath("$PROJECT_ROOT") public class SerializationFirMembersTestGenerated extends AbstractSerializationFirMembersTest { + @Test + @TestMetadata("abstractAndSealed.kt") + public void testAbstractAndSealed() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.kt"); + } + @Test public void testAllFilesPresentInFirMembers() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers"), Pattern.compile("^(.+)\\.kt$"), null, true); diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.fir.txt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.fir.txt new file mode 100644 index 00000000000..b7122cb08bc --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.fir.txt @@ -0,0 +1,144 @@ +FILE: abstractAndSealed.kt + @R|kotlinx/serialization/Serializable|() public sealed interface I : R|kotlin/Any| { + public final companion object Companion : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|I.Companion| + + } + + } + @R|kotlinx/serialization/Serializable|() public sealed class X : R|I| { + protected constructor(): R|X| { + super() + } + + private final var x: R|kotlin/String| = String(X) + private get(): R|kotlin/String| + private set(value: R|kotlin/String|): R|kotlin/Unit| + + public final fun exposeX(): R|kotlin/String| { + ^exposeX this@R|/X|.R|/X.x| + } + + public final companion object Companion : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|X.Companion| + + } + + } + @R|kotlinx/serialization/Serializable|() public abstract class Y : R|X| { + public constructor(): R|Y| { + super() + } + + private final var y: R|kotlin/String| = String(Y) + private get(): R|kotlin/String| + private set(value: R|kotlin/String|): R|kotlin/Unit| + + public final fun exposeY(): R|kotlin/String| { + ^exposeY this@R|/Y|.R|/Y.y| + } + + public final companion object Companion : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|Y.Companion| + + } + + } + @R|kotlinx/serialization/Serializable|() public final class Bottom : R|Y| { + public constructor(): R|Bottom| { + super() + } + + public final companion object Companion : R|kotlin/Any| { + public final fun serializer(): R|kotlinx/serialization/KSerializer| + + private constructor(): R|Bottom.Companion| + + } + + public final object $serializer : R|kotlinx/serialization/internal/GeneratedSerializer| { + public final fun serialize(encoder: R|kotlinx/serialization/encoding/Encoder|, value: R|Bottom|): R|kotlin/Unit| + + public final fun deserialize(decoder: R|kotlinx/serialization/encoding/Decoder|): R|Bottom| + + public final val descriptor: R|kotlinx/serialization/descriptors/SerialDescriptor| + public get(): R|kotlinx/serialization/descriptors/SerialDescriptor| + + public final fun childSerializers(): R|kotlin/Array>| + + private constructor(): R|Bottom.$serializer| + + } + + } + public final fun testData(results: R|kotlin/String|): R|kotlin/String| { + when () { + !=(R|/results|, String(OK)) -> { + ^testData R|/results| + } + } + + lval serial: R|kotlinx/serialization/KSerializer| = Q|Bottom|.R|/Bottom.Companion.serializer|() + lval j: R|kotlinx/serialization/json/Json| = R|kotlinx/serialization/json/Json|( = Json@fun R|kotlinx/serialization/json/JsonBuilder|.(): R|kotlin/Unit| { + this@R|special/anonymous|.R|kotlinx/serialization/json/JsonBuilder.encodeDefaults| = Boolean(true) + } + ) + lval s: R|kotlin/String| = R|/j|.R|kotlinx/serialization/json/Json.encodeToString|(R|/serial|, R|/Bottom.Bottom|()) + when () { + !=(R|/s|, String({"x":"X","y":"Y"})) -> { + ^testData (String(Incorrect encoding: ), R|/s|) + } + } + + lval decoded: R|Bottom| = R|/j|.R|kotlinx/serialization/json/Json.decodeFromString|(R|/serial|, String({"x":"1","y":"2"})) + when () { + !=(R|/decoded|.R|/X.exposeX|(), String(1)) -> { + ^testData String(Incorrect X) + } + } + + when () { + !=(R|/decoded|.R|/Y.exposeY|(), String(2)) -> { + ^testData String(Incorrect Y) + } + } + + ^testData String(OK) + } + @R|kotlin/OptIn|(markerClass = vararg((Q|kotlinx/serialization/ExperimentalSerializationApi|))) public final fun testKinds(): R|kotlin/String| { + when () { + !=(Q|I|.R|/I.Companion.serializer|().R|SubstitutionOverride|.R|kotlinx/serialization/descriptors/SerialDescriptor.kind|, Q|kotlinx/serialization/descriptors/PolymorphicKind.SEALED|) -> { + ^testKinds String(Not sealed: I) + } + } + + when () { + !=(Q|X|.R|/X.Companion.serializer|().R|SubstitutionOverride|.R|kotlinx/serialization/descriptors/SerialDescriptor.kind|, Q|kotlinx/serialization/descriptors/PolymorphicKind.SEALED|) -> { + ^testKinds String(Not sealed: X) + } + } + + when () { + !=(Q|Y|.R|/Y.Companion.serializer|().R|SubstitutionOverride|.R|kotlinx/serialization/descriptors/SerialDescriptor.kind|, Q|kotlinx/serialization/descriptors/PolymorphicKind.OPEN|) -> { + ^testKinds String(Not polymorphic: Y) + } + } + + lval serial: R|kotlinx/serialization/KSerializer| = Q|Bottom|.R|/Bottom.Companion.serializer|() + when () { + !=(R|/serial|.R|SubstitutionOverride|.R|kotlinx/serialization/descriptors/SerialDescriptor.kind|, Q|kotlinx/serialization/descriptors/StructureKind.CLASS|) -> { + ^testKinds String(Not class: Bottom) + } + } + + ^testKinds String(OK) + } + public final fun box(): R|kotlin/String| { + ^box R|/testData|(R|/testKinds|()) + } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.kt new file mode 100644 index 00000000000..e3317e5579e --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/firMembers/abstractAndSealed.kt @@ -0,0 +1,51 @@ +// WITH_STDLIB + +import kotlinx.serialization.* +import kotlinx.serialization.descriptors.* +import kotlinx.serialization.json.* + +@Serializable +sealed interface I + +@Serializable +sealed class X: I { + private var x = "X" + + fun exposeX() = x +} + +@Serializable +abstract class Y: X() { + private var y = "Y" + + fun exposeY() = y +} + +@Serializable +class Bottom: Y() + +fun testData(results: String): String { + if (results != "OK") return results + val serial = Bottom.serializer() + val j = Json { encodeDefaults = true } + val s = j.encodeToString(serial, Bottom()) + if (s != """{"x":"X","y":"Y"}""") return "Incorrect encoding: $s" + val decoded = j.decodeFromString(serial, """{"x":"1","y":"2"}""") + if (decoded.exposeX() != "1") return "Incorrect X" + if (decoded.exposeY() != "2") return "Incorrect Y" + return "OK" +} + +@OptIn(ExperimentalSerializationApi::class) +fun testKinds(): String { + if (I.serializer().descriptor.kind != PolymorphicKind.SEALED) return "Not sealed: I" + if (X.serializer().descriptor.kind != PolymorphicKind.SEALED) return "Not sealed: X" + if (Y.serializer().descriptor.kind != PolymorphicKind.OPEN) return "Not polymorphic: Y" + val serial = Bottom.serializer() + if (serial.descriptor.kind != StructureKind.CLASS) return "Not class: Bottom" + return "OK" +} + +fun box(): String { + return testData(testKinds()) +} \ No newline at end of file