From d881efdeb19df24fbc26e35c0e3fb470f57e57fd Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Sun, 31 Dec 2017 02:23:41 +0300 Subject: [PATCH] Improve disambiguation of subplugin option inputs The original approach required evaluating the existing input properties of the task. This led to evaluation of the property values, and could execute incorrectly if the task was not properly initialized at that moment. The new approach fixes that by first grouping options from each subplugin by key and then adding disambiguating index suffixes. --- .../internal/Kapt3KotlinGradleSubplugin.kt | 10 ++--- .../kotlin/gradle/plugin/KotlinPlugin.kt | 43 ++++++++++++------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt index 0d1fc0ecb83..c0e5223ac85 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt @@ -246,17 +246,17 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { private fun Kapt3SubpluginContext.buildAndAddOptionsTo(task: Task, container: CompilerPluginOptions, aptMode: String) { val compilerPluginId = getCompilerPluginId() - for (option in wrapPluginOptions(buildOptions(aptMode), "configuration")) { + val kaptSubpluginOptions = wrapPluginOptions(buildOptions(aptMode), "configuration") + task.registerSubpluginOptionsAsInputs(compilerPluginId, kaptSubpluginOptions) + + for (option in kaptSubpluginOptions) { container.addPluginArgument(compilerPluginId, option) - task.registerSubpluginOptionAsInput(compilerPluginId, option) } // Also register all the subplugin options from the Kotlin task: project.afterEvaluate { kotlinCompile.pluginOptions.subpluginOptionsByPluginId.forEach { (pluginId, options) -> - options.forEach { option -> - task.registerSubpluginOptionAsInput("kotlinCompile.$pluginId", option) - } + task.registerSubpluginOptionsAsInputs("kotlinCompile.$pluginId", options) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 88cb9be513d..d4c6ec19bed 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -826,10 +826,12 @@ internal class SubpluginEnvironment( val subpluginClasspath = subpluginClasspaths[subplugin] ?: continue subpluginClasspath.forEach { pluginOptions.addClasspathEntry(it) } - for (option in subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, javaSourceSet)) { - val pluginId = subplugin.getCompilerPluginId() - pluginOptions.addPluginArgument(pluginId, option) - kotlinTask.registerSubpluginOptionAsInput(pluginId, option) + val subpluginOptions = subplugin.apply(project, kotlinTask, javaTask, variantData, androidProjectHandler, javaSourceSet) + val subpluginId = subplugin.getCompilerPluginId() + kotlinTask.registerSubpluginOptionsAsInputs(subpluginId, subpluginOptions) + + for (option in subpluginOptions) { + pluginOptions.addPluginArgument(subpluginId, option) } } @@ -837,18 +839,27 @@ internal class SubpluginEnvironment( } } -internal fun Task.registerSubpluginOptionAsInput(subpluginId: String, option: SubpluginOption) { - when (option) { - is CompositeSubpluginOption -> { - val subpluginIdWithWrapperKey = "$subpluginId.${option.key}" - option.originalOptions.forEach { registerSubpluginOptionAsInput(subpluginIdWithWrapperKey, it) } - } - is FilesSubpluginOption -> Unit - else -> { - // Since there might be multiple subplugin options with the same key, - // use the properties count to resolve duplication: - val propertyInputsCount = inputsCompatible.properties.size - inputsCompatible.propertyCompatible("$subpluginId." + option.key + ".$propertyInputsCount", option.value) +internal fun Task.registerSubpluginOptionsAsInputs(subpluginId: String, subpluginOptions: List) { + // There might be several options with the same key. We group them together + // and add an index to the Gradle input property name to resolve possible duplication: + val pluginOptionsGrouped = subpluginOptions.groupBy { it.key } + for ((optionKey, optionsGroup) in pluginOptionsGrouped) { + optionsGroup.forEachIndexed { index, option -> + val indexSuffix = if (optionsGroup.size > 1) ".$index" else "" + when (option) { + is CompositeSubpluginOption -> { + val subpluginIdWithWrapperKey = "$subpluginId.${optionKey}$indexSuffix" + registerSubpluginOptionsAsInputs(subpluginIdWithWrapperKey, option.originalOptions) + } + + is FilesSubpluginOption -> when (option.kind) { + FilesOptionKind.INTERNAL -> Unit + }.run { /* exhaustive when */ } + + else -> { + inputsCompatible.propertyCompatible("$subpluginId." + option.key + indexSuffix, option.value) + } + } } } }