Skip to content

Commit

Permalink
Declare errorprone javac as a default dependency
Browse files Browse the repository at this point in the history
There hasn't been a new version for nearly 4 years,
and it's highly unlikely there'll be a new one at
this point, so this will save some configuration for
users, and simplifies the plugin as it no longer
has to warn when none has been configured.
  • Loading branch information
tbroyer committed Oct 10, 2022
1 parent 8958d29 commit 72a842c
Show file tree
Hide file tree
Showing 10 changed files with 26 additions and 225 deletions.
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,8 @@ tasks.register<JavaCompile>("compileCustom") {
## JDK 8 support

Error Prone requires at least a JDK 9 compiler.
When using a JDK 8 compiler, you can configure a dependency on the Error Prone javac in the `errorproneJavac` configuration:
```gradle
dependencies {
errorproneJavac("com.google.errorprone:javac:9+181-r4173-1")
}
```
and the plugin will configure the `JavaCompile` tasks to [use a forking compiler][CompileOptions.fork]
and will override the compiler by prepending the dependencies to the bootstrap classpath
When using a JDK 8 compiler, the plugin will configure the `JavaCompile` tasks to [use a forking compiler][CompileOptions.fork]
and will override the compiler by prepending the Error Prone javac to the bootstrap classpath
(using a `-Xbootclasspath/p:` [JVM argument][BaseForkOptions.getJvmArgs]).

You can [configure `JavaCompile` tasks][gradle-toolchains] to use a specific JDK compiler,
Expand Down
2 changes: 0 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ gradle.taskGraph.whenReady {
val additionalPluginClasspath by configurations.creating

val errorproneVersion = "2.10.0"
val errorproneJavacVersion = "9+181-r4173-1"

repositories {
mavenCentral()
Expand Down Expand Up @@ -111,7 +110,6 @@ tasks {
androidSdkHome?.also { systemProperty("test.android-sdk-home", androidSdkHome) }

systemProperty("errorprone.version", errorproneVersion)
systemProperty("errorprone-javac.version", errorproneJavacVersion)

if (project.findProperty("test.skipAndroid").toString().toBoolean()) {
exclude("**/*Android*")
Expand Down
25 changes: 4 additions & 21 deletions src/main/kotlin/net/ltgt/gradle/errorprone/ErrorPronePlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import org.gradle.api.Named
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.FileCollection
import org.gradle.api.logging.Logging
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.plugins.JavaBasePlugin
import org.gradle.api.tasks.ClasspathNormalizer
Expand All @@ -26,7 +25,6 @@ import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.kotlin.dsl.* // ktlint-disable no-wildcard-imports
import org.gradle.process.CommandLineArgumentProvider
import org.gradle.util.GradleVersion
import java.util.concurrent.atomic.AtomicBoolean

/**
* A [Plugin] that configures [JavaCompile] tasks to use the [Error Prone compiler](https://errorprone.info/).
Expand All @@ -40,17 +38,6 @@ class ErrorPronePlugin : Plugin<Project> {

const val JAVAC_CONFIGURATION_NAME = "errorproneJavac"

private val LOGGER = Logging.getLogger(ErrorPronePlugin::class.java)

internal const val NO_JAVAC_DEPENDENCY_WARNING_MESSAGE =
"""No dependency was configured in configuration $JAVAC_CONFIGURATION_NAME, compilation with Error Prone will likely fail as a result.
Add a dependency to com.google.errorprone:javac with the appropriate version corresponding to the version of Error Prone you're using:
dependencies {
$JAVAC_CONFIGURATION_NAME("com.google.errorprone:javac:${'$'}errorproneJavacVersion")
}
"""

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

internal val JVM_ARGS_STRONG_ENCAPSULATION = listOf(
Expand Down Expand Up @@ -86,18 +73,14 @@ Add a dependency to com.google.errorprone:javac with the appropriate version cor
isVisible = false
isCanBeConsumed = false
isCanBeResolved = true
defaultDependencies {
add(project.dependencies.create("com.google.errorprone:javac:9+181-r4173-1"))
}
}

val noJavacDependencyNotified = AtomicBoolean()
fun JavaCompile.configureErrorProneJavac() {
options.isFork = true
javacConfiguration.asPath.also {
if (it.isNotBlank()) {
options.forkOptions.jvmArgs!!.add("-Xbootclasspath/p:$it")
} else if (noJavacDependencyNotified.compareAndSet(false, true)) {
LOGGER.warn(NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
}
}
options.forkOptions.jvmArgs!!.add("-Xbootclasspath/p:${javacConfiguration.asPath}")
}

val providers = project.providers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ class AndroidIntegrationTest : AbstractPluginIntegrationTest() {
}
dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
""".trimIndent()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class ErrorPronePluginIntegrationTest : AbstractPluginIntegrationTest() {
}
dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
""".trimIndent()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class GroovyDslIntegrationTest {
}
dependencies {
errorprone "com.google.errorprone:error_prone_core:$errorproneVersion"
errorproneJavac "com.google.errorprone:javac:$errorproneJavacVersion"
}
""".trimIndent()
)
Expand Down
112 changes: 18 additions & 94 deletions src/test/kotlin/net/ltgt/gradle/errorprone/Java8IntegrationTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
private val NOT_FORKED = "${System.lineSeparator()}Fork: false${System.lineSeparator()}"
private val JVM_ARG = "${System.lineSeparator()}JVM Arg: "
private val JVM_ARG_BOOTCLASSPATH = jvmArg("-Xbootclasspath/p:")
private val JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC = Regex.escape(File.separator).let { fileSeparator ->
val escapedErrorproneJavacVersion = Regex.escape(errorproneJavacVersion)
"""$JVM_ARG_BOOTCLASSPATH.*${fileSeparator}com\.google\.errorprone${fileSeparator}javac$fileSeparator$escapedErrorproneJavacVersion$fileSeparator.*${fileSeparator}javac-$escapedErrorproneJavacVersion.jar[${File.pathSeparator}${System.lineSeparator()}]"""
private val JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC =
"""\Q$JVM_ARG_BOOTCLASSPATH\E.*\Q${File.separator}com.google.errorprone${File.separator}javac${File.separator}9+181-r4173-1${File.separator}\E.*\Q${File.separator}javac-9+181-r4173-1.jar\E(?:\Q${File.pathSeparator}\E|${Regex.escape(System.lineSeparator())})"""
.toPattern()
}
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"
Expand All @@ -39,7 +37,6 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
}
dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
val compileJava: JavaCompile by tasks
Expand Down Expand Up @@ -271,74 +268,6 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}

@Test
fun `warns if Error Prone javac dependency is not configured`() {
assume().withMessage("isJava8").that(JavaVersion.current().isJava8).isTrue()

// given
// Remove the errorproneJavac dependency
buildFile.writeText(
buildFile.readLines().filterNot {
it.contains("""errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")""")
}.joinToString(separator = "\n")
)

// when
testProjectDir.buildWithArgsAndFail("compileJava").also { result ->
// then
assertThat(result.task(":compileJava")?.outcome).isEqualTo(TaskOutcome.FAILED)
assertThat(result.output).contains(ErrorPronePlugin.NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
assertThat(result.output).contains(FORKED)
assertThat(result.output).doesNotContain(JVM_ARG_BOOTCLASSPATH)
// Check that the configured jvm arg is preserved
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}

// check that adding back the dependency fixes compilation (so it was indeed caused by missing dependency) and silences the warning

// given
buildFile.appendText(
"""
dependencies {
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
""".trimIndent()
)

// when
testProjectDir.buildWithArgs("compileJava").also { result ->
// then
assertThat(result.task(":compileJava")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
assertThat(result.output).doesNotContain(ErrorPronePlugin.NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
assertThat(result.output).contains(FORKED)
assertThat(result.output).containsMatch(JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC)
// Check that the configured jvm arg is preserved
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}
}

@Test
fun `does not warn if Error Prone javac dependency is not configured with non-Java 8 VM`() {
assume().withMessage("isJava8").that(JavaVersion.current().isJava8).isFalse()

// given
// Remove the errorproneJavac dependency
buildFile.writeText(
buildFile.readLines().filterNot {
it.contains("""errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")""")
}.joinToString(separator = "\n")
)

// when
testProjectDir.buildWithArgs("compileJava").also { result ->
// then
assertThat(result.task(":compileJava")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
assertThat(result.output).doesNotContain(ErrorPronePlugin.NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
assertThat(result.output).doesNotContain(JVM_ARG_BOOTCLASSPATH)
}
}

@Test
fun `is build-cache friendly`() {
assume().withMessage("isJava8").that(JavaVersion.current().isJava8).isTrue()
Expand Down Expand Up @@ -367,27 +296,22 @@ class Java8IntegrationTest : AbstractPluginIntegrationTest() {
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}

// Move the errorproneJavac dependency: first remove it, then add it back… differently
buildFile.writeText(
buildFile.readLines().filterNot {
it.contains("""errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")""")
}.joinToString(
separator = "\n",
postfix = """
val epJavac by configurations.creating
val moveEpJavac by tasks.creating(Copy::class) {
from(epJavac)
// destinationDir chosen to match JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC
into(file("javac/com.google.errorprone/javac/$errorproneJavacVersion/foo/"))
rename { "renamed-${'$'}it" }
}
dependencies {
epJavac("com.google.errorprone:javac:$errorproneJavacVersion")
errorproneJavac(fileTree(moveEpJavac.destinationDir).builtBy(moveEpJavac))
}
""".trimIndent()
)
// Add the errorproneJavac dependency… differently
buildFile.appendText(
"""
val epJavac by configurations.creating
val moveEpJavac by tasks.creating(Copy::class) {
from(epJavac)
// destinationDir chosen to match JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC
into(file("javac/com.google.errorprone/javac/9+181-r4173-1/foo/"))
rename { "renamed-${'$'}it" }
}
dependencies {
epJavac("com.google.errorprone:javac:9+181-r4173-1")
errorproneJavac(fileTree(moveEpJavac.destinationDir).builtBy(moveEpJavac))
}
""".trimIndent()
)

// when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class ManualConfigurationIntegrationTest : AbstractPluginIntegrationTest() {
}
dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
val compileJava by tasks.creating(JavaCompile::class) {
Expand Down Expand Up @@ -80,7 +79,6 @@ class ManualConfigurationIntegrationTest : AbstractPluginIntegrationTest() {
}
dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
val customCompileJava by tasks.creating(JavaCompile::class) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ class ToolchainsIntegrationTest : AbstractPluginIntegrationTest() {
private val NOT_FORKED = "${System.lineSeparator()}Fork: false${System.lineSeparator()}"
private val JVM_ARG = "${System.lineSeparator()}JVM Arg: "
private val JVM_ARG_BOOTCLASSPATH = jvmArg("-Xbootclasspath/p:")
private val JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC = Regex.escape(File.separator).let { fileSeparator ->
val escapedErrorproneJavacVersion = Regex.escape(errorproneJavacVersion)
"""$JVM_ARG_BOOTCLASSPATH.*${fileSeparator}com\.google\.errorprone${fileSeparator}javac$fileSeparator$escapedErrorproneJavacVersion$fileSeparator.*${fileSeparator}javac-$escapedErrorproneJavacVersion.jar[${File.pathSeparator}${System.lineSeparator()}]"""
private val JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC =
"""\Q$JVM_ARG_BOOTCLASSPATH\E.*\Q${File.separator}com.google.errorprone${File.separator}javac${File.separator}9+181-r4173-1${File.separator}\E.*\Q${File.separator}javac-9+181-r4173-1.jar\E(?:\Q${File.pathSeparator}\E|${Regex.escape(System.lineSeparator())})"""
.toPattern()
}
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"
Expand All @@ -45,7 +43,6 @@ class ToolchainsIntegrationTest : AbstractPluginIntegrationTest() {
}
dependencies {
errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
tasks {
Expand Down Expand Up @@ -356,93 +353,4 @@ class ToolchainsIntegrationTest : AbstractPluginIntegrationTest() {
// Check that the configured jvm arg is preserved
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}

@Test
fun `warns if Error Prone javac dependency is not configured`() {
// given
// Remove the errorproneJavac dependency
buildFile.writeText(
buildFile.readLines().filterNot {
it.contains("""errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")""")
}.joinToString(separator = "\n")
)
buildFile.appendText(
"""
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(8))
}
}
""".trimIndent()
)

// when
testProjectDir.buildWithArgsAndFail("compileJava").also { result ->
// then
result.assumeToolchainAvailable()
assertThat(result.task(":compileJava")?.outcome).isEqualTo(TaskOutcome.FAILED)
assertThat(result.output).contains(ErrorPronePlugin.NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
assertThat(result.output).contains(FORKED)
assertThat(result.output).doesNotContain(JVM_ARG_BOOTCLASSPATH)
// Check that the configured jvm arg is preserved
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}

// check that adding back the dependency fixes compilation (so it was indeed caused by missing dependency) and silences the warning

// given
buildFile.appendText(
"""
dependencies {
errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")
}
""".trimIndent()
)

// when
testProjectDir.buildWithArgsAndFail("compileJava").also { result ->
// then
result.assumeToolchainAvailable()
assertThat(result.task(":compileJava")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
assertThat(result.output).doesNotContain(ErrorPronePlugin.NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
assertThat(result.output).contains(FORKED)
assertThat(result.output).containsMatch(JVM_ARG_BOOTCLASSPATH_ERRORPRONE_JAVAC)
// Check that the configured jvm arg is preserved
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}
}

@Test
fun `does not warn if Error Prone javac dependency is not configured with non-Java 8 VM`() {
// given
// Remove the errorproneJavac dependency
buildFile.writeText(
buildFile.readLines().filterNot {
it.contains("""errorproneJavac("com.google.errorprone:javac:$errorproneJavacVersion")""")
}.joinToString(separator = "\n")
)
buildFile.appendText(
"""
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
""".trimIndent()
)

// when
testProjectDir.buildWithArgsAndFail("compileJava").also { result ->
// then
result.assumeToolchainAvailable()
assertThat(result.task(":compileJava")?.outcome).isEqualTo(TaskOutcome.SUCCESS)
assertThat(result.output).doesNotContain(ErrorPronePlugin.NO_JAVAC_DEPENDENCY_WARNING_MESSAGE)
assertThat(result.output).doesNotContain(JVM_ARG_BOOTCLASSPATH)
// Check that the configured jvm arg is preserved
assertThat(result.output).contains(jvmArg("-XshowSettings"))
}
}
}
1 change: 0 additions & 1 deletion src/test/kotlin/net/ltgt/gradle/errorprone/fixtures.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import java.io.File
val testGradleVersion = System.getProperty("test.gradle-version", GradleVersion.current().version)

val errorproneVersion = System.getProperty("errorprone.version")!!
val errorproneJavacVersion = System.getProperty("errorprone-javac.version")!!

const val FAILURE_SOURCE_COMPILATION_ERROR = "Failure.java:6: error: [ArrayEquals]"

Expand Down

0 comments on commit 72a842c

Please sign in to comment.