diff --git a/compiler/testData/codegen/box/multiplatform/k2/basic/independentCommonSourceModules.kt b/compiler/testData/codegen/box/multiplatform/k2/basic/independentCommonSourceModules.kt index 9685eb21b9a..33be201b2c1 100644 --- a/compiler/testData/codegen/box/multiplatform/k2/basic/independentCommonSourceModules.kt +++ b/compiler/testData/codegen/box/multiplatform/k2/basic/independentCommonSourceModules.kt @@ -8,6 +8,10 @@ fun o() = "O" // MODULE: common2 // TARGET_PLATFORM: Common +// The test framework adds additional files to common modules with no dependencies. +// Those files should only be added once, so we exclude them from common2 and only include +// them in common1. +// NO_COMMON_FILES // FILE: common2.kt fun k() = "K" diff --git a/compiler/testData/codegen/box/multiplatform/k2/defaultArguments/suspend.kt b/compiler/testData/codegen/box/multiplatform/k2/defaultArguments/suspend.kt index f41711b12ca..321e54e3b66 100644 --- a/compiler/testData/codegen/box/multiplatform/k2/defaultArguments/suspend.kt +++ b/compiler/testData/codegen/box/multiplatform/k2/defaultArguments/suspend.kt @@ -1,6 +1,5 @@ // LANGUAGE: +MultiPlatformProjects // WITH_STDLIB -// WITH_COROUTINES // MODULE: common // FILE: common.kt @@ -10,6 +9,7 @@ expect interface I { } // MODULE: main()()(common) +// WITH_COROUTINES // FILE: main.kt import kotlin.coroutines.* import helpers.* diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/WasmEnvironmentConfigurationDirectives.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/WasmEnvironmentConfigurationDirectives.kt index b3e8201bde1..04c6e6d1fc1 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/WasmEnvironmentConfigurationDirectives.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/WasmEnvironmentConfigurationDirectives.kt @@ -47,4 +47,11 @@ object WasmEnvironmentConfigurationDirectives : SimpleDirectivesContainer() { val CHECK_TYPESCRIPT_DECLARATIONS by directive( description = "Check typescript declarations generated by the compiler", ) + + val NO_COMMON_FILES by directive( + """ + Don't added helper files to prevent linking issues. + """.trimIndent(), + applicability = DirectiveApplicability.Global, + ) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/ModuleStructureExtractorImpl.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/ModuleStructureExtractorImpl.kt index 5e4cb34fafb..1cf8f8b4f2d 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/ModuleStructureExtractorImpl.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/services/impl/ModuleStructureExtractorImpl.kt @@ -355,18 +355,13 @@ class ModuleStructureExtractorImpl( directives = moduleDirectives, languageVersionSettings = currentModuleLanguageVersionSettingsBuilder.build() ) - if (testModule.frontendKind != FrontendKinds.FIR || - !testModule.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) || - modules.isEmpty() - ) { - additionalSourceProviders.flatMapTo(filesOfCurrentModule) { additionalSourceProvider -> - additionalSourceProvider.produceAdditionalFiles( - globalDirectives ?: RegisteredDirectives.Empty, - testModule - ).also { additionalFiles -> - require(additionalFiles.all { it.isAdditional }) { - "Files produced by ${additionalSourceProvider::class.qualifiedName} should have flag `isAdditional = true`" - } + additionalSourceProviders.flatMapTo(filesOfCurrentModule) { additionalSourceProvider -> + additionalSourceProvider.produceAdditionalFiles( + globalDirectives ?: RegisteredDirectives.Empty, + testModule + ).also { additionalFiles -> + require(additionalFiles.all { it.isAdditional }) { + "Files produced by ${additionalSourceProvider::class.qualifiedName} should have flag `isAdditional = true`" } } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsAdditionalSourceProvider.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsAdditionalSourceProvider.kt index 443b4a72cfa..a5b5f64c44c 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/JsAdditionalSourceProvider.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/JsAdditionalSourceProvider.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.js.test +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.js.JavaScript import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives @@ -20,6 +21,11 @@ import java.io.FileFilter class JsAdditionalSourceProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) { override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List { if (JsEnvironmentConfigurationDirectives.NO_COMMON_FILES in module.directives) return emptyList() + // For multiplatform projects, add the files only to common modules with no dependencies. + if (module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) && + module.allDependencies.isNotEmpty()) { + return emptyList() + } return getAdditionalKotlinFiles(module.files.first().originalFile.parent).map { it.toTestFile() } } diff --git a/plugins/parcelize/parcelize-compiler/testData/box/additionalAnnotationTrigger.kt b/plugins/parcelize/parcelize-compiler/testData/box/additionalAnnotationTrigger.kt new file mode 100644 index 00000000000..80eb3f13977 --- /dev/null +++ b/plugins/parcelize/parcelize-compiler/testData/box/additionalAnnotationTrigger.kt @@ -0,0 +1,25 @@ +// TARGET_BACKEND: JVM_IR +// WITH_STDLIB + +@file:JvmName("TestKt") +package test + +import android.os.Parcelable +import kotlinx.parcelize.* + +annotation class TriggerParcelize + +@TriggerParcelize +data class User(val name: String) : Parcelable + +fun box() = parcelTest { parcel -> + val user = User("John") + user.writeToParcel(parcel, 0) + + val bytes = parcel.marshall() + parcel.unmarshall(bytes, 0, bytes.size) + parcel.setDataPosition(0) + + val user2 = parcelableCreator().createFromParcel(parcel) + assert(user == user2) +} \ No newline at end of file diff --git a/plugins/parcelize/parcelize-compiler/testData/box/mppWithExpectParcelable.kt b/plugins/parcelize/parcelize-compiler/testData/box/mppWithExpectParcelable.kt new file mode 100644 index 00000000000..9097fad7aec --- /dev/null +++ b/plugins/parcelize/parcelize-compiler/testData/box/mppWithExpectParcelable.kt @@ -0,0 +1,41 @@ +// TARGET_BACKEND: JVM_IR +// !LANGUAGE: +MultiPlatformProjects +// WITH_STDLIB + +// Metadata compilations do not see through the expect/actuals and therefore, +// there are parcelize errors in metadata compilations. +// IGNORE_FIR_DIAGNOSTICS_DIFF + +// MODULE: m1-common +// FILE: common.kt + +package test + +expect interface MyParcelable + +annotation class TriggerParcelize + +@TriggerParcelize +data class User(val name: String) : MyParcelable + +// MODULE: m2-jvm()()(m1-common) +// FILE: android.kt + +@file:JvmName("TestKt") +package test + +import kotlinx.parcelize.* + +actual typealias MyParcelable = android.os.Parcelable + +fun box() = parcelTest { parcel -> + val user = User("John") + user.writeToParcel(parcel, 0) + + val bytes = parcel.marshall() + parcel.unmarshall(bytes, 0, bytes.size) + parcel.setDataPosition(0) + + val user2 = parcelableCreator().createFromParcel(parcel) + assert(user == user2) +} \ No newline at end of file diff --git a/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeFirLightTreeBoxTestGenerated.java b/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeFirLightTreeBoxTestGenerated.java index 2d49835ff1a..33563a8bac0 100644 --- a/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeFirLightTreeBoxTestGenerated.java +++ b/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeFirLightTreeBoxTestGenerated.java @@ -19,6 +19,12 @@ import java.util.regex.Pattern; @TestMetadata("plugins/parcelize/parcelize-compiler/testData/box") @TestDataPath("$PROJECT_ROOT") public class ParcelizeFirLightTreeBoxTestGenerated extends AbstractParcelizeFirLightTreeBoxTest { + @Test + @TestMetadata("additionalAnnotationTrigger.kt") + public void testAdditionalAnnotationTrigger() { + runTest("plugins/parcelize/parcelize-compiler/testData/box/additionalAnnotationTrigger.kt"); + } + @Test public void testAllFilesPresentInBox() { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-compiler/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); @@ -324,6 +330,12 @@ public class ParcelizeFirLightTreeBoxTestGenerated extends AbstractParcelizeFirL runTest("plugins/parcelize/parcelize-compiler/testData/box/maps.kt"); } + @Test + @TestMetadata("mppWithExpectParcelable.kt") + public void testMppWithExpectParcelable() { + runTest("plugins/parcelize/parcelize-compiler/testData/box/mppWithExpectParcelable.kt"); + } + @Test @TestMetadata("nestedArrays.kt") public void testNestedArrays() { diff --git a/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeIrBoxTestGenerated.java b/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeIrBoxTestGenerated.java index a6ab6337915..f3082dd7bcb 100644 --- a/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeIrBoxTestGenerated.java +++ b/plugins/parcelize/parcelize-compiler/tests-gen/org/jetbrains/kotlin/parcelize/test/runners/ParcelizeIrBoxTestGenerated.java @@ -19,6 +19,12 @@ import java.util.regex.Pattern; @TestMetadata("plugins/parcelize/parcelize-compiler/testData/box") @TestDataPath("$PROJECT_ROOT") public class ParcelizeIrBoxTestGenerated extends AbstractParcelizeIrBoxTest { + @Test + @TestMetadata("additionalAnnotationTrigger.kt") + public void testAdditionalAnnotationTrigger() { + runTest("plugins/parcelize/parcelize-compiler/testData/box/additionalAnnotationTrigger.kt"); + } + @Test public void testAllFilesPresentInBox() { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/parcelize/parcelize-compiler/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); @@ -324,6 +330,12 @@ public class ParcelizeIrBoxTestGenerated extends AbstractParcelizeIrBoxTest { runTest("plugins/parcelize/parcelize-compiler/testData/box/maps.kt"); } + @Test + @TestMetadata("mppWithExpectParcelable.kt") + public void testMppWithExpectParcelable() { + runTest("plugins/parcelize/parcelize-compiler/testData/box/mppWithExpectParcelable.kt"); + } + @Test @TestMetadata("nestedArrays.kt") public void testNestedArrays() { diff --git a/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/runners/AbstractParcelizeBoxTest.kt b/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/runners/AbstractParcelizeBoxTest.kt index c7a1ef1b3a0..bb876146669 100644 --- a/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/runners/AbstractParcelizeBoxTest.kt +++ b/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/runners/AbstractParcelizeBoxTest.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler import org.jetbrains.kotlin.test.frontend.fir.Fir2IrJvmResultsConverter import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade +import org.jetbrains.kotlin.test.frontend.fir.FirMetaInfoDiffSuppressor import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticsHandler import org.jetbrains.kotlin.test.model.* @@ -122,6 +123,7 @@ abstract class AbstractParcelizeFirBoxTestBase(val parser: FirParser) : Abstract +ENABLE_PLUGIN_PHASES FirDiagnosticsDirectives.FIR_PARSER with parser } + useAfterAnalysisCheckers(::FirMetaInfoDiffSuppressor) } } } diff --git a/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeEnvironmentConfigurator.kt b/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeEnvironmentConfigurator.kt index f064b768d80..1d74d0011c0 100644 --- a/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeEnvironmentConfigurator.kt +++ b/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeEnvironmentConfigurator.kt @@ -42,13 +42,17 @@ class ParcelizeEnvironmentConfigurator(testServices: TestServices) : Environment kotlinxCollectionsImmutable ) ) + + // Hard coding a name of an additional annotation for parcelize. Test that use this, need to provide the + // additional annotations as part of the test sources. + configuration.put(ParcelizeConfigurationKeys.ADDITIONAL_ANNOTATION, listOf("test.TriggerParcelize")) } override fun CompilerPluginRegistrar.ExtensionStorage.registerCompilerExtensions( module: TestModule, configuration: CompilerConfiguration ) { - val additionalAnnotation = configuration.get(ParcelizeConfigurationKeys.ADDITIONAL_ANNOTATION) + val additionalAnnotation = configuration.get(ParcelizeConfigurationKeys.ADDITIONAL_ANNOTATION) ?: emptyList() ParcelizeComponentRegistrar.registerParcelizeComponents( this, additionalAnnotation, diff --git a/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeUtilSourcesProvider.kt b/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeUtilSourcesProvider.kt index 088dfbf34c6..d85d6ef2155 100644 --- a/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeUtilSourcesProvider.kt +++ b/plugins/parcelize/parcelize-compiler/tests/org/jetbrains/kotlin/parcelize/test/services/ParcelizeUtilSourcesProvider.kt @@ -17,6 +17,8 @@ class ParcelizeUtilSourcesProvider(testServices: TestServices, baseDir: String = @OptIn(ExperimentalStdlibApi::class) override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List { - return listOf(File(libraryPath).toTestFile()) + // Only provide the additional files for a JVM only module. In multiplatform tests, this ensures that the + // additional files are only provided once and in the right module. + return if (module.targetPlatform.all { it.platformName == "JVM" }) listOf(File(libraryPath).toTestFile()) else listOf() } } diff --git a/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/WasmAdditionalSourceProvider.kt b/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/WasmAdditionalSourceProvider.kt index dab036d3c6d..329995bf6dd 100644 --- a/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/WasmAdditionalSourceProvider.kt +++ b/wasm/wasm.tests/test/org/jetbrains/kotlin/wasm/test/WasmAdditionalSourceProvider.kt @@ -5,8 +5,10 @@ package org.jetbrains.kotlin.wasm.test +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives +import org.jetbrains.kotlin.test.directives.WasmEnvironmentConfigurationDirectives import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives import org.jetbrains.kotlin.test.model.TestFile import org.jetbrains.kotlin.test.model.TestModule @@ -24,7 +26,12 @@ class WasmWasiBoxTestHelperSourceProvider(testServices: TestServices) : Addition class WasmAdditionalSourceProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) { override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List { - if (JsEnvironmentConfigurationDirectives.NO_COMMON_FILES in module.directives) return emptyList() + if (WasmEnvironmentConfigurationDirectives.NO_COMMON_FILES in module.directives) return emptyList() + // For multiplatform projects, add the files only to common modules with no dependencies. + if (module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) && + module.allDependencies.isNotEmpty()) { + return emptyList() + } return getAdditionalKotlinFiles(module.files.first().originalFile.parent).map { it.toTestFile() } }