tbroyer / gradle-errorprone-plugin

Gradle plugin to use the error-prone compiler for Java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Cannot Debug Annotation Processors when ErrorProne is Enabled

mikewacker opened this issue · comments

(I'm not sure if this is an issue with the plugin or ErrorProne itself, so I'll start here.)

If I want to debug an annotation processor, I would normally run ./gradlew -Dorg.gradle.debug=true --no-daemon ..., and then attach IntelliJ's debugger to the process. However, once I enable ErrorProne, the debugger will still attach to the process, but I can't hit any breakpoints. If I disable ErrorProne, however, I will start hitting those breakpoints again.

If you want an example to try this on, you can use my side project: https://github.com/mikewacker/annotation-processor-example. The README has some notes included on the need to comment out the ErrorProne lines in order to debug the annotation processor.

With JDK 16+, the plugin is forced to "fork" the compilation because of the "strong encapsulation" (and the need to pass --add-exports and --add-opens): https://github.com/tbroyer/gradle-errorprone-plugin#jdk-16-support
While technically it could work (without forking) if you passed those arguments to org.gradle.jvmargs in your gradle.properties, the plugin (currently) doesn't try to detect this and always explicitly pass the arguments and uses a forking compiler.

You would have to change your build to pass the -agentlib:… in the JavaCompile task's options.fork.jvmArgs (or reproduce the breakage in a compile-testing test)

I've got this partially figured out:

tasks.withType(JavaCompile) {
    if (System.properties.getOrDefault('org.gradle.debug', 'false') == 'true') {
        // TODO: Remove '-agentlib' JVM arg for original compiler.
        options.forkOptions.jvmArgs << '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005'
    }
}

If I set -Dorg.gradle.debug=true on the command line, I now have to attach a debugger twice: once for the original compiler, once for the forking compiler. (The other option is to unconditionally include the options.forkOptions.jvmArgs line, comment it out, and uncomment it when I want to debug.)

I don't think there's a way to disable debugging on the original process if org.gradle.debug option is set, so the best option seems to be to create a org.gradle.debugfork option. Here's how it could be set up in buildSrc for a project:

tasks.withType(JavaCompile) {
    // The Error Prone plugin uses a forking compiler for JDK 16+.
    // The 'org.gradle.debugfork' option has been added to enable debugging on the forked process.
    if (System.properties.getProperty('org.gradle.debugfork', 'false').toBoolean()) {
        // Use port 5006 on the off chance that the original process is listening for a debugger on port 5005.
        options.forkOptions.jvmArgs << '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006'
    }
}

It may make sense to add something like this to the plugin, though, so that consumers don't have to figure all of this out.

I've just published version 3.1.0 that will avoid forking when using JDK 16+ so it should be easier to debug. To benefit from it, you'll have to configure the appropriate --add-exports and --add-opens in org.gradle.jvmargs:

Thanks, can confirm that it works for me.