ErrorProneAgpPlugin.kt

 1package dev.mboa.errorprone
 2
 3import com.android.build.api.variant.AndroidComponentsExtension
 4import org.gradle.api.Plugin
 5import org.gradle.api.Project
 6import org.gradle.api.tasks.compile.JavaCompile
 7import org.gradle.process.CommandLineArgumentProvider
 8
 9class ErrorProneAgpPlugin : Plugin<Project> {
10    override fun apply(project: Project) {
11        val errorproneConfiguration = project.configurations.create("errorprone").apply {
12            isVisible = false
13            isCanBeConsumed = false
14            isCanBeResolved = true
15            description = "ErrorProne dependencies for static analysis"
16        }
17
18        // Wait for the Android plugin to be applied before accessing its extensions
19        project.pluginManager.withPlugin("com.android.application") {
20            configureErrorProne(project, errorproneConfiguration)
21        }
22
23        project.pluginManager.withPlugin("com.android.library") {
24            configureErrorProne(project, errorproneConfiguration)
25        }
26    }
27
28    private fun configureErrorProne(project: Project, errorproneConfiguration: org.gradle.api.artifacts.Configuration) {
29        val androidComponents = project.extensions.getByType(AndroidComponentsExtension::class.java)
30
31        androidComponents.onVariants { variant ->
32            // Use afterEvaluate to ensure we configure after AGP/databinding have set up their annotation processors
33            project.afterEvaluate {
34                project.tasks.withType(JavaCompile::class.java).configureEach {
35                    if (name.contains(variant.name, ignoreCase = true)) {
36                    // Add ErrorProne to the annotation processor path
37                    // This makes it available to the compiler as a plugin
38                    val currentPath = options.annotationProcessorPath ?: project.files()
39                    options.annotationProcessorPath = currentPath.plus(errorproneConfiguration)
40
41                    val isTestVariant = variant.name.contains("test", ignoreCase = true) ||
42                        variant.name.contains("androidTest", ignoreCase = true)
43
44                    options.compilerArgumentProviders.add(CommandLineArgumentProvider {
45                        val args = mutableListOf(
46                            "-XDcompilePolicy=simple",  // Required by ErrorProne
47                            "-XDshould-stop.ifError=FLOW",  // Required by ErrorProne
48                            "-Xplugin:ErrorProne"
49                        )
50                        if (isTestVariant) {
51                            args.add("-XepCompilingTestOnlyCode")
52                        }
53                        args
54                    })
55
56                    // ErrorProne requires access to internal JDK compiler APIs
57                    // Enable forking and add required JVM arguments
58                    options.isFork = true
59                    options.forkOptions.jvmArgs = options.forkOptions.jvmArgs ?: mutableListOf()
60                    (options.forkOptions.jvmArgs as MutableList).addAll(listOf(
61                        "--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
62                        "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
63                        "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
64                        "--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
65                        "--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
66                        "--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
67                        "--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
68                        "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
69                        "--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
70                        "--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED"
71                    ))
72                    }
73                }
74            }
75        }
76    }
77}