diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bb8e3eb4e..42a330c04 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,8 +10,11 @@ moshix = "0.19.0" okio = "2.10.0" retrofit = "2.9.0" -agp = "7.4.2" -agp-common = "30.4.2" +agp = "8.0.2" +#agp = "8.1.4 +#agp = "8.2.1" +#agp = "8.3.0-beta01" # Provides `Sources.manifests` +agp-common = "31.2.0" [libraries] agp = { module = "com.android.tools.build:gradle", version.ref = "agp" } diff --git a/src/functionalTest/groovy/com/autonomousapps/AbstractProject.groovy b/src/functionalTest/groovy/com/autonomousapps/AbstractProject.groovy index 16695ccd6..360bb291f 100644 --- a/src/functionalTest/groovy/com/autonomousapps/AbstractProject.groovy +++ b/src/functionalTest/groovy/com/autonomousapps/AbstractProject.groovy @@ -7,17 +7,26 @@ import com.autonomousapps.kit.GradleProject import com.autonomousapps.kit.gradle.BuildscriptBlock import com.autonomousapps.kit.gradle.GradleProperties import com.autonomousapps.kit.gradle.dependencies.Plugins +import com.autonomousapps.utils.DebugAware @SuppressWarnings('GrMethodMayBeStatic') abstract class AbstractProject extends AbstractGradleProject { - protected static final PRINT_ADVICE = "dependency.analysis.print.build.health=true" + protected static final String PRINT_ADVICE = "dependency.analysis.print.build.health=true" @Override - protected GradleProject.Builder newGradleProjectBuilder(GradleProject.DslKind dslKind = GradleProject.DslKind.GROOVY) { + protected GradleProject.Builder newGradleProjectBuilder( + GradleProject.DslKind dslKind = GradleProject.DslKind.GROOVY + ) { + def additionalProperties = GradleProperties.of(PRINT_ADVICE) + // There is a Gradle bug that makes tests break when the test uses CC and we're also debugging + if (!DebugAware.debug) { + additionalProperties += GradleProperties.enableConfigurationCache() + } + return super.newGradleProjectBuilder(dslKind) .withRootProject { r -> - r.gradleProperties += GradleProperties.enableConfigurationCache() + PRINT_ADVICE + r.gradleProperties += additionalProperties r.withBuildScript { bs -> bs.plugins(Plugins.dependencyAnalysis, Plugins.kotlinNoApply) } diff --git a/src/functionalTest/groovy/com/autonomousapps/android/AbstractAndroidSpec.groovy b/src/functionalTest/groovy/com/autonomousapps/android/AbstractAndroidSpec.groovy index 56f56aef4..2dfac700f 100644 --- a/src/functionalTest/groovy/com/autonomousapps/android/AbstractAndroidSpec.groovy +++ b/src/functionalTest/groovy/com/autonomousapps/android/AbstractAndroidSpec.groovy @@ -7,30 +7,36 @@ import com.autonomousapps.fixtures.ProjectDirProvider import com.autonomousapps.internal.android.AgpVersion import org.gradle.util.GradleVersion +/** + * @see AGP artifacts + */ abstract class AbstractAndroidSpec extends AbstractFunctionalSpec { protected ProjectDirProvider androidProject = null - protected static final AGP_7_3 = AgpVersion.version('7.3.1') - protected static final AGP_7_4 = AgpVersion.version('7.4.2') protected static final AGP_8_0 = AgpVersion.version('8.0.2') - protected static final AGP_8_1 = AgpVersion.version('8.1.0') - protected static final AGP_8_2 = AgpVersion.version('8.2.0-alpha16') + protected static final AGP_8_1 = AgpVersion.version('8.1.4') + protected static final AGP_8_2 = AgpVersion.version('8.2.0') + protected static final AGP_8_3 = AgpVersion.version('8.3.0-beta01') + protected static final AGP_8_4 = AgpVersion.version('8.4.0-alpha01') - protected static final AGP_LATEST = AGP_8_2 + protected static final AGP_LATEST = AGP_8_4 /** - * {@code AGP_7_4} represents the minimum stable _tested_ version. {@code AGP_8_1} represents the maximum stable + * TODO(tsr): this doc is perpetually out of date. + * + * {@code AGP_8_0} represents the minimum stable _tested_ version. {@code AGP_8_1} represents the maximum stable * _tested_ version. We also test against the latest alpha, {@code AGP_8_2} at time of writing. DAGP may work with * other versions of AGP, but they aren't tested, primarily for CI performance reasons. * * @see AGP releases */ protected static final SUPPORTED_AGP_VERSIONS = [ - AGP_7_4, -// AGP_8_0, + AGP_8_0, AGP_8_1, AGP_8_2, + AGP_8_3, + AGP_8_4, ] protected static List agpVersions(AgpVersion minAgpVersion = AgpVersion.AGP_MIN) { diff --git a/src/functionalTest/groovy/com/autonomousapps/android/DuplicateDependencyVersionsSpec.groovy b/src/functionalTest/groovy/com/autonomousapps/android/DuplicateDependencyVersionsSpec.groovy index 0858f4845..e33d269bf 100644 --- a/src/functionalTest/groovy/com/autonomousapps/android/DuplicateDependencyVersionsSpec.groovy +++ b/src/functionalTest/groovy/com/autonomousapps/android/DuplicateDependencyVersionsSpec.groovy @@ -46,6 +46,6 @@ final class DuplicateDependencyVersionsSpec extends AbstractAndroidSpec { .contains(project.expectedOutput) where: - [gradleVersion, agpVersion] << multivariableDataPipe([GRADLE_7_5], [AGP_7_3.version]) + [gradleVersion, agpVersion] << multivariableDataPipe([GRADLE_8_0], [AGP_8_0.version]) } } diff --git a/src/functionalTest/groovy/com/autonomousapps/android/IgnoredVariantSpec.groovy b/src/functionalTest/groovy/com/autonomousapps/android/IgnoredVariantSpec.groovy index b10ae075b..c746b1d24 100644 --- a/src/functionalTest/groovy/com/autonomousapps/android/IgnoredVariantSpec.groovy +++ b/src/functionalTest/groovy/com/autonomousapps/android/IgnoredVariantSpec.groovy @@ -13,7 +13,7 @@ import static com.google.common.truth.Truth.assertAbout @SuppressWarnings("GroovyAssignabilityCheck") final class IgnoredVariantSpec extends AbstractAndroidSpec { - def "plugin ignore android variants (#gradleVersion AGP #agpVersion ignored debug)"() { + def "can ignore debug variant (#gradleVersion AGP #agpVersion)"() { given: def project = new DebugVariantIgnoredProject(agpVersion) gradleProject = project.gradleProject @@ -30,7 +30,7 @@ final class IgnoredVariantSpec extends AbstractAndroidSpec { [gradleVersion, agpVersion] << gradleAgpMatrix() } - def "plugin ignore android variants (#gradleVersion AGP #agpVersion ignored release)"() { + def "can ignore release variant (#gradleVersion AGP #agpVersion)"() { given: def project = new ReleaseVariantIgnoredProject(agpVersion) gradleProject = project.gradleProject @@ -47,7 +47,7 @@ final class IgnoredVariantSpec extends AbstractAndroidSpec { [gradleVersion, agpVersion] << gradleAgpMatrix() } - def "plugin ignore android variants (#gradleVersion AGP #agpVersion ignored all variants)"() { + def "can ignore all (debug and release) variants (#gradleVersion AGP #agpVersion)"() { given: def project = new AllVariantsIgnoredProject(agpVersion) gradleProject = project.gradleProject diff --git a/src/functionalTest/groovy/com/autonomousapps/android/projects/AbstractVariantProject.groovy b/src/functionalTest/groovy/com/autonomousapps/android/projects/AbstractVariantProject.groovy index edcc9de06..6876a513c 100644 --- a/src/functionalTest/groovy/com/autonomousapps/android/projects/AbstractVariantProject.groovy +++ b/src/functionalTest/groovy/com/autonomousapps/android/projects/AbstractVariantProject.groovy @@ -15,6 +15,7 @@ import com.autonomousapps.kit.gradle.GradleProperties import com.autonomousapps.kit.gradle.Plugin import com.autonomousapps.kit.gradle.dependencies.Plugins import com.autonomousapps.model.ProjectAdvice +import com.autonomousapps.utils.DebugAware import static com.autonomousapps.AdviceHelper.actualProjectAdvice import static com.autonomousapps.kit.gradle.dependencies.Dependencies.* @@ -37,9 +38,15 @@ abstract class AbstractVariantProject extends AbstractAndroidProject { } private GradleProject build() { + def properties = projectGradleProperties + if (!DebugAware.debug) { + // There is a Gradle bug that makes tests break when the test uses CC and we're also debugging + properties += GradleProperties.enableConfigurationCache() + } + return newAndroidGradleProjectBuilder(agpVersion) .withRootProject { root -> - root.gradleProperties = projectGradleProperties + GradleProperties.enableConfigurationCache() + root.gradleProperties = properties } .withAndroidSubproject('app') { a -> a.sources = sources diff --git a/src/functionalTest/groovy/com/autonomousapps/android/projects/DataBindingUsagesExclusionsProject.groovy b/src/functionalTest/groovy/com/autonomousapps/android/projects/DataBindingUsagesExclusionsProject.groovy index 5080d28e0..8f745a99c 100644 --- a/src/functionalTest/groovy/com/autonomousapps/android/projects/DataBindingUsagesExclusionsProject.groovy +++ b/src/functionalTest/groovy/com/autonomousapps/android/projects/DataBindingUsagesExclusionsProject.groovy @@ -14,7 +14,6 @@ import com.autonomousapps.model.ProjectAdvice import static com.autonomousapps.AdviceHelper.* import static com.autonomousapps.kit.gradle.Dependency.project import static com.autonomousapps.kit.gradle.dependencies.Dependencies.appcompat -import static com.autonomousapps.kit.gradle.dependencies.Dependencies.kotlinStdLib final class DataBindingUsagesExclusionsProject extends AbstractAndroidProject { @@ -59,7 +58,6 @@ final class DataBindingUsagesExclusionsProject extends AbstractAndroidProject { lib.withBuildScript { bs -> bs.plugins = [Plugins.androidLib, Plugins.kotlinAndroid, Plugins.kapt] bs.android = defaultAndroidLibBlock(true, 'com.example.lib') - bs.dependencies = libDependencies bs.withGroovy("android.buildFeatures.dataBinding true") } lib.sources = libSources @@ -93,9 +91,8 @@ final class DataBindingUsagesExclusionsProject extends AbstractAndroidProject { ] private List appDependencies = [ - kotlinStdLib("implementation"), - appcompat("implementation"), - project("implementation", ":lib"), + appcompat('implementation'), + project('implementation', ':lib'), ] private libSources = [ @@ -114,10 +111,6 @@ final class DataBindingUsagesExclusionsProject extends AbstractAndroidProject { ) ] - private List libDependencies = [ - kotlinStdLib('api') - ] - private final Set expectedBuildHealthWithExclusions = [ projectAdviceForDependencies(':app', [ Advice.ofRemove(projectCoordinates(':lib'), 'implementation') diff --git a/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidProjectAnalyzer.kt b/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidProjectAnalyzer.kt index e7f75d353..8cc56ce2a 100644 --- a/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidProjectAnalyzer.kt +++ b/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidProjectAnalyzer.kt @@ -4,7 +4,6 @@ package com.autonomousapps.internal.analyzer -import com.android.build.gradle.api.BaseVariant import com.autonomousapps.internal.ArtifactAttributes import com.autonomousapps.internal.OutputPaths import com.autonomousapps.internal.android.AndroidGradlePluginFactory @@ -16,8 +15,6 @@ import com.autonomousapps.services.InMemoryCache import com.autonomousapps.tasks.* import org.gradle.api.Project import org.gradle.api.Task -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileTree import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider @@ -25,41 +22,37 @@ import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.register import java.io.File -/** - * Base class for analyzing an Android project (com.android.application or com.android.library only). - */ +/** Base class for analyzing an Android project (`com.android.application` or `com.android.library` only). */ internal abstract class AndroidAnalyzer( project: Project, - protected val variant: BaseVariant, - protected val variantSourceSet: VariantSourceSet, + protected val variant: AndroidVariant, + protected val androidSources: AndroidSources, agpVersion: String, ) : AbstractDependencyAnalyzer(project) { protected val agp = AndroidGradlePluginFactory(project, agpVersion).newAdapter() - private val dataBindingEnabled = agp.isDataBindingEnabled() - private val viewBindingEnabled = agp.isViewBindingEnabled() final override val flavorName: String = variant.flavorName - final override val variantName: String = variant.name - final override val buildType: String = variant.buildType.name - final override val kind: SourceSetKind = variantSourceSet.variant.kind + final override val variantName: String = variant.variantName + final override val buildType: String = variant.buildType + final override val kind: SourceSetKind = androidSources.variant.kind final override val variantNameCapitalized: String = variantName.capitalizeSafely() final override val taskNameSuffix: String = computeTaskNameSuffix() - final override val compileConfigurationName = variantSourceSet.compileClasspathConfigurationName - final override val runtimeConfigurationName = variantSourceSet.runtimeClasspathConfigurationName + final override val compileConfigurationName = androidSources.compileClasspathConfigurationName + final override val runtimeConfigurationName = androidSources.runtimeClasspathConfigurationName final override val kaptConfigurationName = kaptConfName() final override val annotationProcessorConfigurationName = "${variantName}AnnotationProcessorClasspath" - final override val testInstrumentationRunner: String? = variant.mergedFlavor.testInstrumentationRunner - final override val kotlinSourceFiles: FileCollection = getKotlinSources() - final override val javaSourceFiles: FileCollection = getJavaSources() - final override val groovySourceFiles: FileCollection = getGroovySources() - final override val scalaSourceFiles: FileCollection = getScalaSources() + final override val testInstrumentationRunner: Provider = variant.testInstrumentationRunner + final override val kotlinSourceFiles: Provider> = androidSources.getKotlinSources() + final override val javaSourceFiles: Provider> = androidSources.getJavaSources() + final override val groovySourceFiles: Provider> = project.provider { project.files() } + final override val scalaSourceFiles: Provider> = project.provider { project.files() } // TODO(2.0): verify this is the correct attribute. final override val attributeValueJar = ArtifactAttributes.ANDROID_CLASSES_JAR - final override val isDataBindingEnabled: Boolean = dataBindingEnabled - final override val isViewBindingEnabled: Boolean = viewBindingEnabled + final override val isDataBindingEnabled: Provider = agp.isDataBindingEnabled() + final override val isViewBindingEnabled: Provider = agp.isViewBindingEnabled() final override val outputPaths = OutputPaths(project, "$variantName${kind.taskNameSuffix}") @@ -98,9 +91,9 @@ internal abstract class AndroidAnalyzer( final override fun registerExplodeXmlSourceTask(): TaskProvider { return project.tasks.register("explodeXmlSource$taskNameSuffix") { - androidLocalRes.setFrom(getAndroidRes()) - layouts(variant.sourceSets.flatMap { it.resDirectories }) - manifestFiles.setFrom(variant.sourceSets.map { it.manifestFile }) + androidLocalRes.setFrom(androidSources.getAndroidRes()) + layoutFiles.setFrom(androidSources.getLayoutFiles()) + manifestFiles.setFrom(androidSources.getManifestFiles()) namespace.set(agp.namespace()) output.set(outputPaths.androidResToResUsagePath) } @@ -108,7 +101,7 @@ internal abstract class AndroidAnalyzer( final override fun registerExplodeAssetSourceTask(): TaskProvider { return project.tasks.register("explodeAssetSource$taskNameSuffix") { - androidLocalAssets.setFrom(getAndroidAssets()) + androidLocalAssets.setFrom(androidSources.getAndroidAssets()) output.set(outputPaths.androidAssetSourcePath) } } @@ -146,7 +139,7 @@ internal abstract class AndroidAnalyzer( } private fun kaptConfName(): String { - return when (variantSourceSet.variant.kind) { + return when (androidSources.variant.kind) { SourceSetKind.MAIN -> "kapt$variantNameCapitalized" SourceSetKind.TEST -> "kaptTest" SourceSetKind.ANDROID_TEST -> "kaptAndroidTest" @@ -156,7 +149,7 @@ internal abstract class AndroidAnalyzer( // Known to exist in Kotlin 1.3.61. private fun kotlinCompileTask(): TaskProvider? { - return when (variantSourceSet.variant.kind) { + return when (androidSources.variant.kind) { SourceSetKind.MAIN -> project.tasks.namedOrNull("compile${variantNameCapitalized}Kotlin") SourceSetKind.TEST -> project.tasks.namedOrNull("compile${variantNameCapitalized}UnitTestKotlin") SourceSetKind.ANDROID_TEST -> project.tasks.namedOrNull("compile${variantNameCapitalized}AndroidTestKotlin") @@ -167,7 +160,7 @@ internal abstract class AndroidAnalyzer( // Known to exist in AGP 3.5, 3.6, and 4.0, albeit with different backing classes (AndroidJavaCompile, // JavaCompile) private fun javaCompileTask(): TaskProvider { - return when (variantSourceSet.variant.kind) { + return when (androidSources.variant.kind) { SourceSetKind.MAIN -> project.tasks.named("compile${variantNameCapitalized}JavaWithJavac") SourceSetKind.TEST -> project.tasks.named("compile${variantNameCapitalized}UnitTestJavaWithJavac") SourceSetKind.ANDROID_TEST -> project.tasks.named("compile${variantNameCapitalized}AndroidTestJavaWithJavac") @@ -176,76 +169,37 @@ internal abstract class AndroidAnalyzer( } private fun computeTaskNameSuffix(): String { - return if (variantSourceSet.variant.kind == SourceSetKind.MAIN) { + return if (androidSources.variant.kind == SourceSetKind.MAIN) { // "flavorDebug" -> "FlavorDebug" variantName.capitalizeSafely() } else { // "flavorDebug" + "Test" -> "FlavorDebugTest" - variantName.capitalizeSafely() + variantSourceSet.variant.kind.taskNameSuffix + variantName.capitalizeSafely() + androidSources.variant.kind.taskNameSuffix } } - - private fun getGroovySources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.GROOVY)) - private fun getJavaSources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.JAVA)) - private fun getKotlinSources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.KOTLIN)) - private fun getScalaSources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.SCALA)) - - private fun getSourceDirectories(): FileTree { - // Java dirs regardless of whether they exist - val javaDirs = variantSourceSet.androidSourceSets.flatMap { it.javaDirectories } - - // Kotlin dirs, only if they exist. If we filtered the above for existence, and there was no - // Java dir, then this would also be empty. - val kotlinDirs = javaDirs - .map { it.path } - .map { it.removeSuffix("java") + "kotlin" } - .map { File(it) } - .filter { it.exists() } - - // Now finally filter Java dirs for existence - return project.files(javaDirs.filter { it.exists() } + kotlinDirs).asFileTree - } - - private fun getAndroidRes(): FileTree { - val resDirs = variant.sourceSets.flatMap { - it.resDirectories - }.filter { it.exists() } - - return project.files(resDirs).asFileTree.matching { - include("**/*.xml") - } - } - - private fun getAndroidAssets(): FileCollection { - val assetsDirs = variant.sourceSets.flatMap { - it.assetsDirectories - }.filter { it.exists() } - - return project.files(assetsDirs).asFileTree - } } internal class AndroidAppAnalyzer( project: Project, - variant: BaseVariant, + variant: AndroidVariant, agpVersion: String, - variantSourceSet: VariantSourceSet, + androidSources: AndroidSources, ) : AndroidAnalyzer( project = project, variant = variant, - variantSourceSet = variantSourceSet, + androidSources = androidSources, agpVersion = agpVersion ) internal class AndroidLibAnalyzer( project: Project, - variant: BaseVariant, + variant: AndroidVariant, agpVersion: String, - variantSourceSet: VariantSourceSet, + androidSources: AndroidSources, ) : AndroidAnalyzer( project = project, variant = variant, - variantSourceSet = variantSourceSet, + androidSources = androidSources, agpVersion = agpVersion ) { diff --git a/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidSources.kt b/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidSources.kt new file mode 100644 index 000000000..29788170b --- /dev/null +++ b/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidSources.kt @@ -0,0 +1,96 @@ +// Copyright (c) 2024. Tony Robalik. +// SPDX-License-Identifier: Apache-2.0 +package com.autonomousapps.internal.analyzer + +import com.android.build.api.artifact.SingleArtifact +import com.android.build.api.variant.Sources +import com.autonomousapps.model.declaration.Variant +import org.gradle.api.Project +import org.gradle.api.provider.Provider +import java.io.File + +/** + * All the relevant sources for a given Android variant, including Java, Kotlin, assets, res, manifest files, and + * layouts. + */ +internal interface AndroidSources { + val variant: Variant + + /** E.g., `debugCompileClasspath` or `debugUnitTestCompileClasspath` */ + val compileClasspathConfigurationName: String + + /** E.g., `debugRuntimeClasspath` or `debugUnitTestRuntimeClasspath` */ + val runtimeClasspathConfigurationName: String + + fun getJavaSources(): Provider> + fun getKotlinSources(): Provider> + fun getAndroidAssets(): Provider> + fun getAndroidRes(): Provider> + fun getManifestFiles(): Provider> + fun getLayoutFiles(): Provider> +} + +@Suppress("UnstableApiUsage") +internal class DefaultAndroidSources( + private val project: Project, + private val agpVariant: com.android.build.api.variant.Variant, + private val sources: Sources, + override val variant: Variant, + override val compileClasspathConfigurationName: String, + override val runtimeClasspathConfigurationName: String, +) : AndroidSources { + + override fun getJavaSources(): Provider> { + return sources.kotlin?.all + ?.map { directories -> + directories.map { directory -> directory.asFileTree.matching(Language.filterOf(Language.JAVA)) } + }?.map { trees -> trees.flatten() } + ?: project.provider { emptyList() } + } + + override fun getKotlinSources(): Provider> { + return sources.kotlin?.all + ?.map { directories -> + directories.map { directory -> directory.asFileTree.matching(Language.filterOf(Language.KOTLIN)) } + }?.map { trees -> trees.flatten() } + ?: project.provider { emptyList() } + } + + override fun getAndroidAssets(): Provider> { + return sources.assets?.all + ?.map { layers -> layers.flatten() } + ?.map { directories -> directories.map { directory -> directory.asFileTree } } + ?.map { trees -> trees.flatten() } + ?: project.provider { emptyList() } + } + + override fun getAndroidRes(): Provider> { + return sources.res?.all + ?.map { layers -> layers.flatten() } + ?.map { directories -> + directories.map { directory -> directory.asFileTree.matching(Language.filterOf(Language.XML)) } + } + ?.map { trees -> trees.flatten() } + ?: project.provider { emptyList() } + } + + override fun getLayoutFiles(): Provider> { + return sources.res?.all + ?.map { layers -> layers.flatten() } + ?.map { directories -> directories.map { directory -> directory.asFileTree } } + ?.map { fileTrees -> + fileTrees.map { fileTree -> + fileTree.matching { + include("**/layout/**/*.xml") + } + }.flatten() + } + ?: project.provider { emptyList() } + } + + override fun getManifestFiles(): Provider> { + return agpVariant.artifacts.get(SingleArtifact.MERGED_MANIFEST).map { + listOf(it.asFile) + } + } +} diff --git a/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidVariant.kt b/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidVariant.kt new file mode 100644 index 000000000..d5579c43d --- /dev/null +++ b/src/main/kotlin/com/autonomousapps/internal/analyzer/AndroidVariant.kt @@ -0,0 +1,39 @@ +// Copyright (c) 2024. Tony Robalik. +// SPDX-License-Identifier: Apache-2.0 +package com.autonomousapps.internal.analyzer + +import com.android.build.api.variant.HasAndroidTest +import com.android.build.api.variant.Variant +import org.gradle.api.Project +import org.gradle.api.provider.Provider + +internal interface AndroidVariant { + val flavorName: String + val variantName: String + val buildType: String + val testInstrumentationRunner: Provider +} + +internal class DefaultAndroidVariant( + override val flavorName: String, + override val variantName: String, + override val buildType: String, + override val testInstrumentationRunner: Provider, +) : AndroidVariant { + constructor(project: Project, variant: Variant) : this( + flavorName = variant.flavorName.orEmpty(), + variantName = variant.name, + buildType = variant.buildType.orEmpty(), + testInstrumentationRunner = getTestInstrumentationRunner(project, variant), + ) + + private companion object { + fun getTestInstrumentationRunner(project: Project, variant: Variant): Provider { + return if (variant is HasAndroidTest) { + variant.androidTest?.instrumentationRunner ?: project.provider { null } + } else { + project.provider { null } + } + } + } +} diff --git a/src/main/kotlin/com/autonomousapps/internal/analyzer/DependencyAnalyzer.kt b/src/main/kotlin/com/autonomousapps/internal/analyzer/DependencyAnalyzer.kt index 2b8716ff7..ab9fc2734 100644 --- a/src/main/kotlin/com/autonomousapps/internal/analyzer/DependencyAnalyzer.kt +++ b/src/main/kotlin/com/autonomousapps/internal/analyzer/DependencyAnalyzer.kt @@ -6,20 +6,18 @@ package com.autonomousapps.internal.analyzer import com.autonomousapps.internal.OutputPaths import com.autonomousapps.model.declaration.SourceSetKind -import com.autonomousapps.services.InMemoryCache import com.autonomousapps.tasks.* import org.gradle.api.Project import org.gradle.api.UnknownDomainObjectException import org.gradle.api.UnknownTaskException import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.FileCollection -import org.gradle.api.file.FileTree import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.compile.JavaCompile import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.named import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.io.File /** Abstraction for differentiating between android-app, android-lib, and java-lib projects. */ internal interface DependencyAnalyzer { @@ -53,17 +51,18 @@ internal interface DependencyAnalyzer { val annotationProcessorConfigurationName: String /** E.g., "androidx.test.runner.AndroidJUnitRunner" */ - val testInstrumentationRunner: String? + val testInstrumentationRunner: Provider val attributeValueJar: String - val kotlinSourceFiles: FileCollection - val javaSourceFiles: FileCollection? - val groovySourceFiles: FileCollection - val scalaSourceFiles: FileCollection + /** Kotlin projects have no Java source */ + val javaSourceFiles: Provider>? + val kotlinSourceFiles: Provider> + val groovySourceFiles: Provider> + val scalaSourceFiles: Provider> - val isDataBindingEnabled: Boolean - val isViewBindingEnabled: Boolean + val isDataBindingEnabled: Provider + val isViewBindingEnabled: Provider val testJavaCompileName: String val testKotlinCompileName: String @@ -94,16 +93,16 @@ internal interface DependencyAnalyzer { fun registerAndroidScoreTask( synthesizeDependenciesTask: TaskProvider, - synthesizeProjectViewTask: TaskProvider + synthesizeProjectViewTask: TaskProvider, ): TaskProvider? = null } internal abstract class AbstractDependencyAnalyzer( - protected val project: Project + protected val project: Project, ) : DependencyAnalyzer { // Always null for JVM projects. May be null for Android projects. - override val testInstrumentationRunner: String? = null + override val testInstrumentationRunner: Provider = project.provider { null } protected val testJavaCompile by lazy { try { diff --git a/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmProjectAnalyzer.kt b/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmProjectAnalyzer.kt index 0f706d8d6..ddc4763b5 100644 --- a/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmProjectAnalyzer.kt +++ b/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmProjectAnalyzer.kt @@ -18,6 +18,7 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.register +import java.io.File internal abstract class JvmAnalyzer( project: Project, @@ -39,13 +40,13 @@ internal abstract class JvmAnalyzer( final override val attributeValueJar = "jar" - final override val kotlinSourceFiles: FileCollection = getKotlinSources() - override val javaSourceFiles: FileCollection? = getJavaSources() - final override val groovySourceFiles: FileCollection = getGroovySources() - final override val scalaSourceFiles: FileCollection = getScalaSources() + final override val kotlinSourceFiles: Provider> = getKotlinSources() + override val javaSourceFiles: Provider>? = getJavaSources() + final override val groovySourceFiles: Provider> = getGroovySources() + final override val scalaSourceFiles: Provider> = getScalaSources() - final override val isDataBindingEnabled: Boolean = false - final override val isViewBindingEnabled: Boolean = false + final override val isDataBindingEnabled: Provider = project.provider { false } + final override val isViewBindingEnabled: Provider = project.provider { false } override val outputPaths = OutputPaths(project, variantName) @@ -92,10 +93,19 @@ internal abstract class JvmAnalyzer( } } - private fun getGroovySources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.GROOVY)) - private fun getJavaSources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.JAVA)) - private fun getKotlinSources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.KOTLIN)) - private fun getScalaSources(): FileCollection = getSourceDirectories().matching(Language.filterOf(Language.SCALA)) + private fun getGroovySources(): Provider> { + return project.provider { getSourceDirectories().matching(Language.filterOf(Language.GROOVY)) } + } + private fun getJavaSources(): Provider> { + return project.provider { getSourceDirectories().matching(Language.filterOf(Language.JAVA)) } + } + private fun getKotlinSources(): Provider> { + return project.provider { getSourceDirectories().matching(Language.filterOf(Language.KOTLIN)) } + } + + private fun getScalaSources(): Provider> { + return project.provider { getSourceDirectories().matching(Language.filterOf(Language.SCALA)) } + } private fun getSourceDirectories(): FileTree { val allSource = sourceSet.sourceCode.sourceDirectories @@ -134,7 +144,7 @@ internal abstract class KotlinJvmAnalyzer( sourceSet = KotlinSourceSet(sourceSet, kind), hasAbi = hasAbi ) { - final override val javaSourceFiles: FileTree? = null + final override val javaSourceFiles = null } internal class KotlinJvmAppAnalyzer( diff --git a/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmSourceSet.kt b/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmSourceSet.kt index 77f67d1ed..5c05f2727 100644 --- a/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmSourceSet.kt +++ b/src/main/kotlin/com/autonomousapps/internal/analyzer/JvmSourceSet.kt @@ -2,9 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 package com.autonomousapps.internal.analyzer -import com.android.builder.model.SourceProvider import com.autonomousapps.model.declaration.SourceSetKind -import com.autonomousapps.model.declaration.Variant import org.gradle.api.file.FileCollection import org.gradle.api.file.FileTree import org.gradle.api.file.SourceDirectorySet @@ -62,30 +60,17 @@ internal class KotlinSourceSet( override val classesDirs: FileCollection = sourceSet.output.classesDirs } -/** All the relevant Java and Kotlin source sets for a given Android variant. */ -internal class VariantSourceSet( - val variant: Variant, - val androidSourceSets: Set = emptySet(), - /** E.g., `debugCompileClasspath` or `debugUnitTestCompileClasspath` */ - val compileClasspathConfigurationName: String, - /** E.g., `debugRuntimeClasspath` or `debugUnitTestRuntimeClasspath` */ - val runtimeClasspathConfigurationName: String, -) - internal fun SourceSet.java(): FileTree { - return java.sourceDirectories.asFileTree.matching { - include("**/*.java") - } + return java.sourceDirectories.asFileTree.matching(Language.filterOf(Language.JAVA)) } internal fun JbKotlinSourceSet.kotlin(): FileTree { - return kotlin.sourceDirectories.asFileTree.matching { - include("**/*.kt") - } + return kotlin.sourceDirectories.asFileTree.matching(Language.filterOf(Language.KOTLIN)) } internal fun SourceSet.groovy(): FileTree? { - return extensions.findByType()?.sourceDirectories?.asFileTree?.matching { - include("**/*.groovy") - } + return extensions.findByType() + ?.sourceDirectories + ?.asFileTree + ?.matching(Language.filterOf(Language.GROOVY)) } diff --git a/src/main/kotlin/com/autonomousapps/internal/analyzer/Language.kt b/src/main/kotlin/com/autonomousapps/internal/analyzer/Language.kt index f8ba29956..92d2f3674 100644 --- a/src/main/kotlin/com/autonomousapps/internal/analyzer/Language.kt +++ b/src/main/kotlin/com/autonomousapps/internal/analyzer/Language.kt @@ -10,6 +10,7 @@ internal enum class Language(val pattern: String) { JAVA("**/*.java"), KOTLIN("**/*.kt"), SCALA("**/*.scala"), + XML("**/*.xml"), ; companion object { diff --git a/src/main/kotlin/com/autonomousapps/internal/android/AgpVersion.kt b/src/main/kotlin/com/autonomousapps/internal/android/AgpVersion.kt index 9cc9943fa..cd2a7359b 100644 --- a/src/main/kotlin/com/autonomousapps/internal/android/AgpVersion.kt +++ b/src/main/kotlin/com/autonomousapps/internal/android/AgpVersion.kt @@ -5,14 +5,17 @@ package com.autonomousapps.internal.android import com.android.Version import com.autonomousapps.internal.utils.VersionNumber +/** + * @see AGP artifacts + */ internal class AgpVersion private constructor(val version: String) : Comparable { private val versionNumber = VersionNumber.parse(version) companion object { - @JvmStatic val AGP_MIN = version("7.4.2") - @JvmStatic val AGP_MAX = version("8.2.0-alpha16") + @JvmStatic val AGP_MIN = version("8.0.0") + @JvmStatic val AGP_MAX = version("8.4.0-alpha01") @JvmStatic fun current(): AgpVersion = AgpVersion(agpVersion()) @JvmStatic fun version(version: String): AgpVersion = AgpVersion(version) diff --git a/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin.kt b/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin.kt index c25f300fe..72994d14f 100644 --- a/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin.kt +++ b/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin.kt @@ -7,8 +7,8 @@ import org.gradle.api.provider.Provider internal interface AndroidGradlePlugin { fun getBundleTaskOutput(variantName: String): Provider - fun isViewBindingEnabled(): Boolean - fun isDataBindingEnabled(): Boolean + fun isViewBindingEnabled(): Provider + fun isDataBindingEnabled(): Provider /** * The package name or "namespace" of this Android module. diff --git a/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin4_2.kt b/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin4_2.kt index f7759d75f..f40234d31 100644 --- a/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin4_2.kt +++ b/src/main/kotlin/com/autonomousapps/internal/android/AndroidGradlePlugin4_2.kt @@ -5,17 +5,14 @@ package com.autonomousapps.internal.android import com.android.build.api.dsl.CommonExtension -import com.android.build.gradle.BaseExtension import org.gradle.api.Project import org.gradle.api.file.RegularFile import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Provider -import org.gradle.kotlin.dsl.the -import org.gradle.kotlin.dsl.withGroovyBuilder internal class AndroidGradlePlugin4_2( project: Project, - agpVersion: String + agpVersion: String, ) : BaseAndroidGradlePlugin(project, agpVersion) { override val bundleTaskType: String = "com.android.build.gradle.internal.tasks.BundleLibraryClassesJar" @@ -32,14 +29,12 @@ internal class AndroidGradlePlugin4_2( } } - override fun isViewBindingEnabled(): Boolean = project.the().withGroovyBuilder { - getProperty("buildFeatures").withGroovyBuilder { getProperty("viewBinding") } as Boolean? - ?: false + override fun isViewBindingEnabled(): Provider { + return project.provider { project.extensions.getByType(CommonExtension::class.java).viewBinding.enable } } - override fun isDataBindingEnabled(): Boolean = project.the().withGroovyBuilder { - getProperty("buildFeatures").withGroovyBuilder { getProperty("dataBinding") } as Boolean? - ?: false + override fun isDataBindingEnabled(): Provider { + return project.provider { project.extensions.getByType(CommonExtension::class.java).dataBinding.enable } } override fun namespace(): Provider { diff --git a/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt b/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt index 982fe5911..bb42d680c 100644 --- a/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt +++ b/src/main/kotlin/com/autonomousapps/subplugin/ProjectPlugin.kt @@ -2,6 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 package com.autonomousapps.subplugin +import com.android.build.api.variant.AndroidComponentsExtension +import com.android.build.api.variant.HasAndroidTest +import com.android.build.api.variant.Sources import com.android.build.gradle.AppExtension import com.android.build.gradle.LibraryExtension import com.android.build.gradle.api.BaseVariant @@ -148,56 +151,60 @@ internal class ProjectPlugin(private val project: Project) { /** Has the `com.android.application` plugin applied. */ private fun Project.configureAndroidAppProject() { val project = this - val appExtension = the() val ignoredVariantNames = androidIgnoredVariants() - val allowedVariants = appExtension.applicationVariants.matching { variant -> - !ignoredVariantNames.contains(variant.name) - } - - allowedVariants.all { - val mainSourceSets = sourceSets - val unitTestSourceSets = if (shouldAnalyzeTests()) unitTestVariant?.sourceSets else null - val androidTestSourceSets = if (shouldAnalyzeTests()) testVariant?.sourceSets else null - - val agpVersion = AgpVersion.current().version - - mainSourceSets.let { sourceSets -> - val variantSourceSet = newVariantSourceSet(name, SourceSetKind.MAIN, sourceSets) - val dependencyAnalyzer = AndroidAppAnalyzer( - project = project, - variant = this, - agpVersion = agpVersion, - variantSourceSet = variantSourceSet - ) - isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) - isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) - analyzeDependencies(dependencyAnalyzer) - } - unitTestSourceSets?.let { sourceSets -> - val variantSourceSet = newVariantSourceSet(name, SourceSetKind.TEST, sourceSets) - val dependencyAnalyzer = AndroidAppAnalyzer( - project = project, - variant = this, - agpVersion = agpVersion, - variantSourceSet = variantSourceSet - ) - isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) - isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) - analyzeDependencies(dependencyAnalyzer) - } + val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java) + // val newAgpVersion = androidComponents.pluginVersion.toString().removePrefix("Android Gradle Plugin version ") + val agpVersion = AgpVersion.current().version - androidTestSourceSets?.let { sourceSets -> - val variantSourceSet = newVariantSourceSet(name, SourceSetKind.ANDROID_TEST, sourceSets) - val dependencyAnalyzer = AndroidAppAnalyzer( - project = this@configureAndroidAppProject, - variant = this, - agpVersion = agpVersion, - variantSourceSet = variantSourceSet - ) - isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) - isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) - analyzeDependencies(dependencyAnalyzer) + androidComponents.onVariants { variant -> + if (variant.name !in ignoredVariantNames) { + val mainSourceSets = variant.sources + val unitTestSourceSets = if (shouldAnalyzeTests()) variant.unitTest?.sources else null + val androidTestSourceSets = if (shouldAnalyzeTests() && variant is HasAndroidTest) { + variant.androidTest?.sources + } else { + null + } + + mainSourceSets.let { sourceSets -> + val variantSourceSet = newVariantSourceSet(variant.name, SourceSetKind.MAIN, variant, sourceSets) + val dependencyAnalyzer = AndroidAppAnalyzer( + project = project, + variant = DefaultAndroidVariant(project, variant), + agpVersion = agpVersion, + androidSources = variantSourceSet + ) + isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) + isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) + analyzeDependencies(dependencyAnalyzer) + } + + unitTestSourceSets?.let { sourceSets -> + val variantSourceSet = newVariantSourceSet(variant.name, SourceSetKind.TEST, variant, sourceSets) + val dependencyAnalyzer = AndroidAppAnalyzer( + project = project, + variant = DefaultAndroidVariant(project, variant), + agpVersion = agpVersion, + androidSources = variantSourceSet + ) + isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) + isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) + analyzeDependencies(dependencyAnalyzer) + } + + androidTestSourceSets?.let { sourceSets -> + val variantSourceSet = newVariantSourceSet(variant.name, SourceSetKind.ANDROID_TEST, variant, sourceSets) + val dependencyAnalyzer = AndroidAppAnalyzer( + project = this@configureAndroidAppProject, + variant = DefaultAndroidVariant(project, variant), + agpVersion = agpVersion, + androidSources = variantSourceSet + ) + isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) + isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) + analyzeDependencies(dependencyAnalyzer) + } } } } @@ -205,55 +212,60 @@ internal class ProjectPlugin(private val project: Project) { /** Has the `com.android.library` plugin applied. */ private fun Project.configureAndroidLibProject() { val project = this - val libraryExtension = the() val ignoredVariantNames = androidIgnoredVariants() - val allowedVariants = libraryExtension.libraryVariants.matching { variant -> - !ignoredVariantNames.contains(variant.name) - } - allowedVariants.all { - val mainSourceSets = sourceSets - val unitTestSourceSets = if (shouldAnalyzeTests()) unitTestVariant?.sourceSets else null - val androidTestSourceSets = if (shouldAnalyzeTests()) testVariant?.sourceSets else null - - val agpVersion = AgpVersion.current().version - - mainSourceSets.let { sourceSets -> - val variantSourceSet = newVariantSourceSet(name, SourceSetKind.MAIN, sourceSets) - val dependencyAnalyzer = AndroidLibAnalyzer( - project = project, - variant = this, - agpVersion = agpVersion, - variantSourceSet = variantSourceSet - ) - isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) - isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) - analyzeDependencies(dependencyAnalyzer) - } - unitTestSourceSets?.let { sourceSets -> - val variantSourceSet = newVariantSourceSet(name, SourceSetKind.TEST, sourceSets) - val dependencyAnalyzer = AndroidLibAnalyzer( - project = project, - variant = this, - agpVersion = agpVersion, - variantSourceSet = variantSourceSet - ) - isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) - isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) - analyzeDependencies(dependencyAnalyzer) - } + val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java) + // val newAgpVersion = androidComponents.pluginVersion.toString().removePrefix("Android Gradle Plugin version ") + val agpVersion = AgpVersion.current().version - androidTestSourceSets?.let { sourceSets -> - val variantSourceSet = newVariantSourceSet(name, SourceSetKind.ANDROID_TEST, sourceSets) - val dependencyAnalyzer = AndroidLibAnalyzer( - project = project, - variant = this, - agpVersion = agpVersion, - variantSourceSet = variantSourceSet - ) - isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) - isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) - analyzeDependencies(dependencyAnalyzer) + androidComponents.onVariants { variant -> + if (variant.name !in ignoredVariantNames) { + val mainSourceSets = variant.sources + val unitTestSourceSets = if (shouldAnalyzeTests()) variant.unitTest?.sources else null + val androidTestSourceSets = if (shouldAnalyzeTests() && variant is HasAndroidTest) { + variant.androidTest?.sources + } else { + null + } + + mainSourceSets.let { sourceSets -> + val variantSourceSet = newVariantSourceSet(variant.name, SourceSetKind.MAIN, variant, sourceSets) + val dependencyAnalyzer = AndroidLibAnalyzer( + project = project, + variant = DefaultAndroidVariant(project, variant), + agpVersion = agpVersion, + androidSources = variantSourceSet + ) + isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) + isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) + analyzeDependencies(dependencyAnalyzer) + } + + unitTestSourceSets?.let { sourceSets -> + val variantSourceSet = newVariantSourceSet(variant.name, SourceSetKind.TEST, variant, sourceSets) + val dependencyAnalyzer = AndroidLibAnalyzer( + project = project, + variant = DefaultAndroidVariant(project, variant), + agpVersion = agpVersion, + androidSources = variantSourceSet + ) + isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) + isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) + analyzeDependencies(dependencyAnalyzer) + } + + androidTestSourceSets?.let { sourceSets -> + val variantSourceSet = newVariantSourceSet(variant.name, SourceSetKind.ANDROID_TEST, variant, sourceSets) + val dependencyAnalyzer = AndroidLibAnalyzer( + project = project, + variant = DefaultAndroidVariant(project, variant), + agpVersion = agpVersion, + androidSources = variantSourceSet + ) + isDataBindingEnabled.set(dependencyAnalyzer.isDataBindingEnabled) + isViewBindingEnabled.set(dependencyAnalyzer.isViewBindingEnabled) + analyzeDependencies(dependencyAnalyzer) + } } } } @@ -261,10 +273,13 @@ internal class ProjectPlugin(private val project: Project) { private fun newVariantSourceSet( variantName: String, kind: SourceSetKind, - androidSourceSets: List, - ) = VariantSourceSet( + variant: com.android.build.api.variant.Variant, + sources: Sources, + ): AndroidSources = DefaultAndroidSources( + project = project, + sources = sources, + agpVariant = variant, variant = Variant(variantName, kind), - androidSourceSets = androidSourceSets.toSortedSet(JAVA_COMPARATOR), compileClasspathConfigurationName = kind.compileClasspathConfigurationName(variantName), runtimeClasspathConfigurationName = kind.runtimeClasspathConfigurationName(variantName), ) @@ -749,7 +764,7 @@ internal class ProjectPlugin(private val project: Project) { // Optional: only exists for Android libraries. explodeAssetSourceTask?.let { t -> androidAssetsSource.set(t.flatMap { it.output }) } // Optional: only exists for Android projects. - dependencyAnalyzer.testInstrumentationRunner?.let { testInstrumentationRunner.set(it) } + testInstrumentationRunner.set(dependencyAnalyzer.testInstrumentationRunner) output.set(outputPaths.syntheticProjectPath) } diff --git a/src/main/kotlin/com/autonomousapps/tasks/XmlSourceExploderTask.kt b/src/main/kotlin/com/autonomousapps/tasks/XmlSourceExploderTask.kt index 065b04c52..9ffc47585 100644 --- a/src/main/kotlin/com/autonomousapps/tasks/XmlSourceExploderTask.kt +++ b/src/main/kotlin/com/autonomousapps/tasks/XmlSourceExploderTask.kt @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 package com.autonomousapps.tasks -import com.autonomousapps.TASK_GROUP_DEP_INTERNAL import com.autonomousapps.internal.parse.AndroidLayoutParser import com.autonomousapps.internal.parse.AndroidManifestParser import com.autonomousapps.internal.parse.AndroidResBuilder @@ -14,13 +13,11 @@ import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.ProjectLayout import org.gradle.api.file.RegularFileProperty -import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property import org.gradle.api.tasks.* import org.gradle.workers.WorkAction import org.gradle.workers.WorkParameters import org.gradle.workers.WorkerExecutor -import java.io.File import javax.inject.Inject /** @@ -46,14 +43,8 @@ import javax.inject.Inject abstract class XmlSourceExploderTask @Inject constructor( private val workerExecutor: WorkerExecutor, private val layout: ProjectLayout, - private val objects: ObjectFactory ) : DefaultTask() { - init { - group = TASK_GROUP_DEP_INTERNAL - description = "Produces a report of all resources references in this project" - } - @get:PathSensitive(PathSensitivity.RELATIVE) @get:InputFiles abstract val androidLocalRes: ConfigurableFileCollection @@ -74,22 +65,6 @@ abstract class XmlSourceExploderTask @Inject constructor( @get:OutputFile abstract val output: RegularFileProperty - internal fun layouts(files: List) { - for (file in files) { - layoutFiles.from( - objects.fileTree().from(file) - .matching { - // At this point in the filtering, there's a mix of directories and files - // Can't filter on file extension - include { it.path.contains("layout") } - }.files - // At this point, we have only files. It is safe to filter on extension. We - // only want XML files. - .filter { it.extension == "xml" } - ) - } - } - @TaskAction fun action() { workerExecutor.noIsolation().submit(XmlSourceExploderWorkAction::class.java) { projectDir.set(layout.projectDirectory)