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.
This commit is contained in:
Sergey Igushkin
2017-12-31 02:23:41 +03:00
parent 1be9e04797
commit d881efdeb1
2 changed files with 32 additions and 21 deletions
@@ -246,17 +246,17 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
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)
}
}
}
@@ -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<SubpluginOption>) {
// 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)
}
}
}
}
}