diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt index fc5bd0ef765..82dbae6bc51 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt @@ -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 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() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index 18dc98db610..13f6f46881f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -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> = project.provider { + private fun Kapt3SubpluginContext.getAPOptions(): Provider = 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> = 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> = - 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) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt index 01b9932d0fa..ed4d4923856 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptWithoutKotlincTask.kt @@ -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).forEach { + (it as CommandLineArgumentProvider).asArguments().forEach { + result[it.removePrefix("-A")] = "" + } + } + } + return result }