From edaf925b196edf74abd7ed76724d761cd262e4eb Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Thu, 29 Jul 2021 16:55:29 +0400 Subject: [PATCH] Reorder Gradle -Xplugin=... so that serialization goes first (KT-47921) Ensure that the serialization plugin's artifact (and, possibly, some other prioritized plugin artifacts) are put first to the -Xplugin=... classpath passed to the compiler. This fixes the conflict of the serialization plugin with some other plugins altering the IR in unexpected ways. Issue #KT-47921 --- .../jetbrains/kotlin/gradle/SubpluginsIT.kt | 26 +++++++++++++- .../internal/CompilerArgumentsContributor.kt | 4 +-- .../gradle/internal/compilerPluginUtils.kt | 35 +++++++++++++++++++ .../internal/kapt/KaptWithKotlincTask.kt | 4 +-- .../gradle/plugin/KotlinTargetConfigurator.kt | 2 ++ .../mpp/pm20/GradleKpmCompilerPlugin.kt | 3 +- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 1 + .../kotlin/gradle/utils/fileUtils.kt | 4 +-- 8 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/compilerPluginUtils.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt index fe4dc06ee8a..c16d34c1b3b 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/SubpluginsIT.kt @@ -275,6 +275,30 @@ class SubpluginsIT : BaseGradleIT() { Project("lombokProject").build("build") { assertSuccessful() } - + + } + + @Test // KT-47921 + fun testSerializationPluginOrderedFirst() = with(Project("allOpenSimple")) { + setupWorkingDir() + // Ensure that there are also allopen, noarg, and serialization plugins applied: + gradleBuildScript().appendText( + """ + buildscript { + dependencies { + classpath("org.jetbrains.kotlin:kotlin-noarg:${defaultBuildOptions().kotlinVersion}") + classpath("org.jetbrains.kotlin:kotlin-serialization:${defaultBuildOptions().kotlinVersion}") + } + } + apply plugin: "org.jetbrains.kotlin.plugin.noarg" + apply plugin: "org.jetbrains.kotlin.plugin.serialization" + """.trimIndent() + ) + + build("compileKotlin") { + assertSuccessful() + val xPlugin = output.split(" ").single { it.startsWith("-Xplugin") }.substringAfter("-Xplugin").split(",") + assertTrue("Expected serialization plugin to go first; actual order: $xPlugin") { xPlugin.first().contains("serialization") } + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt index f0e63f9f8fa..9377ec63977 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/CompilerArgumentsContributor.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompileArgumentsProvider import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompilerArgumentsProvider -import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray +import org.jetbrains.kotlin.gradle.utils.toPathsArray import org.jetbrains.kotlin.incremental.classpathAsList import org.jetbrains.kotlin.incremental.destinationAsFile @@ -63,7 +63,7 @@ internal open class AbstractKotlinCompileArgumentsContributor + val orderedDependencies = dependencySet.toList().partition(Dependency::isPrioritized).toList().flatten() + dependencySet.clear() + dependencySet.addAll(orderedDependencies) + } +} + +private val Dependency.isPrioritized: Boolean + get() = this is ModuleDependency && (group to name) in prioritizedPluginArtifactCoordinates + +private val prioritizedPluginArtifactCoordinates = setOf( + "org.jetbrains.kotlin" to "kotlin-serialization", + "org.jetbrains.kotlin" to "kotlin-serialization-unshaded" +) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt index 10a1a720d38..6fcf490022e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithKotlincTask.kt @@ -24,7 +24,7 @@ import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.utils.newInstance import org.jetbrains.kotlin.gradle.utils.property -import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray +import org.jetbrains.kotlin.gradle.utils.toPathsArray import java.io.File import javax.inject.Inject @@ -71,7 +71,7 @@ abstract class KaptWithKotlincTask @Inject constructor( ignoreClasspathResolutionErrors )) - args.pluginClasspaths = pluginClasspath.toSortedPathsArray() + args.pluginClasspaths = pluginClasspath.toPathsArray() val pluginOptionsWithKapt: CompilerPluginOptions = pluginOptions.withWrappedKaptOptions( withApClasspath = kaptClasspath, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index 5641c4d7514..7f82cd78e2d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -27,6 +27,7 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.jvm.tasks.ProcessResources import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.internal.reorderPluginClasspathDependencies import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget @@ -286,6 +287,7 @@ abstract class AbstractKotlinTargetConfigurator isVisible = false isCanBeConsumed = false description = "Kotlin compiler plugins for $compilation" + reorderPluginClasspathDependencies() } val compileConfiguration = configurations.findByName(compilation.deprecatedCompileConfigurationName)?.apply { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt index 9906b7a982f..e749b7abba0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradleKpmCompilerPlugin.kt @@ -7,9 +7,9 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.Project import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.internal.reorderPluginClasspathDependencies import org.jetbrains.kotlin.gradle.plugin.FilesSubpluginOption import org.jetbrains.kotlin.gradle.plugin.SubpluginOption -import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerPluginData import org.jetbrains.kotlin.gradle.utils.newProperty @@ -93,6 +93,7 @@ internal class CompilerPluginOptionsBuilder( isCanBeConsumed = false isCanBeResolved = true isVisible = false + reorderPluginClasspathDependencies() } artifacts.forEach { project.dependencies.add(configurationName, it) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index b8006c146f8..5bae9eda9a6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.tasks import org.gradle.api.GradleException import org.gradle.api.Project import org.gradle.api.Task +import org.gradle.api.artifacts.Configuration import org.gradle.api.file.* import org.gradle.api.invocation.Gradle import org.gradle.api.attributes.Attribute diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt index 4353ac6ef62..d337b5fe532 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/utils/fileUtils.kt @@ -26,8 +26,8 @@ internal fun Iterable.pathsAsStringRelativeTo(base: File): String = internal fun File.relativeToRoot(project: Project): String = relativeOrCanonical(project.rootProject.rootDir) -internal fun Iterable.toSortedPathsArray(): Array = - map { it.canonicalPath }.toTypedArray().also { Arrays.sort(it) } +internal fun Iterable.toPathsArray(): Array = + map { it.canonicalPath }.toTypedArray() internal fun newTmpFile(prefix: String, suffix: String? = null, directory: File? = null, deleteOnExit: Boolean = true): File = (if (directory == null) Files.createTempFile(prefix, suffix) else Files.createTempFile(directory.toPath(), prefix, suffix))