From c3a0f39f816317b8f945596a6d5fd3b33f8bbb71 Mon Sep 17 00:00:00 2001 From: Brad Corso Date: Thu, 27 Nov 2025 10:21:18 -0800 Subject: [PATCH] Update HiltGradlePlugin to AGP 9. This required a number of changes: * Update Gradle 8.14.3 -> 9.2.0 * Update shadow plugin from `com.github.johnrengelman.shadow:8.1.1` to 'com.gradleup.shadow:9.2.2' (old artifact doesn't support Gradle 9). * Update HiltGradlePlugin to 9.0.0-beta02: * Migrate `BaseExtension` to `AndroidComponentsExtension` * Migrate `BaseVariant` to `Component` * Migrate `variant.javaCompileOutput.classpath` to `variant.compileClasspath` * Migrate `variant.javaCompileOutput.destinationDirectory` to `variant.artifacts.use(HiltCopyTask).toGet()` * Migrate `variant.javaCompileOutput.options.bootstrapClasspath` with `androidExtension.sdkComponents.bootClasspath` * Migrate `variant.javaCompileOutput.options.compilerArgumentProviders` with `variant.javaCompilation.annotationProcessor.argumentProviders` * `project.buildDir = ...` to `project.layout.buildDirectory.set(...)` * Update HiltGradlePlugin tests to use AGP 9.0.0-beta02: * Migrate to builtin kotlin * remove 'kotlin-android' * replace 'kotlin-kapt' with 'legacy-kapt' * Migrate javatests/artifacts/hilt-android/simple/app/build.gradle to kts and replace GradleVersion with custom AgpVersion. The GradleVersion does not work with APG versions like 9.0.0-beta02, so I had to do this with custom parsing. * remove `android.kotlinOptions` (removed in AGP 9) RELNOTES=N/A PiperOrigin-RevId: 837566667 --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- java/dagger/hilt/android/plugin/build.gradle | 10 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../hilt/android/plugin/main/build.gradle | 20 +- .../hilt/android/plugin/HiltGradlePlugin.kt | 118 ++++++----- .../hilt/android/plugin/task/HiltSyncTask.kt | 39 ++++ .../android/plugin/util/Configurations.kt | 31 --- .../dagger/hilt/android/plugin/util/Tasks.kt | 3 +- .../hilt/android/plugin/util/Variants.kt | 32 --- .../src/test/kotlin/AGPCompatibilityTest.kt | 7 +- .../main/src/test/kotlin/BuildCacheTest.kt | 2 +- .../main/src/test/kotlin/GradleTestRunner.kt | 10 +- .../test/kotlin/IncrementalProcessorTest.kt | 2 +- .../main/src/test/kotlin/SPIPluginTest.kt | 3 +- .../main/src/test/kotlin/TransformTest.kt | 92 ++++---- .../dagger-android-ksp/app/build.gradle | 1 - .../dagger-android/simple/build.gradle | 3 - .../hilt-android/lazyclasskey/build.gradle | 2 +- .../pluginMarker/app/build.gradle | 2 +- .../hilt-android/simple/app/build.gradle | 139 ------------ .../hilt-android/simple/app/build.gradle.kts | 199 ++++++++++++++++++ .../hilt-android/simple/build.gradle | 5 +- .../hilt-android/simple/feature/build.gradle | 3 +- .../simpleKotlin/android-library/build.gradle | 6 +- .../simpleKotlin/app/build.gradle | 3 +- .../hilt-android/simpleKotlin/build.gradle | 1 + .../deep-android-lib/build.gradle | 6 +- util/deploy-hilt-gradle-plugin.sh | 2 +- 29 files changed, 391 insertions(+), 356 deletions(-) create mode 100644 java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/task/HiltSyncTask.kt delete mode 100644 javatests/artifacts/hilt-android/simple/app/build.gradle create mode 100644 javatests/artifacts/hilt-android/simple/app/build.gradle.kts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c5ab96cbfb..02269ef8828 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: - USE_AGP_VERSION: '8.13.0' + USE_AGP_VERSION: '9.0.0-beta04' USE_JAVA_DISTRIBUTION: 'zulu' USE_JAVA_VERSION_FOR_BAZEL: '21' USE_JAVA_VERSION_FOR_GRADLE: '21' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a564ac5b79f..2f9c6e87662 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: - USE_AGP_VERSION: '8.13.0' + USE_AGP_VERSION: '9.0.0-beta04' USE_JAVA_DISTRIBUTION: 'zulu' USE_JAVA_VERSION_FOR_BAZEL: '21' USE_JAVA_VERSION_FOR_GRADLE: '21' diff --git a/java/dagger/hilt/android/plugin/build.gradle b/java/dagger/hilt/android/plugin/build.gradle index 7e95e4f545b..77ba04678c8 100644 --- a/java/dagger/hilt/android/plugin/build.gradle +++ b/java/dagger/hilt/android/plugin/build.gradle @@ -1,7 +1,7 @@ buildscript { ext { kotlin_version = "2.2.0" - agp_version = System.getenv('AGP_VERSION') + agp_version = System.getenv('AGP_VERSION') ?: "9.0.0-beta04" ksp_version = "$kotlin_version-2.0.2" pluginArtifactId = 'hilt-android-gradle-plugin' pluginId = 'com.google.dagger.hilt.android' @@ -12,7 +12,7 @@ plugins { id 'org.jetbrains.kotlin.jvm' version "$kotlin_version" id 'java-gradle-plugin' id 'maven-publish' - id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'com.gradleup.shadow' version '9.2.2' id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false } @@ -24,10 +24,10 @@ allprojects { } // Avoids conflict with BUILD file -project.buildDir = 'buildOut' +project.layout.buildDirectory.set(file('buildOut')) -subprojects { - project.buildDir = 'buildOut' +subprojects {subproject -> + subproject.layout.buildDirectory.set(file('buildOut')) afterEvaluate { dependencies { // This is needed to align older versions of kotlin-stdlib. diff --git a/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.properties b/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.properties index 3ae1e2f124c..63e0e830323 100644 --- a/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.properties +++ b/java/dagger/hilt/android/plugin/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/java/dagger/hilt/android/plugin/main/build.gradle b/java/dagger/hilt/android/plugin/main/build.gradle index d288985f56f..e6def030104 100644 --- a/java/dagger/hilt/android/plugin/main/build.gradle +++ b/java/dagger/hilt/android/plugin/main/build.gradle @@ -17,14 +17,13 @@ import dagger.hilt.android.plugin.task.ImportSharedLibTask import java.util.zip.ZipEntry import java.util.zip.ZipFile -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinVersion plugins { id 'org.jetbrains.kotlin.jvm' id 'java-gradle-plugin' id 'maven-publish' - id 'com.github.johnrengelman.shadow' + id 'com.gradleup.shadow' } configurations { @@ -69,6 +68,7 @@ dependencies { // Use compile-only for other plugin dependencies to avoid brining those // to projects that don't use them. compileOnly "com.android.tools.build:gradle:$agp_version" + compileOnly "com.android.legacy-kapt:com.android.legacy-kapt.gradle.plugin:$agp_version" compileOnly "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" compileOnly "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp_version" @@ -81,6 +81,7 @@ dependencies { testImplementation 'com.google.truth:truth:1.0.1' testImplementation 'org.javassist:javassist:3.26.0-GA' testPluginCompile "com.android.tools.build:gradle:$agp_version" + testPluginCompile "com.android.legacy-kapt:com.android.legacy-kapt.gradle.plugin:$agp_version" testPluginCompile "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" testPluginCompile "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp_version" } @@ -110,18 +111,19 @@ kotlin { tasks.register("importSharedLib", ImportSharedLibTask) { outputDir.set(file("${project.projectDir}/libs")) } -tasks.getByName('compileKotlin').dependsOn('importSharedLib') +tasks.named('compileKotlin').configure { it.dependsOn('importSharedLib') } // Task that generates a top-level property containing the version of the // project so that it can be used in code and at runtime. -def pluginVersionOutDir = file("$buildDir/generated/source/plugin-version/") +def pluginVersionOutDir = + project.layout.buildDirectory.map {file("$it/generated/source/plugin-version/") } tasks.register("generatePluginVersionSource").configure { def version = getPublishVersion() inputs.property('version', version) outputs.dir(pluginVersionOutDir) doLast { def versionFile = - file("$pluginVersionOutDir/dagger/hilt/android/plugin/Version.kt") + file("${pluginVersionOutDir.get()}/dagger/hilt/android/plugin/Version.kt") versionFile.parentFile.mkdirs() versionFile.text = """ // Generated file. Do not edit! @@ -132,14 +134,14 @@ tasks.register("generatePluginVersionSource").configure { } } sourceSets.main.java.srcDir pluginVersionOutDir -tasks.getByName('compileKotlin').dependsOn('generatePluginVersionSource') +tasks.named('compileKotlin').configure { it.dependsOn('generatePluginVersionSource') } // Create sources Jar from main kotlin sources tasks.register("sourcesJar", Jar).configure { group = JavaBasePlugin.DOCUMENTATION_GROUP description = "Assembles sources JAR" archiveClassifier.set("sources") - from(sourceSets["main"].allSource) + from(sourceSets.named("main").map { it.allSource }) dependsOn('generatePluginVersionSource') } @@ -153,7 +155,7 @@ tasks.register("javadocJar", Jar).configure { } // Disable Gradle metadata publication. -tasks.withType(GenerateModuleMetadata) { +tasks.withType(GenerateModuleMetadata).configureEach { enabled = false } @@ -254,7 +256,7 @@ def getPublishVersion() { return (publishVersion != null) ? publishVersion : "LOCAL-SNAPSHOT" } -def checkJarFile(File jarFile, String... allowedPrefixes) { +static def checkJarFile(File jarFile, String... allowedPrefixes) { def zip = new ZipFile(jarFile) try { Enumeration list = zip.entries() diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt index 091309603f5..d8057472330 100644 --- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt +++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt @@ -17,18 +17,21 @@ package dagger.hilt.android.plugin import com.android.build.api.AndroidPluginVersion +import com.android.build.api.artifact.ScopedArtifact import com.android.build.api.dsl.CommonExtension import com.android.build.api.dsl.CompileOptions import com.android.build.api.instrumentation.FramesComputationMode import com.android.build.api.instrumentation.InstrumentationScope import com.android.build.api.variant.AndroidComponentsExtension import com.android.build.api.variant.ApplicationAndroidComponentsExtension +import com.android.build.api.variant.Component import com.android.build.api.variant.LibraryAndroidComponentsExtension +import com.android.build.api.variant.ScopedArtifacts import com.android.build.api.variant.TestAndroidComponentsExtension -import com.android.build.gradle.BaseExtension import com.android.build.gradle.api.AndroidBasePlugin import com.android.build.gradle.tasks.JdkImageInput import dagger.hilt.android.plugin.task.AggregateDepsTask +import dagger.hilt.android.plugin.task.HiltSyncTask import dagger.hilt.android.plugin.transform.AggregatedPackagesTransform import dagger.hilt.android.plugin.transform.AndroidEntryPointClassVisitor import dagger.hilt.android.plugin.transform.CopyTransform @@ -36,7 +39,6 @@ import dagger.hilt.android.plugin.util.addJavaTaskProcessorOptions import dagger.hilt.android.plugin.util.addKaptTaskProcessorOptions import dagger.hilt.android.plugin.util.addKspTaskProcessorOptions import dagger.hilt.android.plugin.util.capitalize -import dagger.hilt.android.plugin.util.forEachRootVariant import dagger.hilt.android.plugin.util.getConfigName import dagger.hilt.android.plugin.util.getKaptConfigName import dagger.hilt.android.plugin.util.getKspConfigName @@ -55,6 +57,7 @@ import org.gradle.api.artifacts.ExternalDependency import org.gradle.api.artifacts.component.ProjectComponentIdentifier import org.gradle.api.attributes.Attribute import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DuplicatesStrategy import org.gradle.api.file.FileCollection import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.TaskProvider @@ -177,31 +180,34 @@ class HiltGradlePlugin @Inject constructor(private val providers: ProviderFactor } private fun HiltPluginEnvironment.configureAggregatingTask() { - legacyAndroidExtension.forEachRootVariant { variant -> + androidExtension.onRootVariants { variant, testedVariant -> if (!isAggregatingTaskEnabled()) { // Option is not enabled, don't configure aggregating task. - return@forEachRootVariant + return@onRootVariants } // Both the AggregateDepsTask and the JavaCompileTask need the runtime configuration, which - // contains the full set of transitive dependencies for this variant. In addition, we create - // the hiltCompileOnly configuration, which contains the generated bytecode of the main - // javac/kotlinc compile tasks, R.jar, compileOnly dependencies, and tested classes if - // the variant is androidTest. Note: These configurations should be filtered using + // contains the full set of transitive dependencies for this variant, and the compile + // configuration, which contains the compileOnly dependencies. In addition, we create the + // hiltCompileOnly configuration, which contains the generated bytecode of the main + // javac/kotlinc compile tasks and R.jar dependencies, and tested classes if the variant is + // androidTest. Note: These configurations should be filtered using // getHiltTransformedDependencies to only include what Hilt needs in the classpath. val configurations = - buildList { - @Suppress("DEPRECATION") // Older variant API is deprecated - if (variant is com.android.build.gradle.api.TestVariant) { - add(variant.testedVariant.runtimeConfiguration) + buildList { + testedVariant?.let { + add(it.runtimeConfiguration) + add(it.compileConfiguration) } add(variant.runtimeConfiguration) - add(createHiltCompileOnlyConfiguration(variant)) + add(variant.compileConfiguration) + add(createHiltCompileOnlyConfiguration(variant, testedVariant)) } val aggregatingTask = configureAggregateDepsTask( variant = variant, + testedVariant = testedVariant, classpath = project.files( getHiltTransformedDependencies(configurations, AGGREGATED_HILT_ARTIFACT_TYPE_VALUE) @@ -211,6 +217,7 @@ class HiltGradlePlugin @Inject constructor(private val providers: ProviderFactor val javaCompileTask = configureJavaCompileTask( variant = variant, + testedVariant = testedVariant, sources = project.files(aggregatingTask.map { it.outputDir }), classpath = project.files( @@ -218,36 +225,64 @@ class HiltGradlePlugin @Inject constructor(private val providers: ProviderFactor ), ) - val javaCompileOutput = project.files(javaCompileTask.map { it.destinationDirectory }) - javaCompileOutput.builtBy(javaCompileTask) - variant.registerPostJavacGeneratedBytecode(javaCompileOutput) + variant.artifacts + .forScope(ScopedArtifacts.Scope.PROJECT) + .use(javaCompileTask) + .toAppend(ScopedArtifact.CLASSES, JavaCompile::getDestinationDirectory) } } private fun HiltPluginEnvironment.createHiltCompileOnlyConfiguration( - @Suppress("DEPRECATION") variant: com.android.build.gradle.api.BaseVariant, + variant: Component, + testedVariant: Component? ): Configuration { + val hiltSyncTask = + project.tasks.register( + "hiltSync${variant.name.capitalize()}", + HiltSyncTask::class.java + ) { task -> + task.duplicatesStrategy = DuplicatesStrategy.EXCLUDE + task.from(task.classesJars) + task.from(task.classesDirectories) + task.from(task.testedClassesJars) + task.from(task.testedClassesDirectories) + task.into(project.buildDir("intermediates/hilt/copy/${variant.name}/")) + } + + variant.artifacts + .forScope(ScopedArtifacts.Scope.PROJECT) + .use(hiltSyncTask) + .toGet( + type = ScopedArtifact.POST_COMPILATION_CLASSES, + inputJars = HiltSyncTask::classesJars, + inputDirectories = HiltSyncTask::classesDirectories + ) + + testedVariant?.artifacts + ?.forScope(ScopedArtifacts.Scope.PROJECT) + ?.use(hiltSyncTask) + ?.toGet( + type = ScopedArtifact.CLASSES, + inputJars = HiltSyncTask::testedClassesJars, + inputDirectories = HiltSyncTask::testedClassesDirectories + ) + return project.configurations.create("hiltCompileOnly${variant.name.capitalize()}").apply { description = "Hilt aggregated compile only dependencies for '${variant.name}'" isCanBeConsumed = false isCanBeResolved = true - // Add the JavaCompile task classpath and output dir to the config, the task's classpath - // will contain: - // * compileOnly dependencies - // * KAPT, KSP and Kotlinc generated bytecode - // * R.jar - // * Tested classes if the variant is androidTest - // TODO(danysantiago): Revisit to support K2 compiler + // Add the current variant's JavaCompile output to the cofiguration. This includes the + // compiled classes from any Java/Kotlin sources (including those generated by KAPT/KSP). project.dependencies.apply { - add(name, project.files(variant.javaCompileProvider.map { it.classpath })) - add(name, project.files(variant.javaCompileProvider.map { it.destinationDirectory })) + add(name, project.files(hiltSyncTask.map { it.outputs.files })) } } } private fun HiltPluginEnvironment.configureAggregateDepsTask( - @Suppress("DEPRECATION") variant: com.android.build.gradle.api.BaseVariant, + variant: Component, + testedVariant: Component?, classpath: ConfigurableFileCollection, ): TaskProvider { return project.tasks.register( @@ -256,11 +291,8 @@ class HiltGradlePlugin @Inject constructor(private val providers: ProviderFactor ) { it.compileClasspath.setFrom(classpath) it.outputDir.set(project.buildDir("generated/hilt/component_trees/${variant.name}/")) - @Suppress("DEPRECATION") // Older variant API is deprecated it.testEnvironment.set( - variant is com.android.build.gradle.api.TestVariant || - variant is com.android.build.gradle.api.UnitTestVariant || - androidExtension is com.android.build.gradle.TestExtension + androidExtension is TestAndroidComponentsExtension || testedVariant != null ) it.crossCompilationRootValidationDisabled.set(!isCrossCompilationRootValidationEnabled()) it.asmApiVersion.set(Opcodes.ASM9) @@ -268,14 +300,13 @@ class HiltGradlePlugin @Inject constructor(private val providers: ProviderFactor } private fun HiltPluginEnvironment.configureJavaCompileTask( - @Suppress("DEPRECATION") variant: com.android.build.gradle.api.BaseVariant, + variant: Component, + testedVariant: Component?, sources: ConfigurableFileCollection, classpath: ConfigurableFileCollection, ): TaskProvider { val hiltAnnotationProcessorConfiguration = configureHiltAnnotationProcessorConfiguration(variant) - val destinationDirectory = - project.buildDir("intermediates/hilt/component_classes/${variant.name}/") return project.tasks.register( "hiltJavaCompile${variant.name.capitalize()}", JavaCompile::class.java, @@ -284,22 +315,18 @@ class HiltGradlePlugin @Inject constructor(private val providers: ProviderFactor // Configure the input classpath based on Java 9 compatibility, specifically for Java 9 the // android.jar is now included in the input classpath instead of the bootstrapClasspath. // See: com/android/build/gradle/tasks/JavaCompileUtils.kt - val mainBootstrapClasspath = - variant.javaCompileProvider.map { it.options.bootstrapClasspath ?: project.files() }.get() + val mainBootstrapClasspath = project.files(androidExtension.sdkComponents.bootClasspath) if (commonExtension.compileOptions.isJava9Compatible()) { compileTask.classpath = classpath.plus(mainBootstrapClasspath) // Copies argument providers from original task, which should contain the JdkImageInput - variant.javaCompileProvider.get().let { originalCompileTask -> - originalCompileTask.options.compilerArgumentProviders - .filter { it is HiltCommandLineArgumentProvider || it is JdkImageInput } - .forEach { compileTask.options.compilerArgumentProviders.add(it) } - } + variant.javaCompilation?.annotationProcessor?.argumentProviders + ?.filter { it is HiltCommandLineArgumentProvider || it is JdkImageInput } + ?.forEach { compileTask.options.compilerArgumentProviders.add(it) } compileTask.options.compilerArgs.add("-XDstringConcat=inline") } else { compileTask.classpath = classpath compileTask.options.bootstrapClasspath = mainBootstrapClasspath } - compileTask.destinationDirectory.set(destinationDirectory) compileTask.options.apply { annotationProcessorPath = hiltAnnotationProcessorConfiguration generatedSourceOutputDirectory.set( @@ -321,14 +348,13 @@ class HiltGradlePlugin @Inject constructor(private val providers: ProviderFactor } private fun HiltPluginEnvironment.configureHiltAnnotationProcessorConfiguration( - @Suppress("DEPRECATION") variant: com.android.build.gradle.api.BaseVariant, + variant: Component, ): Configuration { val configName = "hiltAnnotationProcessor${variant.name.capitalize()}" return project.configurations.create(configName).apply { description = "Hilt annotation processor classpath for '${variant.name}'" isCanBeConsumed = false isCanBeResolved = true - // Add user annotation processor configuration, so that SPI plugins and other processors // are discoverable. val apConfigurations: List = buildList { @@ -462,10 +488,6 @@ private class HiltPluginEnvironment( } } ?: error("Could not find the Android Gradle Plugin (AGP) components extension.") - val legacyAndroidExtension = - project.extensions.findByType(BaseExtension::class.java) - ?: error("Could not find the Android Gradle Plugin (AGP) base extension.") - val commonExtension = project.extensions.findByType(CommonExtension::class.java) ?: error("Could not find the Android Gradle Plugin (AGP) common extension.") diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/task/HiltSyncTask.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/task/HiltSyncTask.kt new file mode 100644 index 00000000000..97d1b4b2674 --- /dev/null +++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/task/HiltSyncTask.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2025 The Dagger Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dagger.hilt.android.plugin.task + +import org.gradle.api.file.Directory +import org.gradle.api.file.RegularFile +import org.gradle.api.provider.ListProperty +import org.gradle.api.tasks.Classpath +import org.gradle.api.tasks.Sync +import org.gradle.work.DisableCachingByDefault + +@DisableCachingByDefault(because = "Not worth caching") +abstract class HiltSyncTask : Sync() { + @get:Classpath + abstract val classesDirectories: ListProperty + + @get:Classpath + abstract val classesJars: ListProperty + + @get:Classpath + abstract val testedClassesDirectories: ListProperty + + @get:Classpath + abstract val testedClassesJars: ListProperty +} \ No newline at end of file diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Configurations.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Configurations.kt index 406946f207a..009e75c0b4e 100644 --- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Configurations.kt +++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Configurations.kt @@ -40,34 +40,3 @@ internal fun getConfigName(variant: Component, prefix: String? = null): String { prefix?.let { "$prefix${name.capitalize()}" } ?: name } } - -@Suppress("DEPRECATION") // Older variant API is deprecated -internal fun getKaptConfigName(variant: com.android.build.gradle.api.BaseVariant) - = getConfigName(variant, "kapt") - -@Suppress("DEPRECATION") // Older variant API is deprecated -internal fun getKspConfigName(variant: com.android.build.gradle.api.BaseVariant) - = getConfigName(variant, "ksp") - -@Suppress("DEPRECATION") // Older variant API is deprecated -internal fun getConfigName( - variant: com.android.build.gradle.api.BaseVariant, - prefix: String? = null, -): String { - // Config names don't follow the usual task name conventions: - // -> - // debug -> Debug - // debugAndroidTest -> AndroidTestDebug - // debugUnitTest -> TestDebug - // release -> Release - // releaseUnitTest -> TestRelease - return when (variant) { - is com.android.build.gradle.api.TestVariant -> - "androidTest${variant.name.substringBeforeLast("AndroidTest").capitalize()}" - is com.android.build.gradle.api.UnitTestVariant -> - "test${variant.name.substringBeforeLast("UnitTest").capitalize()}" - else -> variant.name - }.let { name -> - prefix?.let { "$prefix${name.capitalize()}" } ?: name - } -} \ No newline at end of file diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt index 3846545d41a..5d7b8335143 100644 --- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt +++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt @@ -40,7 +40,7 @@ internal fun addKaptTaskProcessorOptions( project: Project, variantIdentity: ComponentIdentity, produceArgProvider: (Task) -> CommandLineArgumentProvider -) = project.plugins.withId("kotlin-kapt") { +) = project.plugins.withId("com.android.legacy-kapt") { checkClass("org.jetbrains.kotlin.gradle.internal.KaptTask") { """ The KAPT plugin was detected to be applied but its task class could not be found. @@ -135,4 +135,3 @@ private val kspTwoTaskClass = internal fun Task.isKspTask() = kspOneTaskClass?.isAssignableFrom(this::class.java) == true || kspTwoTaskClass?.isAssignableFrom(this::class.java) == true - diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Variants.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Variants.kt index e59eec1607a..0a1b74b6a56 100644 --- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Variants.kt +++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Variants.kt @@ -24,10 +24,6 @@ import com.android.build.api.variant.HasUnitTest import com.android.build.api.variant.LibraryAndroidComponentsExtension import com.android.build.api.variant.TestAndroidComponentsExtension import com.android.build.api.variant.Variant -import com.android.build.gradle.AppExtension -import com.android.build.gradle.BaseExtension -import com.android.build.gradle.LibraryExtension -import com.android.build.gradle.TestExtension /** * Invokes the [block] function for each Android variant that is considered a Hilt root, where @@ -74,31 +70,3 @@ internal fun AndroidComponentsExtension<*, *, *>.onTestVariants( (variant as? HasAndroidTest)?.androidTest?.let { block(it, variant) } } } - -/** - * Invokes the [block] function for each Android variant that is considered a Hilt root, where - * dependencies are aggregated and components are generated. - */ -internal fun BaseExtension.forEachRootVariant( - @Suppress("DEPRECATION") block: (variant: com.android.build.gradle.api.BaseVariant) -> Unit -) { - when (this) { - is AppExtension -> { - // For an app project we configure the app variant and both androidTest and unitTest - // variants, Hilt components are generated in all of them. - applicationVariants.all { block(it) } - testVariants.all { block(it) } - unitTestVariants.all { block(it) } - } - is LibraryExtension -> { - // For a library project, only the androidTest and unitTest variant are configured since - // Hilt components are not generated in a library. - testVariants.all { block(it) } - unitTestVariants.all { block(it) } - } - is TestExtension -> { - applicationVariants.all { block(it) } - } - else -> error("Hilt plugin does not know how to configure '$this'") - } -} diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt index dd07e0ca32d..6930848d72a 100644 --- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt +++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt @@ -82,6 +82,11 @@ class AGPCompatibilityTest(private val agpVersion: String, private val gradleVer companion object { @JvmStatic @Parameterized.Parameters(name = "agpVersion = {0}, gradleVersion = {1}") - fun parameters() = listOf(arrayOf(/* agpVersion = */ "8.13.0", /* gradleVersion = */ "9.2.0")) + fun parameters() = listOf( + arrayOf( + /* agpVersion = */ "9.0.0-beta04", + /* gradleVersion = */ "9.2.0" + ) + ) } } diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt index a786920d9e7..4b0423657f9 100644 --- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt +++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt @@ -87,7 +87,7 @@ class BuildCacheTest(private val enableAggregatingTask: Boolean) { add(":compressDebugAssets") add(":desugarDebugFileDependencies") add(":extractDeepLinksDebug") - add(":generateDebugResValues") + add(":generateDebugRFile") add(":generateDebugResources") // When aggregating task is enabled, the plugin adds two more tasks that should be // cacheable. diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt index 1966ec81670..1149ecbce28 100644 --- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt +++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt @@ -144,7 +144,8 @@ class GradleTestRunner(val tempFolder: TemporaryFolder) { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.13.0' + classpath 'com.android.tools.build:gradle:$AGP_VERSION' + classpath 'com.android.legacy-kapt:com.android.legacy-kapt.gradle.plugin:$AGP_VERSION' ${pluginClasspaths.joinToString(separator = "\n") { "classpath '$it'" }} } } @@ -183,13 +184,14 @@ class GradleTestRunner(val tempFolder: TemporaryFolder) { } dependencies { - implementation(platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')) + implementation(platform('org.jetbrains.kotlin:kotlin-bom:2.2.0')) ${dependencies.joinToString(separator = "\n")} } hilt { ${hiltOptions.joinToString(separator = "\n")} } + ${additionalClosures.joinToString(separator = "\n")} """ .trimIndent() @@ -264,4 +266,8 @@ class GradleTestRunner(val tempFolder: TemporaryFolder) { } } } + + companion object { + const val AGP_VERSION = "9.0.0-beta04" + } } diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt index 62e41eb3e59..43031111f80 100644 --- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt +++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt @@ -221,7 +221,7 @@ class IncrementalProcessorTest(private val incapMode: String) { "build/intermediates/javac/debugUnitTest/compileDebugUnitTestJavaWithJavac/classes" fun getRootClassesDir(variant: String) = if (incapMode == ISOLATING_MODE) { - "build/intermediates/hilt/component_classes/$variant/" + "build/intermediates/classes/$variant/hiltJavaCompile${variant.capitalize()}/" } else { "build/intermediates/javac/$variant/compile${variant.capitalize()}JavaWithJavac/classes" } diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/SPIPluginTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/SPIPluginTest.kt index 963d262f0a0..faf62c3a731 100644 --- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/SPIPluginTest.kt +++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/SPIPluginTest.kt @@ -49,9 +49,8 @@ class SPIPluginTest(val backend: Backend) { Backend.KSP -> "ksp" } if (backend == Backend.KAPT || backend == Backend.KSP) { - gradleRunner.addPluginId("kotlin-android") if (backend == Backend.KAPT) { - gradleRunner.addPluginId("kotlin-kapt") + gradleRunner.addPluginId("com.android.legacy-kapt") } else { gradleRunner.addPluginId("com.google.devtools.ksp") } diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/TransformTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/TransformTest.kt index d45dc3ec4ad..f69b47bacac 100644 --- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/TransformTest.kt +++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/TransformTest.kt @@ -26,9 +26,11 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import org.junit.runners.Parameterized -class TransformTest { - +@RunWith(Parameterized::class) +class TransformTest(val backend: Backend) { @get:Rule val testProjectDir = TemporaryFolder() @@ -36,11 +38,11 @@ class TransformTest { @Before fun setup() { - gradleRunner = GradleTestRunner(testProjectDir) - gradleRunner.addSrc( - srcPath = "minimal/MainActivity.java", - srcContent = - """ + gradleRunner = GradleTestRunner(testProjectDir).apply { + addSrc( + srcPath = "minimal/MainActivity.java", + srcContent = + """ package minimal; import android.os.Bundle; @@ -54,21 +56,30 @@ class TransformTest { } } """.trimIndent() - ) + ) + addDependencies( + "implementation 'androidx.appcompat:appcompat:1.1.0'", + "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", + ) + when (backend) { + Backend.JAVAC -> { + addDependencies("annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'") + } + Backend.KAPT -> { + addPluginId("com.android.legacy-kapt") + addDependencies("kapt 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'") + } + Backend.KSP -> { + addPluginId("com.google.devtools.ksp") + addDependencies("ksp 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'") + } + } + } } // Simple functional test to verify transformation. @Test fun testAssemble() { - gradleRunner.addDependencies( - "implementation 'androidx.appcompat:appcompat:1.1.0'", - "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", - "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'" - ) - gradleRunner.addActivities( - "" - ) - val result = gradleRunner.build() val assembleTask = result.getTask(":assembleDebug") Assert.assertEquals(TaskOutcome.SUCCESS, assembleTask.outcome) @@ -98,12 +109,6 @@ class TransformTest { // Verify correct transformation is done on nested classes. @Test fun testAssemble_nestedClass() { - gradleRunner.addDependencies( - "implementation 'androidx.appcompat:appcompat:1.1.0'", - "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", - "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'" - ) - gradleRunner.addSrc( srcPath = "minimal/TopClass.java", srcContent = @@ -134,12 +139,6 @@ class TransformTest { // Verify transformation ignores abstract methods. @Test fun testAssemble_abstractMethod() { - gradleRunner.addDependencies( - "implementation 'androidx.appcompat:appcompat:1.1.0'", - "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", - "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'" - ) - gradleRunner.addSrc( srcPath = "minimal/AbstractActivity.java", srcContent = @@ -170,12 +169,6 @@ class TransformTest { // Verify transformation ignores native methods. @Test fun testAssemble_nativeMethod() { - gradleRunner.addDependencies( - "implementation 'androidx.appcompat:appcompat:1.1.0'", - "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", - "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'" - ) - gradleRunner.addSrc( srcPath = "minimal/SimpleActivity.java", srcContent = @@ -206,12 +199,6 @@ class TransformTest { // Verifies the transformation is applied incrementally when a class to be transformed is updated. @Test fun testTransform_incrementalClass() { - gradleRunner.addDependencies( - "implementation 'androidx.appcompat:appcompat:1.1.0'", - "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", - "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'" - ) - val srcFile = gradleRunner.addSrc( srcPath = "minimal/OtherActivity.java", srcContent = @@ -269,12 +256,6 @@ class TransformTest { // directory. @Test fun testTransform_incrementalDir() { - gradleRunner.addDependencies( - "implementation 'androidx.appcompat:appcompat:1.1.0'", - "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", - "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'" - ) - gradleRunner.addSrcPackage("ui/") gradleRunner.build().let { @@ -312,12 +293,6 @@ class TransformTest { // See: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.9 @Test fun testTransform_genericSuperclass() { - gradleRunner.addDependencies( - "implementation 'androidx.appcompat:appcompat:1.1.0'", - "implementation 'com.google.dagger:hilt-android:LOCAL-SNAPSHOT'", - "annotationProcessor 'com.google.dagger:hilt-compiler:LOCAL-SNAPSHOT'" - ) - gradleRunner.addSrc( srcPath = "minimal/BaseActivity.java", srcContent = @@ -395,7 +370,14 @@ class TransformTest { } companion object { - const val TRANSFORM_TASK_NAME = - ":transformDebugClassesWithAsm" + const val TRANSFORM_TASK_NAME = ":transformDebugClassesWithAsm" + + @JvmStatic + @Parameterized.Parameters(name = "backend = {0}") + fun params() = listOf(Backend.JAVAC, Backend.KAPT, Backend.KSP) + + enum class Backend { + JAVAC, KAPT, KSP + } } } diff --git a/javatests/artifacts/dagger-android-ksp/app/build.gradle b/javatests/artifacts/dagger-android-ksp/app/build.gradle index 626487cf442..8fd22f271e5 100644 --- a/javatests/artifacts/dagger-android-ksp/app/build.gradle +++ b/javatests/artifacts/dagger-android-ksp/app/build.gradle @@ -16,7 +16,6 @@ plugins { id 'com.android.application' - id 'org.jetbrains.kotlin.android' id 'com.google.devtools.ksp' } diff --git a/javatests/artifacts/dagger-android/simple/build.gradle b/javatests/artifacts/dagger-android/simple/build.gradle index 558426d4b1f..bf52aa2ef6d 100644 --- a/javatests/artifacts/dagger-android/simple/build.gradle +++ b/javatests/artifacts/dagger-android/simple/build.gradle @@ -47,6 +47,3 @@ allprojects { } } } - -// Instrumentation tests: Combines test reports for all modules -apply plugin: 'android-reporting' diff --git a/javatests/artifacts/hilt-android/lazyclasskey/build.gradle b/javatests/artifacts/hilt-android/lazyclasskey/build.gradle index 0654387c9e6..59aa43d54e5 100644 --- a/javatests/artifacts/hilt-android/lazyclasskey/build.gradle +++ b/javatests/artifacts/hilt-android/lazyclasskey/build.gradle @@ -28,7 +28,7 @@ buildscript { dependencies { classpath "com.android.tools.build:gradle:$agp_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" + classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" } } diff --git a/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle b/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle index 633bb5eb1be..258d6792776 100644 --- a/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle +++ b/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle @@ -15,7 +15,7 @@ */ plugins { - id 'com.android.application' version '8.4.2' + id 'com.android.application' version '9.0.0-beta04' id 'com.google.dagger.hilt.android' version 'LOCAL-SNAPSHOT' } diff --git a/javatests/artifacts/hilt-android/simple/app/build.gradle b/javatests/artifacts/hilt-android/simple/app/build.gradle deleted file mode 100644 index db9782c8a2d..00000000000 --- a/javatests/artifacts/hilt-android/simple/app/build.gradle +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2020 The Dagger Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import org.gradle.util.GradleVersion - -apply plugin: 'com.android.application' -apply plugin: 'com.google.dagger.hilt.android' - -// Gets additional test directories to be added to test and androidTest source -// sets. If the directory name is appended with '-agp-x.x.x' then the directory -// is conditionally added based on the AGP version of the project. -def getAdditionalTestDirs(String variant) { - def testDirs = [ - 'androidTest': [], - 'sharedTest': ['src/sharedTest/java'], - 'test': [] - ] - def suffix = '-agp-' - def agpVersion = GradleVersion.version(agp_version) - file("${getProjectDir().absolutePath}/src").eachFile { file -> - int indexOf = file.name.indexOf(suffix) - if (file.isDirectory() && indexOf != -1) { - def dirAgpVersion = - GradleVersion.version(file.name.substring(indexOf + suffix.length())) - if (agpVersion >= dirAgpVersion) { - testDirs[file.name.substring(0, indexOf)].add("src/${file.name}/java") - } - } - } - return testDirs[variant] + testDirs['sharedTest'] -} - -android { - compileSdkVersion 36 - buildToolsVersion "36.0.0" - - defaultConfig { - applicationId "dagger.hilt.android.simple" - minSdkVersion 16 - targetSdkVersion 36 - versionCode 1 - versionName "1.0" - testInstrumentationRunner "dagger.hilt.android.simple.SimpleEmulatorTestRunner" - } - namespace "dagger.hilt.android.simple" - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - testOptions { - unitTests.includeAndroidResources = true - } - lintOptions { - checkReleaseBuilds = false - } - sourceSets { - test { - java.srcDirs += getAdditionalTestDirs("test") - } - androidTest { - java.srcDirs += getAdditionalTestDirs("androidTest") - } - } - flavorDimensions "tier" - productFlavors { - free { - dimension "tier" - } - pro { - dimension "tier" - matchingFallbacks = ["free"] - } - } -} - -hilt { - enableTransformForLocalTests = true - enableAggregatingTask = true -} - -configurations.all { - resolutionStrategy.eachDependency { DependencyResolveDetails details -> - if ("$dagger_version" == 'LOCAL-SNAPSHOT' - && details.requested.group == 'com.google.dagger') { - details.useVersion 'LOCAL-SNAPSHOT' - details.because 'LOCAL-SNAPSHOT should act as latest version.' - } - } -} - -dependencies { - implementation project(':feature') - implementation project(':lib') - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation "com.google.dagger:hilt-android:$dagger_version" - annotationProcessor "com.google.dagger:hilt-compiler:$dagger_version" - - testImplementation 'com.google.truth:truth:1.0.1' - testImplementation 'junit:junit:4.13' - testImplementation 'org.robolectric:robolectric:4.11.1' - testImplementation 'androidx.core:core:1.3.2' - testImplementation 'androidx.test.ext:junit:1.1.3' - testImplementation 'androidx.test:runner:1.4.0' - testImplementation 'androidx.test.espresso:espresso-core:3.5.1' - testImplementation "com.google.dagger:hilt-android-testing:$dagger_version" - testAnnotationProcessor "com.google.dagger:hilt-compiler:$dagger_version" - - androidTestImplementation 'com.google.truth:truth:1.0.1' - androidTestImplementation 'junit:junit:4.13' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' - androidTestImplementation "com.google.dagger:hilt-android-testing:$dagger_version" - androidTestAnnotationProcessor "com.google.dagger:hilt-compiler:$dagger_version" - - // To help us catch usages of Guava APIs for Java 8 in the '-jre' variant. - annotationProcessor'com.google.guava:guava:28.1-android' - testAnnotationProcessor'com.google.guava:guava:28.1-android' - androidTestAnnotationProcessor'com.google.guava:guava:28.1-android' - - // To help us catch version skew related issues in hilt extensions. - // TODO(bcorso): Add examples testing the actual API. - implementation 'androidx.hilt:hilt-work:1.0.0' - annotationProcessor 'androidx.hilt:hilt-compiler:1.0.0' - testAnnotationProcessor 'androidx.hilt:hilt-compiler:1.0.0' - androidTestAnnotationProcessor 'androidx.hilt:hilt-compiler:1.0.0' -} diff --git a/javatests/artifacts/hilt-android/simple/app/build.gradle.kts b/javatests/artifacts/hilt-android/simple/app/build.gradle.kts new file mode 100644 index 00000000000..94c26f78374 --- /dev/null +++ b/javatests/artifacts/hilt-android/simple/app/build.gradle.kts @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2020 The Dagger Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.File + +plugins { + id("com.android.application") + id("com.google.dagger.hilt.android") +} + +data class AgpVersion( + val major: Int, + val minor: Int, + val patch: Int, + val qualifierName: String?, + val qualifierVersion: Int?, +): Comparable { + override fun compareTo(other: AgpVersion): Int { + val versionComparison = compareValuesBy(this, other, { it.major }, { it.minor }, { it.patch }) + return if (versionComparison != 0) { + versionComparison + } else { + // If the versions are equal then compare qualifiers: + when { + qualifierName == null && other.qualifierName == null -> 0 + qualifierName == null && other.qualifierName != null -> -1 + qualifierName != null && other.qualifierName == null -> 1 + else -> compareValuesBy( + this, other, + { it.qualifierName!! }, + { it.qualifierVersion!! }, + ) + } + } + } + + companion object { + val VERSION_REGEX = Regex( + "(?\\d+)\\.(?\\d+)\\.(?\\d+)" + + "(?:-(?[a-zA-Z]+)(?\\d+))?" + ) + + fun parse(versionStr: String): AgpVersion { + return VERSION_REGEX.matchEntire(versionStr)?.let { match -> + AgpVersion( + major = match.groups["major"]!!.value.toInt(), + minor = match.groups["minor"]!!.value.toInt(), + patch = match.groups["patch"]!!.value.toInt(), + qualifierName = match.groups["qualifierName"]?.value, + qualifierVersion = match.groups["qualifierVersion"]?.value?.toInt() + ) + } ?: error("Version string has incorrect format: $versionStr") + } + } +} + +// Gets additional test directories to be added to test and androidTest source +// sets. If the directory name is appended with '-agp-x.x.x' then the directory +// is conditionally added based on the AGP version of the project. +fun getAdditionalTestDirs(variant: String): List { + val testDirs = mutableMapOf( + "androidTest" to mutableListOf(), + "sharedTest" to mutableListOf("src/sharedTest/java"), + "test" to mutableListOf() + ) + val suffix = "-agp-" + + val agpVersionString = properties["agp_version"] as String + val agpVersion = AgpVersion.parse(agpVersionString) + + File("${project.projectDir.absolutePath}/src").listFiles()?.forEach { file -> + if (file.isDirectory) { + val indexOf = file.name.indexOf(suffix) + if (indexOf != -1) { + try { + val dirAgpVersionStr = file.name.substring(indexOf + suffix.length) + val dirAgpVersion = AgpVersion.parse(dirAgpVersionStr) + if (agpVersion >= dirAgpVersion) { + val dirName = file.name.substring(0, indexOf) + testDirs[dirName]?.add("src/${file.name}/java") + } + } catch (e: IllegalArgumentException) { + // Handle cases where the version string is not valid + println("Warning: Could not parse version from directory name: ${file.name}") + } + } + } + } + return (testDirs[variant] ?: emptyList()) + (testDirs["sharedTest"] ?: emptyList()) +} + +android { + compileSdk = 36 + buildToolsVersion = "36.0.0" + + defaultConfig { + applicationId = "dagger.hilt.android.simple" + minSdk = 16 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + testInstrumentationRunner = "dagger.hilt.android.simple.SimpleEmulatorTestRunner" + } + namespace = "dagger.hilt.android.simple" + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + testOptions { + unitTests.isIncludeAndroidResources = true + } + lint { + checkReleaseBuilds = false + } + sourceSets { + named("test").map { + it.java.directories.addAll(getAdditionalTestDirs("test")) + } + named("androidTest").map { + it.java.directories.addAll(getAdditionalTestDirs("androidTest")) + } + } + flavorDimensions += "tier" + productFlavors { + create("free") { + dimension = "tier" + } + create("pro") { + dimension = "tier" + matchingFallbacks += "free" + } + } +} + +hilt { + enableAggregatingTask = true +} + +val dagger_version: String by project + +configurations.all { + resolutionStrategy.eachDependency { + if (dagger_version == "LOCAL-SNAPSHOT" && requested.group == "com.google.dagger") { + useVersion("LOCAL-SNAPSHOT") + because("LOCAL-SNAPSHOT should act as latest version.") + } + } +} + +dependencies { + implementation(project(":feature")) + implementation(project(":lib")) + implementation("androidx.appcompat:appcompat:1.2.0") + implementation("com.google.dagger:hilt-android:$dagger_version") + annotationProcessor("com.google.dagger:hilt-compiler:$dagger_version") + + testImplementation("com.google.truth:truth:1.0.1") + testImplementation("junit:junit:4.13") + testImplementation("org.robolectric:robolectric:4.11.1") + testImplementation("androidx.core:core:1.3.2") + testImplementation("androidx.test.ext:junit:1.1.3") + testImplementation("androidx.test:runner:1.4.0") + testImplementation("androidx.test.espresso:espresso-core:3.5.1") + testImplementation("com.google.dagger:hilt-android-testing:$dagger_version") + testAnnotationProcessor("com.google.dagger:hilt-compiler:$dagger_version") + + androidTestImplementation("com.google.truth:truth:1.0.1") + androidTestImplementation("junit:junit:4.13") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test:runner:1.4.0") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + androidTestImplementation("com.google.dagger:hilt-android-testing:$dagger_version") + androidTestAnnotationProcessor("com.google.dagger:hilt-compiler:$dagger_version") + + // To help us catch usages of Guava APIs for Java 8 in the '-jre' variant. + annotationProcessor("com.google.guava:guava:28.1-android") + testAnnotationProcessor("com.google.guava:guava:28.1-android") + androidTestAnnotationProcessor("com.google.guava:guava:28.1-android") + + // To help us catch version skew related issues in hilt extensions. + // TODO(bcorso): Add examples testing the actual API. + implementation("androidx.hilt:hilt-work:1.0.0") + annotationProcessor("androidx.hilt:hilt-compiler:1.0.0") + testAnnotationProcessor("androidx.hilt:hilt-compiler:1.0.0") + androidTestAnnotationProcessor("androidx.hilt:hilt-compiler:1.0.0") +} diff --git a/javatests/artifacts/hilt-android/simple/build.gradle b/javatests/artifacts/hilt-android/simple/build.gradle index a57ed70e78f..ecc258a017f 100644 --- a/javatests/artifacts/hilt-android/simple/build.gradle +++ b/javatests/artifacts/hilt-android/simple/build.gradle @@ -27,7 +27,7 @@ buildscript { } dependencies { classpath "com.android.tools.build:gradle:$agp_version" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "com.android.legacy-kapt:com.android.legacy-kapt.gradle.plugin:$agp_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$dagger_version" } } @@ -64,6 +64,3 @@ subprojects { } } } - -// Instrumentation tests: Combines test reports for all modules -apply plugin: 'android-reporting' diff --git a/javatests/artifacts/hilt-android/simple/feature/build.gradle b/javatests/artifacts/hilt-android/simple/feature/build.gradle index cb268048d7b..ccdfe83f91e 100644 --- a/javatests/artifacts/hilt-android/simple/feature/build.gradle +++ b/javatests/artifacts/hilt-android/simple/feature/build.gradle @@ -15,8 +15,7 @@ */ apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' +apply plugin: 'com.android.legacy-kapt' apply plugin: 'com.google.dagger.hilt.android' android { diff --git a/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle index d5320b91ba5..450cfc931f7 100644 --- a/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle +++ b/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle @@ -1,7 +1,6 @@ plugins { id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' + id 'com.android.legacy-kapt' id 'com.google.devtools.ksp' } @@ -20,9 +19,6 @@ android { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } - kotlinOptions { - jvmTarget = '11' - } flavorDimensions "tier", "processorConfig" productFlavors { free { diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle index ff8091d35be..d1ea5f8e860 100644 --- a/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle +++ b/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle @@ -15,9 +15,8 @@ */ apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' apply plugin: 'com.google.dagger.hilt.android' -apply plugin: 'kotlin-kapt' +apply plugin: 'com.android.legacy-kapt' apply plugin: 'com.google.devtools.ksp' android { diff --git a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/build.gradle index 7e055faf9f8..e02ac019833 100644 --- a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle +++ b/javatests/artifacts/hilt-android/simpleKotlin/build.gradle @@ -27,6 +27,7 @@ buildscript { } dependencies { classpath "com.android.tools.build:gradle:$agp_version" + classpath "com.android.legacy-kapt:com.android.legacy-kapt.gradle.plugin:$agp_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp_version" classpath 'com.google.dagger:hilt-android-gradle-plugin:LOCAL-SNAPSHOT' diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle index 2db3a9344c7..b4b8ada9309 100644 --- a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle +++ b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle @@ -1,7 +1,6 @@ plugins { id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' + id 'com.android.legacy-kapt' id 'com.google.devtools.ksp' id 'com.google.dagger.hilt.android' } @@ -23,9 +22,6 @@ android { sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 } - kotlinOptions { - jvmTarget = '11' - } lintOptions { checkReleaseBuilds = false } diff --git a/util/deploy-hilt-gradle-plugin.sh b/util/deploy-hilt-gradle-plugin.sh index 3e16f4bbe8e..9bfef0c1afd 100755 --- a/util/deploy-hilt-gradle-plugin.sh +++ b/util/deploy-hilt-gradle-plugin.sh @@ -10,7 +10,7 @@ readonly EXTRA_MAVEN_ARGS=("$@") # Builds and deploy the Gradle plugin. _deploy_plugin() { local plugindir=java/dagger/hilt/android/plugin - AGP_VERSION="8.13.0" ./$plugindir/gradlew -p $plugindir --no-daemon clean \ + AGP_VERSION="9.0.0-beta04" ./$plugindir/gradlew -p $plugindir --no-daemon clean \ publishAllPublicationsToMavenRepository -PPublishVersion="$VERSION_NAME" local outdir=$plugindir/main/buildOut/repo/com/google/dagger/hilt-android-gradle-plugin/$VERSION_NAME local markerOutDir=$plugindir/main/buildOut/repo/com/google/dagger/hilt/android/com.google.dagger.hilt.android.gradle.plugin/$VERSION_NAME