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
This commit is contained in:
+25
-1
@@ -275,6 +275,30 @@ class SubpluginsIT : BaseGradleIT() {
|
|||||||
Project("lombokProject").build("build") {
|
Project("lombokProject").build("build") {
|
||||||
assertSuccessful()
|
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") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileArgumentsProvider
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileArgumentsProvider
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompilerArgumentsProvider
|
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.classpathAsList
|
||||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ internal open class AbstractKotlinCompileArgumentsContributor<T : CommonCompiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun setupPlugins(compilerArgs: T) {
|
internal fun setupPlugins(compilerArgs: T) {
|
||||||
compilerArgs.pluginClasspaths = pluginClasspath.toSortedPathsArray()
|
compilerArgs.pluginClasspaths = pluginClasspath.toPathsArray()
|
||||||
compilerArgs.pluginOptions = pluginOptions.arguments.toTypedArray()
|
compilerArgs.pluginOptions = pluginOptions.arguments.toTypedArray()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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.kotlin.gradle.internal
|
||||||
|
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.artifacts.Dependency
|
||||||
|
import org.gradle.api.artifacts.ModuleDependency
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reorder the compiler plugin dependencies in this [Configuration] so that dependencies on the
|
||||||
|
* modules under [prioritizedPluginArtifactCoordinates] appear first.
|
||||||
|
*
|
||||||
|
* In particular, the serialization plugin needs to appear first on the -Xplugin classpath in order to avoid conflicts with other compiler
|
||||||
|
* plugins producing unexpected IR.
|
||||||
|
*
|
||||||
|
* KT-47921
|
||||||
|
*/
|
||||||
|
internal fun Configuration.reorderPluginClasspathDependencies() {
|
||||||
|
withDependencies { dependencySet ->
|
||||||
|
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"
|
||||||
|
)
|
||||||
+2
-2
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.gradle.report.ReportingSettings
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.*
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
import org.jetbrains.kotlin.gradle.utils.newInstance
|
import org.jetbrains.kotlin.gradle.utils.newInstance
|
||||||
import org.jetbrains.kotlin.gradle.utils.property
|
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 java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ abstract class KaptWithKotlincTask @Inject constructor(
|
|||||||
ignoreClasspathResolutionErrors
|
ignoreClasspathResolutionErrors
|
||||||
))
|
))
|
||||||
|
|
||||||
args.pluginClasspaths = pluginClasspath.toSortedPathsArray()
|
args.pluginClasspaths = pluginClasspath.toPathsArray()
|
||||||
|
|
||||||
val pluginOptionsWithKapt: CompilerPluginOptions = pluginOptions.withWrappedKaptOptions(
|
val pluginOptionsWithKapt: CompilerPluginOptions = pluginOptions.withWrappedKaptOptions(
|
||||||
withApClasspath = kaptClasspath,
|
withApClasspath = kaptClasspath,
|
||||||
|
|||||||
+2
@@ -27,6 +27,7 @@ import org.gradle.language.base.plugins.LifecycleBasePlugin
|
|||||||
import org.gradle.language.jvm.tasks.ProcessResources
|
import org.gradle.language.jvm.tasks.ProcessResources
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
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.plugin.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
|
||||||
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
|
||||||
@@ -286,6 +287,7 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
|
|||||||
isVisible = false
|
isVisible = false
|
||||||
isCanBeConsumed = false
|
isCanBeConsumed = false
|
||||||
description = "Kotlin compiler plugins for $compilation"
|
description = "Kotlin compiler plugins for $compilation"
|
||||||
|
reorderPluginClasspathDependencies()
|
||||||
}
|
}
|
||||||
|
|
||||||
val compileConfiguration = configurations.findByName(compilation.deprecatedCompileConfigurationName)?.apply {
|
val compileConfiguration = configurations.findByName(compilation.deprecatedCompileConfigurationName)?.apply {
|
||||||
|
|||||||
+2
-1
@@ -7,9 +7,9 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.provider.Provider
|
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.FilesSubpluginOption
|
||||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
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.CompilerPluginOptions
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerPluginData
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerPluginData
|
||||||
import org.jetbrains.kotlin.gradle.utils.newProperty
|
import org.jetbrains.kotlin.gradle.utils.newProperty
|
||||||
@@ -93,6 +93,7 @@ internal class CompilerPluginOptionsBuilder(
|
|||||||
isCanBeConsumed = false
|
isCanBeConsumed = false
|
||||||
isCanBeResolved = true
|
isCanBeResolved = true
|
||||||
isVisible = false
|
isVisible = false
|
||||||
|
reorderPluginClasspathDependencies()
|
||||||
}
|
}
|
||||||
artifacts.forEach { project.dependencies.add(configurationName, it) }
|
artifacts.forEach { project.dependencies.add(configurationName, it) }
|
||||||
|
|
||||||
|
|||||||
+1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.tasks
|
|||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
import org.gradle.api.file.*
|
import org.gradle.api.file.*
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
import org.gradle.api.attributes.Attribute
|
import org.gradle.api.attributes.Attribute
|
||||||
|
|||||||
+2
-2
@@ -26,8 +26,8 @@ internal fun Iterable<File>.pathsAsStringRelativeTo(base: File): String =
|
|||||||
internal fun File.relativeToRoot(project: Project): String =
|
internal fun File.relativeToRoot(project: Project): String =
|
||||||
relativeOrCanonical(project.rootProject.rootDir)
|
relativeOrCanonical(project.rootProject.rootDir)
|
||||||
|
|
||||||
internal fun Iterable<File>.toSortedPathsArray(): Array<String> =
|
internal fun Iterable<File>.toPathsArray(): Array<String> =
|
||||||
map { it.canonicalPath }.toTypedArray().also { Arrays.sort(it) }
|
map { it.canonicalPath }.toTypedArray()
|
||||||
|
|
||||||
internal fun newTmpFile(prefix: String, suffix: String? = null, directory: File? = null, deleteOnExit: Boolean = true): File =
|
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))
|
(if (directory == null) Files.createTempFile(prefix, suffix) else Files.createTempFile(directory.toPath(), prefix, suffix))
|
||||||
|
|||||||
Reference in New Issue
Block a user