Skip to content

Commit

Permalink
Use jvmArgumentProviders in Gradle 7.1+
Browse files Browse the repository at this point in the history
The only missing lazily-configurable piece that still
mandates the use of a doFirst{} block is options.isFork:
gradle/gradle#12546
  • Loading branch information
tbroyer committed Oct 10, 2022
1 parent aa83154 commit ffef94d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 30 deletions.
75 changes: 47 additions & 28 deletions src/main/kotlin/net/ltgt/gradle/errorprone/ErrorPronePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.ClasspathNormalizer
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import org.gradle.api.tasks.Optional
Expand All @@ -40,6 +42,8 @@ class ErrorPronePlugin : Plugin<Project> {

internal const val TOO_OLD_TOOLCHAIN_ERROR_MESSAGE = "Must not enable ErrorProne when compiling with JDK < 8"

private val HAS_JVM_ARGUMENT_PROVIDERS = GradleVersion.current() >= GradleVersion.version("7.1")

internal val JVM_ARGS_STRONG_ENCAPSULATION = listOf(
"--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
"--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
Expand Down Expand Up @@ -78,10 +82,6 @@ class ErrorPronePlugin : Plugin<Project> {
}
}

fun JavaCompile.configureErrorProneJavac() {
options.forkOptions.jvmArgs!!.add("-Xbootclasspath/p:${javacConfiguration.asPath}")
}

val providers = project.providers
project.tasks.withType<JavaCompile>().configureEach {
val errorproneOptions =
Expand All @@ -90,25 +90,25 @@ class ErrorPronePlugin : Plugin<Project> {
.compilerArgumentProviders
.add(ErrorProneCompilerArgumentProvider(errorproneOptions))

inputs.files(
providers.provider {
when {
!errorproneOptions.isEnabled.getOrElse(false) -> emptyList()
compilerVersion == JavaVersion.VERSION_1_8 -> javacConfiguration
else -> emptyList()
}
val jvmArgumentProvider = ErrorProneJvmArgumentProvider(this, errorproneOptions, javacConfiguration)
if (HAS_JVM_ARGUMENT_PROVIDERS) {
options.forkOptions.jvmArgumentProviders.add(jvmArgumentProvider)
} else {
inputs.property("errorprone.compilerVersion", providers.provider { jvmArgumentProvider.compilerVersion })
.optional(true)
inputs.files(providers.provider { jvmArgumentProvider.bootstrapClasspath })
.withPropertyName("errorprone.bootstrapClasspath")
.withNormalizer(ClasspathNormalizer::class)
.optional()
doFirst("Configure JVM arguments for errorprone") {
options.forkOptions.jvmArgs!!.addAll(jvmArgumentProvider.asArguments())
}
).withPropertyName(JAVAC_CONFIGURATION_NAME).withNormalizer(ClasspathNormalizer::class)
doFirst("configure JVM arguments and forking for errorprone") {
}
doFirst("Configure forking for errorprone") {
if (!errorproneOptions.isEnabled.getOrElse(false)) return@doFirst
compilerVersion?.let {
jvmArgumentProvider.compilerVersion?.let {
if (it < JavaVersion.VERSION_1_8) throw UnsupportedOperationException(TOO_OLD_TOOLCHAIN_ERROR_MESSAGE)
if (it.needsForking) options.isFork = true
if (it == JavaVersion.VERSION_1_8) {
configureErrorProneJavac()
} else {
configureForJava9plus()
}
if (it == JavaVersion.VERSION_1_8 || it >= JavaVersion.VERSION_16) options.isFork = true
}
}
}
Expand Down Expand Up @@ -149,18 +149,37 @@ class ErrorPronePlugin : Plugin<Project> {
}
}
}
}

private val JavaCompile.compilerVersion get() =
javaCompiler
internal class ErrorProneJvmArgumentProvider(
private val task: JavaCompile,
private val errorproneOptions: ErrorProneOptions,
private val javacConfiguration: FileCollection
) : CommandLineArgumentProvider, Named {

@Internal override fun getName(): String = "errorprone"

@get:Input
@get:Optional
val compilerVersion by lazy {
task.javaCompiler
.map { JavaVersion.toVersion(it.metadata.languageVersion.asInt()) }
.orNull ?: if (options.isCommandLine) null else JavaVersion.current()
.orNull ?: if (task.options.isCommandLine) null else JavaVersion.current()
}

private val JavaVersion.needsForking get() =
this == JavaVersion.VERSION_1_8 || this >= JavaVersion.VERSION_16
@get:Classpath
@get:Optional
val bootstrapClasspath get() = javacConfiguration.takeIf {
errorproneOptions.isEnabled.getOrElse(false) &&
compilerVersion == JavaVersion.VERSION_1_8
}

private fun JavaCompile.configureForJava9plus() {
// https://errorprone.info/docs/installation#java-9-and-newer
options.forkOptions.jvmArgs!!.addAll(JVM_ARGS_STRONG_ENCAPSULATION)
override fun asArguments(): Iterable<String> = when {
!errorproneOptions.isEnabled.getOrElse(false) -> emptyList()
compilerVersion == null -> emptyList()
compilerVersion == JavaVersion.VERSION_1_8 -> listOf("-Xbootclasspath/p:${javacConfiguration.asPath}")
compilerVersion!! > JavaVersion.VERSION_1_8 -> ErrorPronePlugin.JVM_ARGS_STRONG_ENCAPSULATION
else -> emptyList()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.google.common.truth.Truth.assertThat
import com.google.common.truth.TruthJUnit.assume
import org.gradle.api.JavaVersion
import org.gradle.testkit.runner.TaskOutcome
import org.gradle.util.GradleVersion
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.io.File
Expand All @@ -21,6 +22,8 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
private val JVM_ARGS_STRONG_ENCAPSULATION = ErrorPronePlugin.JVM_ARGS_STRONG_ENCAPSULATION.joinToString(prefix = JVM_ARG, separator = JVM_ARG)

private fun jvmArg(argPrefix: String) = "$JVM_ARG$argPrefix"

private val ALL_JVM_ARGS = if (GradleVersion.version(testGradleVersion) >= GradleVersion.version("7.1")) "allJvmArgs" else "jvmArgs?"
}

@BeforeEach
Expand All @@ -42,7 +45,7 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
val displayCompileJavaOptions by tasks.creating {
doFirst {
println("Fork: ${'$'}{compileJava.options.isFork}")
compileJava.options.forkOptions.jvmArgs?.forEach { arg ->
compileJava.options.forkOptions.$ALL_JVM_ARGS.forEach { arg ->
println("JVM Arg: ${'$'}arg")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class ToolchainsIntegrationTest : AbstractPluginIntegrationTest() {
private val JVM_ARGS_STRONG_ENCAPSULATION = ErrorPronePlugin.JVM_ARGS_STRONG_ENCAPSULATION.joinToString(prefix = JVM_ARG, separator = JVM_ARG)

private fun jvmArg(argPrefix: String) = "$JVM_ARG$argPrefix"

private val ALL_JVM_ARGS = if (GradleVersion.version(testGradleVersion) >= GradleVersion.version("7.1")) "allJvmArgs" else "jvmArgs?"
}

@BeforeEach
Expand Down Expand Up @@ -56,7 +58,7 @@ class ToolchainsIntegrationTest : AbstractPluginIntegrationTest() {
doFirst {
println("ErrorProne: ${'$'}{if (compileJava.get().options.errorprone.isEnabled.getOrElse(false)) "enabled" else "disabled"}")
println("Fork: ${'$'}{compileJava.get().options.isFork}")
compileJava.get().options.forkOptions.jvmArgs?.forEach { arg ->
compileJava.get().options.forkOptions.$ALL_JVM_ARGS.forEach { arg ->
println("JVM Arg: ${'$'}arg")
}
}
Expand Down

0 comments on commit ffef94d

Please sign in to comment.