From a1f02eac9c04de16d0380af310e20f3d2f6b83a6 Mon Sep 17 00:00:00 2001 From: John Rodriguez Date: Fri, 24 May 2024 14:51:08 +0200 Subject: [PATCH] Migrate to modern AGP variants APIs --- .../cash/paparazzi/gradle/PaparazziPlugin.kt | 82 +++++++++---------- .../paparazzi/gradle/PaparazziPluginTest.kt | 26 +++++- .../consumer/build.gradle | 2 +- .../consumer/build.gradle | 2 +- 4 files changed, 64 insertions(+), 48 deletions(-) diff --git a/paparazzi-gradle-plugin/src/main/java/app/cash/paparazzi/gradle/PaparazziPlugin.kt b/paparazzi-gradle-plugin/src/main/java/app/cash/paparazzi/gradle/PaparazziPlugin.kt index 2c8643c19e..47c5017032 100644 --- a/paparazzi-gradle-plugin/src/main/java/app/cash/paparazzi/gradle/PaparazziPlugin.kt +++ b/paparazzi-gradle-plugin/src/main/java/app/cash/paparazzi/gradle/PaparazziPlugin.kt @@ -18,16 +18,14 @@ package app.cash.paparazzi.gradle import app.cash.paparazzi.gradle.utils.artifactViewFor import app.cash.paparazzi.gradle.utils.artifactsFor import app.cash.paparazzi.gradle.utils.relativize +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.ApplicationAndroidComponentsExtension +import com.android.build.api.variant.DynamicFeatureAndroidComponentsExtension +import com.android.build.api.variant.HasUnitTest +import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.TestedExtension -import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.internal.api.TestedVariant -import com.android.build.gradle.internal.dsl.BaseAppModuleExtension -import com.android.build.gradle.internal.dsl.DynamicFeatureExtension import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType import org.gradle.api.DefaultTask -import org.gradle.api.DomainObjectSet import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.artifacts.component.ProjectComponentIdentifier @@ -62,19 +60,20 @@ public class PaparazziPlugin : Plugin { supportedPlugins.forEach { plugin -> project.plugins.withId(plugin) { - val variants = when (val extension = project.extensions.getByType(TestedExtension::class.java)) { - is LibraryExtension -> extension.libraryVariants - is BaseAppModuleExtension -> extension.applicationVariants - is DynamicFeatureExtension -> extension.applicationVariants + val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java) + when (androidComponents) { + is LibraryAndroidComponentsExtension, + is ApplicationAndroidComponentsExtension, + is DynamicFeatureAndroidComponentsExtension -> Unit // exhaustive to avoid potential breaking changes in future AGP releases - else -> error("${extension.javaClass.name} from $plugin is not supported in Paparazzi") + else -> error("${androidComponents.javaClass.name} from $plugin is not supported in Paparazzi") } - setupPaparazzi(project, variants) + setupPaparazzi(project, androidComponents) } } } - private fun setupPaparazzi(project: Project, variants: DomainObjectSet) where T : BaseVariant, T : TestedVariant { + private fun setupPaparazzi(project: Project, extension: AndroidComponentsExtension<*, *, *>) { project.addTestDependency() val nativePlatformFileCollection = project.setupNativePlatformDependency() val snapshotOutputDir = project.layout.projectDirectory.dir("src/test/snapshots") @@ -102,17 +101,16 @@ public class PaparazziPlugin : Plugin { it.delete(files) } - variants.all { variant -> + extension.onVariants { variant -> val variantSlug = variant.name.capitalize(Locale.US) - val testVariant = variant.unitTestVariant ?: return@all + val testVariant = (variant as? HasUnitTest)?.unitTest ?: return@onVariants val projectDirectory = project.layout.projectDirectory val buildDirectory = project.layout.buildDirectory val gradleUserHomeDir = project.gradle.gradleUserHomeDir val reportOutputDir = project.extensions.getByType(ReportingExtension::class.java).baseDirectory.dir("paparazzi/${variant.name}") - val localResourceDirs = project - .files(variant.sourceSets.flatMap { it.resDirectories }) + val localResourceDirs = variant.sources.res?.all ?: project.provider { emptyList() } // https://android.googlesource.com/platform/tools/base/+/96015063acd3455a76cdf1cc71b23b0828c0907f/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeResources.kt#875 @@ -124,8 +122,7 @@ public class PaparazziPlugin : Plugin { .artifactsFor(ArtifactType.ANDROID_RES.type) { it !is ProjectComponentIdentifier } .artifactFiles - val localAssetDirs = project - .files(variant.sourceSets.flatMap { it.assetsDirectories }) + val localAssetDirs = variant.sources.assets?.all ?: project.provider { emptyList() } // https://android.googlesource.com/platform/tools/base/+/96015063acd3455a76cdf1cc71b23b0828c0907f/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/MergeResources.kt#875 @@ -155,24 +152,23 @@ public class PaparazziPlugin : Plugin { task.nonTransitiveRClassEnabled.set(nonTransitiveRClassEnabled) task.targetSdkVersion.set(android.targetSdkVersion()) task.compileSdkVersion.set(android.compileSdkVersion()) - task.projectResourceDirs.set( + + val localResourcePaths = localResourceDirs + .map { layers -> layers.flatten() } + .map { dirs -> dirs.map { projectDirectory.relativize(it.asFile) }.asReversed() } + + task.projectResourceDirs.set(localResourcePaths) + task.moduleResourceDirs.set(moduleResourceDirs.relativize(projectDirectory)) + task.aarExplodedDirs.set(aarExplodedDirs.relativize(gradleHomeDir)) + task.projectAssetDirs.set( run { - val resourcesComputer = variant.mergeResourcesProvider - val extraGeneratedResDirs = - resourcesComputer?.map { it.resourcesComputer.extraGeneratedResFolders } - ?: project.provider { project.files() } - val generatedResOutputDirs = - resourcesComputer?.map { it.resourcesComputer.generatedResOutputDir } - ?: project.provider { project.files() } - extraGeneratedResDirs - .zip(project.provider { localResourceDirs }, FileCollection::plus) - .zip(generatedResOutputDirs, FileCollection::plus) - .flatMap { it.relativize(projectDirectory) } + val localAssetPaths = localAssetDirs + .map { layers -> layers.flatten() } + .map { dirs -> dirs.map { projectDirectory.relativize(it.asFile) }.asReversed() } + val moduleAssetPaths = moduleAssetDirs.relativize(projectDirectory) + localAssetPaths.zip(moduleAssetPaths, List::plus) } ) - task.moduleResourceDirs.set(moduleResourceDirs.relativize(projectDirectory)) - task.aarExplodedDirs.set(aarExplodedDirs.relativize(gradleHomeDir)) - task.projectAssetDirs.set(localAssetDirs.plus(moduleAssetDirs).relativize(projectDirectory)) task.aarAssetDirs.set(aarAssetDirs.relativize(gradleHomeDir)) task.paparazziResources.set(buildDirectory.file("intermediates/paparazzi/${variant.name}/resources.json")) } @@ -180,8 +176,8 @@ public class PaparazziPlugin : Plugin { val testVariantSlug = testVariant.name.capitalize(Locale.US) project.plugins.withType(JavaBasePlugin::class.java) { - project.tasks.named("compile${testVariantSlug}JavaWithJavac") - .configure { it.dependsOn(writeResourcesTask) } + project.tasks.named { it == "compile${testVariantSlug}JavaWithJavac" } + .configureEach { it.dependsOn(writeResourcesTask) } } project.plugins.withType(KotlinMultiplatformPluginWrapper::class.java) { @@ -190,13 +186,13 @@ public class PaparazziPlugin : Plugin { check(multiplatformExtension.targets.any { target -> target is KotlinAndroidTarget }) { "There must be an Android target configured when using Paparazzi with the Kotlin Multiplatform Plugin" } - project.tasks.named("compile${testVariantSlug}KotlinAndroid") - .configure { it.dependsOn(writeResourcesTask) } + project.tasks.named { it == "compile${testVariantSlug}KotlinAndroid" } + .configureEach { it.dependsOn(writeResourcesTask) } } project.plugins.withType(KotlinAndroidPluginWrapper::class.java) { - project.tasks.named("compile${testVariantSlug}Kotlin") - .configure { it.dependsOn(writeResourcesTask) } + project.tasks.named { it == "compile${testVariantSlug}Kotlin" } + .configureEach { it.dependsOn(writeResourcesTask) } } val recordTaskProvider = project.tasks.register("recordPaparazzi$variantSlug", PaparazziTask::class.java) { @@ -225,7 +221,9 @@ public class PaparazziPlugin : Plugin { isVerifyRun.set(verifyTaskProvider.map { graph.hasTask(it) }) } - val testTaskProvider = project.tasks.named("test$testVariantSlug", Test::class.java) { test -> + val testTaskProvider = + project.tasks.withType(Test::class.java).named { it == "test$testVariantSlug" } + testTaskProvider.configureEach { test -> test.systemProperties["paparazzi.test.resources"] = writeResourcesTask.flatMap { it.paparazziResources.asFile }.get().path test.systemProperties["paparazzi.project.dir"] = projectDirectory.toString() diff --git a/paparazzi-gradle-plugin/src/test/java/app/cash/paparazzi/gradle/PaparazziPluginTest.kt b/paparazzi-gradle-plugin/src/test/java/app/cash/paparazzi/gradle/PaparazziPluginTest.kt index d152b74bb6..cef9e72f79 100644 --- a/paparazzi-gradle-plugin/src/test/java/app/cash/paparazzi/gradle/PaparazziPluginTest.kt +++ b/paparazzi-gradle-plugin/src/test/java/app/cash/paparazzi/gradle/PaparazziPluginTest.kt @@ -832,7 +832,12 @@ class PaparazziPluginTest { "app.cash.paparazzi.plugin.test.module1", "app.cash.paparazzi.plugin.test.module2" ) - assertThat(config.projectResourceDirs).containsExactly("build/generated/res/extra", "src/main/res", "src/debug/res", "build/generated/res/resValues/debug") + assertThat(config.projectResourceDirs).containsExactly( + "src/main/res", + "src/debug/res", + "build/generated/res/resValues/debug", + "build/generated/res/extra" + ) assertThat(config.moduleResourceDirs).containsExactly( "../module1/build/intermediates/packaged_res/debug/packageDebugResources", "../module2/build/intermediates/packaged_res/debug/packageDebugResources" @@ -863,7 +868,12 @@ class PaparazziPluginTest { "app.cash.paparazzi.plugin.test.module1", "app.cash.paparazzi.plugin.test.module2" ) - assertThat(config.projectResourceDirs).containsExactly("build/generated/res/extra", "src/main/res", "src/debug/res", "build/generated/res/resValues/debug") + assertThat(config.projectResourceDirs).containsExactly( + "src/main/res", + "src/debug/res", + "build/generated/res/resValues/debug", + "build/generated/res/extra" + ) assertThat(config.moduleResourceDirs).containsExactly( "../module1/build/intermediates/packaged_res/debug/packageDebugResources", "../module2/build/intermediates/packaged_res/debug/packageDebugResources" @@ -904,7 +914,11 @@ class PaparazziPluginTest { val resourcesFile = File(fixtureRoot, "build/intermediates/paparazzi/debug/resources.json") var config = resourcesFile.loadConfig() - assertThat(config.projectResourceDirs).containsExactly("src/main/res", "src/debug/res", "build/generated/res/resValues/debug") + assertThat(config.projectResourceDirs).containsExactly( + "src/main/res", + "src/debug/res", + "build/generated/res/resValues/debug" + ) buildDir.deleteRecursively() @@ -926,7 +940,11 @@ class PaparazziPluginTest { } config = resourcesFile.loadConfig() - assertThat(config.projectResourceDirs).containsExactly("src/main/res", "src/debug/res", "build/generated/res/resValues/debug") + assertThat(config.projectResourceDirs).containsExactly( + "src/main/res", + "src/debug/res", + "build/generated/res/resValues/debug" + ) } @Test diff --git a/paparazzi-gradle-plugin/src/test/projects/verify-resources-java/consumer/build.gradle b/paparazzi-gradle-plugin/src/test/projects/verify-resources-java/consumer/build.gradle index 7610feaa29..e59a36935a 100644 --- a/paparazzi-gradle-plugin/src/test/projects/verify-resources-java/consumer/build.gradle +++ b/paparazzi-gradle-plugin/src/test/projects/verify-resources-java/consumer/build.gradle @@ -14,7 +14,7 @@ android { targetCompatibility = libs.versions.javaTarget.get() } libraryVariants.configureEach { - it.registerGeneratedResFolders(project.files("${project.buildDir.path}/generated/res/extra")) + it.registerGeneratedResFolders(project.layout.buildDirectory.files("generated/res/extra")) } } diff --git a/paparazzi-gradle-plugin/src/test/projects/verify-resources-kotlin/consumer/build.gradle b/paparazzi-gradle-plugin/src/test/projects/verify-resources-kotlin/consumer/build.gradle index cc6679be92..f077e88e8a 100644 --- a/paparazzi-gradle-plugin/src/test/projects/verify-resources-kotlin/consumer/build.gradle +++ b/paparazzi-gradle-plugin/src/test/projects/verify-resources-kotlin/consumer/build.gradle @@ -15,7 +15,7 @@ android { targetCompatibility = libs.versions.javaTarget.get() } libraryVariants.configureEach { - it.registerGeneratedResFolders(project.files("${project.buildDir.path}/generated/res/extra")) + it.registerGeneratedResFolders(project.layout.buildDirectory.files("generated/res/extra")) } }