From bdf83f109c9782e5d461f92d760c92f88e725c5f Mon Sep 17 00:00:00 2001 From: Scott Pollom Date: Wed, 30 Oct 2024 22:07:15 -0700 Subject: [PATCH] Fix error when KSP plugin applied before AGP Previously, when the KSP plugin was applied before AGP and AGP's built-in Kotlin support for test fixtures or screenshot tests was enabled, there would be an error when building. The underlying cause for this error is https://github.com/gradle/gradle/issues/31092, which caused the KSP plugin to try to access the android extension before AGP's apply method had completed. This change fixes the problem by using the "com.android.base" plugin as the indicator that a module is an Android module. The "com.android.base" plugin is applied after the android extension has been added, so it works around the Gradle bug. Bug: https://github.com/google/ksp/issues/2174 Test: GradleCompilationTest (cherry picked from commit 5b1cd4a998619a174058842fdb93e59dfc98dc46) --- .../ksp/gradle/AndroidPluginIntegration.kt | 10 +++----- .../ksp/gradle/GradleCompilationTest.kt | 12 ++++++++++ .../gradle/testing/KspIntegrationTestRule.kt | 23 ++++++++++++++----- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt index 8c7a006c53..a1e3655eee 100644 --- a/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt +++ b/gradle-plugin/src/main/kotlin/com/google/devtools/ksp/gradle/AndroidPluginIntegration.kt @@ -39,14 +39,10 @@ import java.util.concurrent.Callable @Suppress("UnstableApiUsage") // some android APIs are unsable. object AndroidPluginIntegration { - private val agpPluginIds = listOf("com.android.application", "com.android.library", "com.android.dynamic-feature") - fun forEachAndroidSourceSet(project: Project, onSourceSet: (String) -> Unit) { - agpPluginIds.forEach { agpPluginId -> - project.pluginManager.withPlugin(agpPluginId) { - // for android apps, we need a configuration per source set - decorateAndroidExtension(project, onSourceSet) - } + project.pluginManager.withPlugin("com.android.base") { + // for android modules, we need a configuration per source set + decorateAndroidExtension(project, onSourceSet) } } diff --git a/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/GradleCompilationTest.kt b/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/GradleCompilationTest.kt index 27ccd4cd47..d0fe401401 100644 --- a/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/GradleCompilationTest.kt +++ b/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/GradleCompilationTest.kt @@ -414,4 +414,16 @@ class GradleCompilationTest { ) testRule.runner().withArguments(":app:assembleDebug").build() } + + /** + * Regression test for https://github.com/google/ksp/issues/2174 + */ + @Test + fun androidGradlePluginBuiltInKotlinWithKspAppliedFirst() { + testRule.setupAppAsAndroidApp(applyKspPluginFirst = true) + // Enable AGP's built-in Kotlin support for test fixtures + testRule.runner() + .withArguments("tasks", "-Pandroid.experimental.enableTestFixturesKotlinSupport=true") + .build() + } } diff --git a/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/testing/KspIntegrationTestRule.kt b/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/testing/KspIntegrationTestRule.kt index f4fff4c835..baf69f5d83 100644 --- a/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/testing/KspIntegrationTestRule.kt +++ b/gradle-plugin/src/test/kotlin/com/google/devtools/ksp/gradle/testing/KspIntegrationTestRule.kt @@ -93,14 +93,25 @@ class KspIntegrationTestRule( /** * Sets up the app module as an android app, adding necessary plugin dependencies, a manifest * file and necessary gradle configuration. If [enableAgpBuiltInKotlinSupport] is true, enable AGP's built-in Kotlin - * support instead of applying the Kotlin Android Gradle plugin. + * support instead of applying the Kotlin Android Gradle plugin. If [applyKspPluginFirst] is true, apply the KSP + * plugin first. */ - fun setupAppAsAndroidApp(enableAgpBuiltInKotlinSupport: Boolean = false) { + fun setupAppAsAndroidApp( + enableAgpBuiltInKotlinSupport: Boolean = false, + applyKspPluginFirst: Boolean = false + ) { testProject.appModule.plugins.addAll( - listOf( - PluginDeclaration.id("com.android.application", testConfig.androidBaseVersion), - PluginDeclaration.id("com.google.devtools.ksp", testConfig.kspVersion) - ) + if (applyKspPluginFirst) { + listOf( + PluginDeclaration.id("com.google.devtools.ksp", testConfig.kspVersion), + PluginDeclaration.id("com.android.application", testConfig.androidBaseVersion) + ) + } else { + listOf( + PluginDeclaration.id("com.android.application", testConfig.androidBaseVersion), + PluginDeclaration.id("com.google.devtools.ksp", testConfig.kspVersion) + ) + } ) if (enableAgpBuiltInKotlinSupport) { testProject.appModule