From 0869dd9c92b3053037890c58f3bfd2fb19ee4ead Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Thu, 18 Aug 2022 15:48:47 +0200 Subject: [PATCH] Repair bootstrapping for wasm-ir module by removing class referencing from constructor of kotlinx.serialization ir generator. Such references may be null if plugin was applied to the module, but no runtime was provided in current compile configuration (see added test). --- .../compiler/backend/ir/IrPreGenerator.kt | 19 +++++++++-- .../SerializationLoweringExtension.kt | 2 +- ...actSerializationWithoutRuntimeIrBoxTest.kt | 17 ++++++++++ ...ationWithoutRuntimeIrBoxTestGenerated.java | 33 +++++++++++++++++++ .../kotlinx/serialization/TestGenerator.kt | 4 +++ .../testData/boxWithoutRuntime/basic.kt | 23 +++++++++++++ 6 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/AbstractSerializationWithoutRuntimeIrBoxTest.kt create mode 100644 plugins/kotlin-serialization/kotlin-serialization-compiler/test/org/jetbrains/kotlinx/serialization/SerializationWithoutRuntimeIrBoxTestGenerated.java create mode 100644 plugins/kotlin-serialization/kotlin-serialization-compiler/testData/boxWithoutRuntime/basic.kt 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