diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index e91f0671180..62237f3711f 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -8767,6 +8767,11 @@ + + + + + @@ -8813,6 +8818,11 @@ + + + + + @@ -8877,6 +8887,11 @@ + + + + + @@ -8909,6 +8924,11 @@ + + + + + diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts b/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts index 64eafb58b37..740a5a576ac 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/build.gradle.kts @@ -41,8 +41,8 @@ dependencies { testApi(commonDependency("junit:junit")) testApiJUnit5(vintageEngine = true) - testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.2.2") - testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2") + testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.0-RC") + testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0-RC") testRuntimeOnly(intellijCore()) } 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 6f4a792c683..9f6861ad589 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 @@ -563,10 +563,7 @@ interface IrBuilderExtension { } irAccessor.body = when (isGetter) { - true -> { - irAccessor.returnType = irAccessor.returnType.kClassToJClassIfNeeded() - generateDefaultGetterBody(descriptor as PropertyGetterDescriptor, irAccessor) - } + true -> generateDefaultGetterBody(descriptor as PropertyGetterDescriptor, irAccessor) false -> generateDefaultSetterBody(descriptor as PropertySetterDescriptor, irAccessor) } @@ -597,7 +594,10 @@ interface IrBuilderExtension { propertyIrType, receiver ).let { - if (propertyIrType.isKClass()) kClassExprToJClassIfNeeded(startOffset, endOffset, it) else it + if (propertyIrType.isKClass()) { + irAccessor.returnType = irAccessor.returnType.kClassToJClassIfNeeded() + kClassExprToJClassIfNeeded(startOffset, endOffset, it) + } else it } ) ) @@ -1115,6 +1115,7 @@ interface IrBuilderExtension { } else { constructors.find { it.owner.lastArgumentIsAnnotationArray() } ?: run { // not found - we are using old serialization runtime without this feature + // todo: optimize allocating an empty array when no annotations defined, maybe use old constructor? needToCopyAnnotations = false constructors.single { it.owner.isPrimary } } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxIr/metaSerializable.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxIr/metaSerializable.kt index 39fb7f04329..62b41388563 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxIr/metaSerializable.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxIr/metaSerializable.kt @@ -3,7 +3,6 @@ // WITH_STDLIB -import kotlinx.serialization.* import kotlinx.serialization.* import kotlinx.serialization.encoding.* import kotlinx.serialization.descriptors.* @@ -13,11 +12,11 @@ import kotlin.test.* // TODO: for this test to work, runtime dependency should be updated to (yet unreleased) serialization with @MetaSerializable annotation -//@MetaSerializable +@MetaSerializable @Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY) annotation class MySerializable -//@MetaSerializable +@MetaSerializable @Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY) annotation class MySerializableWithInfo( val value: Int, @@ -32,7 +31,7 @@ class Project2(val name: String, val language: String) @Serializable class Wrapper( -// @MySerializableWithInfo(234, Int::class) val project: Project2 + @MySerializableWithInfo(234, Int::class) val project: Project2 ) @Serializable @@ -40,7 +39,7 @@ class Wrapper( class Project3(val name: String, val language: String) @Serializable(with = MySerializer::class) -//@MySerializableWithInfo(123, String::class) +@MySerializableWithInfo(123, String::class) class Project4(val name: String, val language: String) @MySerializableWithInfo(123, String::class) @@ -79,99 +78,99 @@ object MySerializer : KSerializer { } fun testMetaSerializable() { -// val string = Json.encodeToString(Project1.serializer(), Project1("name", "lang")) -// assertEquals("""{"name":"name","language":"lang"}""", string) -// -// val reconstructed = Json.decodeFromString(Project1.serializer(), string) -// assertEquals("name", reconstructed.name) -// assertEquals("lang", reconstructed.language) + val string = Json.encodeToString(Project1.serializer(), Project1("name", "lang")) + assertEquals("""{"name":"name","language":"lang"}""", string) + + val reconstructed = Json.decodeFromString(Project1.serializer(), string) + assertEquals("name", reconstructed.name) + assertEquals("lang", reconstructed.language) } fun testMetaSerializableWithInfo() { -// val string = Json.encodeToString(Project2.serializer(), Project2("name", "lang")) -// assertEquals("""{"name":"name","language":"lang"}""", string) -// -// val reconstructed = Json.decodeFromString(Project2.serializer(), string) -// assertEquals("name", reconstructed.name) -// assertEquals("lang", reconstructed.language) -// -// val info = Project2.serializer().descriptor.annotations.filterIsInstance().first() -// assertEquals(123, info.value) -// assertEquals(String::class, info.kclass) + val string = Json.encodeToString(Project2.serializer(), Project2("name", "lang")) + assertEquals("""{"name":"name","language":"lang"}""", string) + + val reconstructed = Json.decodeFromString(Project2.serializer(), string) + assertEquals("name", reconstructed.name) + assertEquals("lang", reconstructed.language) + + val info = Project2.serializer().descriptor.annotations.filterIsInstance().first() + assertEquals(123, info.value) + assertEquals(String::class, info.kclass) } fun testMetaSerializableOnProperty() { -// val info = Wrapper.serializer().descriptor.getElementAnnotations(0).filterIsInstance().first() -// assertEquals(234, info.value) -// assertEquals(Int::class, info.kclass) + val info = Wrapper.serializer().descriptor.getElementAnnotations(0).filterIsInstance().first() + assertEquals(234, info.value) + assertEquals(Int::class, info.kclass) } fun testSerializableAndMetaAnnotation() { -// val string = Json.encodeToString(Project3.serializer(), Project3("name", "lang")) -// assertEquals("""{"name":"name","language":"lang"}""", string) -// -// val reconstructed = Json.decodeFromString(Project3.serializer(), string) -// assertEquals("name", reconstructed.name) -// assertEquals("lang", reconstructed.language) -// -// val info = Project3.serializer().descriptor.annotations.filterIsInstance().first() -// assertEquals(123, info.value) -// assertEquals(String::class, info.kclass) + val string = Json.encodeToString(Project3.serializer(), Project3("name", "lang")) + assertEquals("""{"name":"name","language":"lang"}""", string) + + val reconstructed = Json.decodeFromString(Project3.serializer(), string) + assertEquals("name", reconstructed.name) + assertEquals("lang", reconstructed.language) + + val info = Project3.serializer().descriptor.annotations.filterIsInstance().first() + assertEquals(123, info.value) + assertEquals(String::class, info.kclass) } fun testCustomSerializerAndMetaAnnotation() { -// val string = Json.encodeToString(Project4.serializer(), Project4("name", "lang")) -// assertEquals("""name:lang""", string) -// -// val reconstructed = Json.decodeFromString(Project4.serializer(), string) -// assertEquals("name", reconstructed.name) -// assertEquals("lang", reconstructed.language) + val string = Json.encodeToString(Project4.serializer(), Project4("name", "lang")) + assertEquals("""name:lang""", string) + + val reconstructed = Json.decodeFromString(Project4.serializer(), string) + assertEquals("name", reconstructed.name) + assertEquals("lang", reconstructed.language) } fun testSealed() { -// val serializerA = TestSealed.A.serializer() -// val serializerB = TestSealed.B.serializer() -// assertNotNull(serializerA) -// assertNotNull(serializerB) -// -// val infoA = serializerA.descriptor.annotations.filterIsInstance().first() -// val infoB = serializerB.descriptor.annotations.filterIsInstance().first() -// assertEquals(123, infoA.value) -// assertEquals(String::class, infoA.kclass) -// assertEquals(123, infoB.value) -// assertEquals(String::class, infoB.kclass) + val serializerA = TestSealed.A.serializer() + val serializerB = TestSealed.B.serializer() + assertNotNull(serializerA) + assertNotNull(serializerB) + + val infoA = serializerA.descriptor.annotations.filterIsInstance().first() + val infoB = serializerB.descriptor.annotations.filterIsInstance().first() + assertEquals(123, infoA.value) + assertEquals(String::class, infoA.kclass) + assertEquals(123, infoB.value) + assertEquals(String::class, infoB.kclass) } fun testAbstract() { -// val serializerA = TestAbstract.A.serializer() -// val serializerB = TestAbstract.B.serializer() -// assertNotNull(serializerA) -// assertNotNull(serializerB) -// -// val infoA = serializerA.descriptor.annotations.filterIsInstance().first() -// val infoB = serializerB.descriptor.annotations.filterIsInstance().first() -// assertEquals(123, infoA.value) -// assertEquals(String::class, infoA.kclass) -// assertEquals(123, infoB.value) -// assertEquals(String::class, infoB.kclass) + val serializerA = TestAbstract.A.serializer() + val serializerB = TestAbstract.B.serializer() + assertNotNull(serializerA) + assertNotNull(serializerB) + + val infoA = serializerA.descriptor.annotations.filterIsInstance().first() + val infoB = serializerB.descriptor.annotations.filterIsInstance().first() + assertEquals(123, infoA.value) + assertEquals(String::class, infoA.kclass) + assertEquals(123, infoB.value) + assertEquals(String::class, infoB.kclass) } fun testEnum() { -// val serializer = TestEnum.serializer() -// assertNotNull(serializer) -// -// val info = serializer.descriptor.annotations.filterIsInstance().first() -// assertEquals(123, info.value) -// assertEquals(String::class, info.kclass) + val serializer = TestEnum.serializer() + assertNotNull(serializer) + + val info = serializer.descriptor.annotations.filterIsInstance().first() + assertEquals(123, info.value) + assertEquals(String::class, info.kclass) } fun testObject() { -// val serializer = TestObject.serializer() -// assertNotNull(serializer) -// -// val info = serializer.descriptor.annotations.filterIsInstance().first() -// assertEquals(123, info.value) -// assertEquals(String::class, info.kclass) + val serializer = TestObject.serializer() + assertNotNull(serializer) + + val info = serializer.descriptor.annotations.filterIsInstance().first() + assertEquals(123, info.value) + assertEquals(String::class, info.kclass) } fun box(): String {