xref: /aosp_15_r20/external/dagger2/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
<lambda>null2  * Copyright (C) 2023 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.hilt.android.plugin.util
18 
19 import com.google.devtools.ksp.gradle.KspTaskJvm
20 import org.gradle.api.Project
21 import org.gradle.api.Task
22 import org.gradle.api.tasks.compile.JavaCompile
23 import org.gradle.process.CommandLineArgumentProvider
24 import org.jetbrains.kotlin.gradle.internal.KaptTask
25 
26 internal fun addJavaTaskProcessorOptions(
27   project: Project,
28   component: ComponentCompat,
29   produceArgProvider: (Task) -> CommandLineArgumentProvider
30 ) = project.tasks.withType(JavaCompile::class.java) { task ->
31   if (task.name == "compile${component.name.capitalize()}JavaWithJavac") {
32     task.options.compilerArgumentProviders.add(produceArgProvider.invoke(task))
33   }
34 }
35 
addKaptTaskProcessorOptionsnull36 internal fun addKaptTaskProcessorOptions(
37   project: Project,
38   component: ComponentCompat,
39   produceArgProvider: (Task) -> CommandLineArgumentProvider
40 ) = project.plugins.withId("kotlin-kapt") {
41   checkClass("org.jetbrains.kotlin.gradle.internal.KaptTask") {
42     """
43     The KAPT plugin was detected to be applied but its task class could not be found.
44 
45     This is an indicator that the Hilt Gradle Plugin is using a different class loader because
46     it was declared at the root while KAPT was declared in a sub-project. To fix this, declare
47     both plugins in the same scope, i.e. either at the root (without applying them) or at the
48     sub-projects.
49     """.trimIndent()
50   }
51   project.tasks.withType(KaptTask::class.java) { task ->
52     if (task.name == "kapt${component.name.capitalize()}Kotlin" ||
53         // Task names in shared/src/AndroidMain in KMP projects has a platform suffix.
54         task.name == "kapt${component.name.capitalize()}KotlinAndroid") {
55       val argProvider = produceArgProvider.invoke(task)
56       // TODO: Update once KT-58009 is fixed.
57       try {
58         // Because of KT-58009, we need to add a `listOf(argProvider)` instead
59         // of `argProvider`.
60         task.annotationProcessorOptionProviders.add(listOf(argProvider))
61       } catch (e: Throwable) {
62         // Once KT-58009 is fixed, adding `listOf(argProvider)` will fail, we will
63         // pass `argProvider` instead, which is the correct way.
64         task.annotationProcessorOptionProviders.add(argProvider)
65       }
66     }
67   }
68 }
69 
addKspTaskProcessorOptionsnull70 internal fun addKspTaskProcessorOptions(
71   project: Project,
72   component: ComponentCompat,
73   produceArgProvider: (Task) -> CommandLineArgumentProvider
74 ) = project.plugins.withId("com.google.devtools.ksp") {
75   checkClass("com.google.devtools.ksp.gradle.KspTaskJvm") {
76     """
77     The KSP plugin was detected to be applied but its task class could not be found.
78 
79     This is an indicator that the Hilt Gradle Plugin is using a different class loader because
80     it was declared at the root while KSP was declared in a sub-project. To fix this, declare
81     both plugins in the same scope, i.e. either at the root (without applying them) or at the
82     sub-projects.
83 
84     See https://github.com/google/dagger/issues/3965 for more details.
85     """.trimIndent()
86   }
87   project.tasks.withType(KspTaskJvm::class.java) { task ->
88     if (task.name == "ksp${component.name.capitalize()}Kotlin" ||
89         // Task names in shared/src/AndroidMain in KMP projects has a platform suffix.
90         task.name == "ksp${component.name.capitalize()}KotlinAndroid") {
91       task.commandLineArgumentProviders.add(produceArgProvider.invoke(task))
92     }
93   }
94 }
95 
checkClassnull96 private inline fun checkClass(fqn: String, msg: () -> String) {
97   try {
98     Class.forName(fqn)
99   } catch (ex: ClassNotFoundException) {
100     throw IllegalStateException(msg.invoke(), ex)
101   }
102 }
103 
isKspTasknull104 internal fun Task.isKspTask(): Boolean = try {
105   val kspTaskClass = Class.forName("com.google.devtools.ksp.gradle.KspTask")
106   kspTaskClass.isAssignableFrom(this::class.java)
107 } catch (ex: ClassNotFoundException) {
108   false
109 }
110 
111