Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to modern AGP variants APIs #1443

Merged
merged 1 commit into from
May 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -62,19 +60,20 @@ public class PaparazziPlugin : Plugin<Project> {

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 <T> setupPaparazzi(project: Project, variants: DomainObjectSet<T>) 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")
Expand Down Expand Up @@ -102,17 +101,16 @@ public class PaparazziPlugin : Plugin<Project> {
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

Expand All @@ -124,8 +122,7 @@ public class PaparazziPlugin : Plugin<Project> {
.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

Expand Down Expand Up @@ -155,33 +152,32 @@ public class PaparazziPlugin : Plugin<Project> {
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)
kevinzheng-ap marked this conversation as resolved.
Show resolved Hide resolved
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<String>::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"))
}

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) }
jrodbx marked this conversation as resolved.
Show resolved Hide resolved
}

project.plugins.withType(KotlinMultiplatformPluginWrapper::class.java) {
Expand All @@ -190,13 +186,13 @@ public class PaparazziPlugin : Plugin<Project> {
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) {
Expand Down Expand Up @@ -225,7 +221,9 @@ public class PaparazziPlugin : Plugin<Project> {
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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
jrodbx marked this conversation as resolved.
Show resolved Hide resolved
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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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()

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
}

Expand Down