KAPT: Avoid evaluating apOptions from AGP too early
This is causing issues such as https://issuetracker.google.com/183423660. Annotation processor options that are provided by the Android Gradle plugin may contain references to files and file collections that are safe to evaluate only at execution time. This change avoids eagerly creating compiler plugin options for these options, as they are already a task input. Test: AbstractKotlinAndroidGradleTests.testAgpNestedArgsNotEvaluatedDuringConfiguration ^KT-39715 In Progress
This commit is contained in:
committed by
TeamCityServer
parent
1123f97a15
commit
19708cfa87
+36
@@ -521,6 +521,42 @@ open class KotlinAndroid34GradleIT : KotlinAndroid3GradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAgpNestedArgsNotEvaluatedDuringConfiguration() = with(Project("AndroidProject")) {
|
||||
setupWorkingDir()
|
||||
|
||||
gradleBuildScript(subproject = "Android").appendText(
|
||||
"""
|
||||
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
class MyNested implements org.gradle.process.CommandLineArgumentProvider {
|
||||
@Override
|
||||
Iterable<String> asArguments() {
|
||||
throw new RuntimeException("This should not be invoked during configuration.")
|
||||
}
|
||||
}
|
||||
|
||||
def nested = new MyNested()
|
||||
|
||||
android.applicationVariants.all {
|
||||
it.javaCompileOptions.annotationProcessorOptions.compilerArgumentProviders.add(nested)
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
build(":Android:kaptFlavor1DebugKotlin", "--dry-run") {
|
||||
assertSuccessful()
|
||||
}
|
||||
|
||||
build(
|
||||
":Android:kaptFlavor1DebugKotlin", "--dry-run",
|
||||
options = defaultBuildOptions().copy(kaptOptions = KaptOptions(verbose = false, useWorkers = false))
|
||||
) {
|
||||
assertSuccessful()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOmittedStdlibVersion() = Project("AndroidProject").run {
|
||||
setupWorkingDir()
|
||||
|
||||
+40
-32
@@ -324,13 +324,10 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
||||
pluginOptions += SubpluginOption("processors", annotationProcessors)
|
||||
}
|
||||
|
||||
val apOptions = getAPOptions().get()
|
||||
|
||||
pluginOptions += CompositeSubpluginOption(
|
||||
"apoptions",
|
||||
lazy { encodeList(apOptions.associate { it.key to it.value }) },
|
||||
apOptions
|
||||
)
|
||||
if (aptMode == "apt") {
|
||||
// apOptions are needed only for "apt" mode
|
||||
pluginOptions += getAPOptions().get()
|
||||
}
|
||||
|
||||
pluginOptions += SubpluginOption("javacArguments", encodeList(javacOptions.get()))
|
||||
|
||||
@@ -342,35 +339,46 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
||||
}
|
||||
}
|
||||
|
||||
private fun Kapt3SubpluginContext.getAPOptions(): Provider<List<SubpluginOption>> = project.provider {
|
||||
private fun Kapt3SubpluginContext.getAPOptions(): Provider<CompositeSubpluginOption> = project.provider {
|
||||
val androidVariantData = KaptWithAndroid.androidVariantData(this)
|
||||
|
||||
val androidPlugin = androidVariantData?.let {
|
||||
val androidOptions = androidVariantData?.annotationProcessorOptions ?: emptyMap()
|
||||
val annotationProcessorProviders = androidVariantData?.annotationProcessorOptionProviders
|
||||
|
||||
val subluginOptionsFromProvidedApOptions = lazy {
|
||||
val apOptionsFromProviders =
|
||||
annotationProcessorProviders?.flatMap {
|
||||
(it as CommandLineArgumentProvider).asArguments()
|
||||
}.orEmpty()
|
||||
|
||||
apOptionsFromProviders.map {
|
||||
// Use the internal subplugin option type to exclude them from Gradle input/output checks, as their providers are already
|
||||
// properly registered as a nested input:
|
||||
|
||||
// Pass options as they are in the key-only form (key = 'a=b'), kapt will deal with them:
|
||||
InternalSubpluginOption(key = it.removePrefix("-A"), value = "")
|
||||
}
|
||||
}
|
||||
|
||||
val nonAndroidOptions = androidOptions.toList().map { SubpluginOption(it.first, it.second) } + getKaptApOptions().get()
|
||||
|
||||
CompositeSubpluginOption(
|
||||
"apoptions",
|
||||
lazy { encodeList((nonAndroidOptions + subluginOptionsFromProvidedApOptions.value).associate { it.key to it.value }) },
|
||||
nonAndroidOptions
|
||||
)
|
||||
}
|
||||
|
||||
private fun Kapt3SubpluginContext.getKaptApOptions(): Provider<List<SubpluginOption>> = project.provider {
|
||||
val androidVariantData = KaptWithAndroid.androidVariantData(this)
|
||||
|
||||
val androidExtension = androidVariantData?.let {
|
||||
project.extensions.findByName("android") as? BaseExtension
|
||||
}
|
||||
|
||||
val androidOptions = androidVariantData?.annotationProcessorOptions ?: emptyMap()
|
||||
|
||||
val apOptionsFromProviders =
|
||||
androidVariantData?.annotationProcessorOptionProviders
|
||||
?.flatMap { (it as CommandLineArgumentProvider).asArguments() }
|
||||
.orEmpty()
|
||||
|
||||
val subluginOptionsFromProvidedApOptions = apOptionsFromProviders.map {
|
||||
// Use the internal subplugin option type to exclude them from Gradle input/output checks, as their providers are already
|
||||
// properly registered as a nested input:
|
||||
|
||||
// Pass options as they are in the key-only form (key = 'a=b'), kapt will deal with them:
|
||||
InternalSubpluginOption(key = it.removePrefix("-A"), value = "")
|
||||
}
|
||||
|
||||
val apOptionsPairsList: List<Pair<String, String>> =
|
||||
kaptExtension.getAdditionalArguments(project, androidVariantData, androidPlugin).toList() +
|
||||
androidOptions.toList()
|
||||
|
||||
apOptionsPairsList.map { SubpluginOption(it.first, it.second) } +
|
||||
FilesSubpluginOption(KAPT_KOTLIN_GENERATED, listOf(kotlinSourcesOutputDir)) +
|
||||
subluginOptionsFromProvidedApOptions
|
||||
kaptExtension.getAdditionalArguments(project, androidVariantData, androidExtension).toList()
|
||||
.map { SubpluginOption(it.first, it.second) } +
|
||||
FilesSubpluginOption(KAPT_KOTLIN_GENERATED, listOf(kotlinSourcesOutputDir))
|
||||
}
|
||||
|
||||
private fun Kapt3SubpluginContext.registerSubpluginOptions(
|
||||
@@ -563,7 +571,7 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
||||
it.javacOptions = dslJavacOptions.get()
|
||||
}
|
||||
|
||||
val subpluginOptions = getAPOptions()
|
||||
val subpluginOptions = getKaptApOptions()
|
||||
registerSubpluginOptions(kaptTaskProvider, subpluginOptions)
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -11,6 +11,7 @@ import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
import org.gradle.process.CommandLineArgumentProvider
|
||||
import org.gradle.workers.IsolationMode
|
||||
import org.gradle.workers.WorkAction
|
||||
import org.gradle.workers.WorkParameters
|
||||
@@ -74,6 +75,14 @@ abstract class KaptWithoutKotlincTask @Inject constructor(
|
||||
for (option in options) {
|
||||
result[option.key] = option.value
|
||||
}
|
||||
annotationProcessorOptionProviders.forEach {
|
||||
(it as List<Any>).forEach {
|
||||
(it as CommandLineArgumentProvider).asArguments().forEach {
|
||||
result[it.removePrefix("-A")] = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user