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 09b984207c6..00227edf557 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 @@ -34,8 +34,8 @@ class IrPreGenerator( val irClass: IrClass, compilerContext: SerializationPluginContext, ) : BaseIrGenerator(irClass, compilerContext) { - private val serialDescriptorSymbol = compilerContext.getClassFromRuntime(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS) - fun generate() { + + private fun generate() { preGenerateWriteSelfMethodIfNeeded() preGenerateDeserializationConstructorIfNeeded() } @@ -75,6 +75,7 @@ class IrPreGenerator( SERIALIZATION_PLUGIN_ORIGIN ) // descriptor + val serialDescriptorSymbol = compilerContext.getClassFromRuntime(SerialEntityNames.SERIAL_DESCRIPTOR_CLASS) method.addValueParameter( Name.identifier("serialDesc"), serialDescriptorSymbol.defaultType, SERIALIZATION_PLUGIN_ORIGIN @@ -93,7 +94,9 @@ class IrPreGenerator( private fun preGenerateDeserializationConstructorIfNeeded() { if (!irClass.isInternalSerializable) return // do not add synthetic deserialization constructor if .deserialize method is customized - if (irClass.hasCompanionObjectAsSerializer && irClass.companionObject()?.findPluginGeneratedMethod(SerialEntityNames.LOAD) == null) return + if (irClass.hasCompanionObjectAsSerializer && irClass.companionObject() + ?.findPluginGeneratedMethod(SerialEntityNames.LOAD) == null + ) return if (irClass.isValue) return if (irClass.findSerializableSyntheticConstructor() != null) return val ctor = irClass.addConstructor { @@ -120,4 +123,14 @@ class IrPreGenerator( if (this.isPrimitiveType(false)) this else this.makeNullable() + companion object { + fun generate( + irClass: IrClass, + compilerContext: SerializationPluginContext + ) { + if (!irClass.isInternalSerializable) return + IrPreGenerator(irClass, compilerContext).generate() + } + } + } \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt index 7e466c58554..eabee0f3291 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/src/org/jetbrains/kotlinx/serialization/compiler/extensions/SerializationLoweringExtension.kt @@ -109,7 +109,7 @@ private class SerializerClassPreLowering( override fun lower(irClass: IrClass) { irClass.runPluginSafe { - IrPreGenerator(irClass, context).generate() + IrPreGenerator.generate(irClass, context) } } } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationWithoutRuntimeIrBoxTest.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationWithoutRuntimeIrBoxTest.kt new file mode 100644 index 00000000000..688c3e974f5 --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationWithoutRuntimeIrBoxTest.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2021 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. + */ + +package org.jetbrains.kotlinx.serialization + +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.runners.codegen.AbstractIrBlackBoxCodegenTest + +open class AbstractSerializationWithoutRuntimeIrBoxTest : AbstractIrBlackBoxCodegenTest() { + override fun configure(builder: TestConfigurationBuilder) { + super.configure(builder) + builder.configureForKotlinxSerialization(emptyList()) + } + +} \ No newline at end of file diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationWithoutRuntimeIrBoxTestGenerated.java b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationWithoutRuntimeIrBoxTestGenerated.java new file mode 100644 index 00000000000..bde9d5cc27d --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationWithoutRuntimeIrBoxTestGenerated.java @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2022 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. + */ + +package org.jetbrains.kotlinx.serialization; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link GenerateNewCompilerTests.kt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxWithoutRuntime") +@TestDataPath("$PROJECT_ROOT") +public class SerializationWithoutRuntimeIrBoxTestGenerated extends AbstractSerializationWithoutRuntimeIrBoxTest { + @Test + public void testAllFilesPresentInBoxWithoutRuntime() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxWithoutRuntime"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("basic.kt") + public void testBasic() throws Exception { + runTest("plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxWithoutRuntime/basic.kt"); + } +} diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/TestGenerator.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/TestGenerator.kt index bb0c0e4f227..4a582ec9510 100644 --- a/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/TestGenerator.kt +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/TestGenerator.kt @@ -21,6 +21,10 @@ fun main(args: Array) { model("boxIr") } + testClass { + model("boxWithoutRuntime") + } + testClass { model("firMembers") } diff --git a/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxWithoutRuntime/basic.kt b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxWithoutRuntime/basic.kt new file mode 100644 index 00000000000..a22d8a3857a --- /dev/null +++ b/plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxWithoutRuntime/basic.kt @@ -0,0 +1,23 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_STDLIB + +/** + * This test checks that in the case when serialization plugin is applied, but kotlinx-serialization-core runtime is not present in compile classpath, + * compilation of regular Kotlin classes still finishes succesfully. + * + * Such requirement is needed for cases when plugin is applied to a Gradle module, but runtime dependency is provided only in certain configurations, + * e.g. only in `testImplementation` configuration (see :wasm:wasm-ir module). In such setup, production sources have plugin applied, but no runtime in classpath. + */ + +data class X(val i: Int) { + companion object { + fun x(): X = X(42) + } +} + +fun box(): String { + val i = X.x().i + return if (i == 42) "OK" else i.toString() +} \ No newline at end of file