0

General idea: I want to build a simple annotation processor on Gradle and Java 17 (Gradle 7.5, Java 17.0.6). And use it in another project with the same setup.

here is my code:

annotation-processor project build.gradle:

plugins {
    id 'java'
    id 'maven-publish'
}

group 'org.simple.processor'
version '1.0-SNAPSHOT'

repositories {
    mavenLocal()
}

publishing {
    publications {
        maven(MavenPublication) {

        }
    }
    repositories {
        mavenLocal()
    }
}

compileJava {
    options.annotationProcessorPath = configurations.annotationProcessor
}

sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17

tasks.withType(JavaCompile) {
    options.compilerArgs += ["--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED"]
    options.compilerArgs += ["--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED"]
    options.compilerArgs += ["--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"]
    options.compilerArgs += ["--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"]
}

annotation-processor project LocalVariableTranslator.class:

public class LocalVariableTranslator extends TreeTranslator {
    @Override
    public void visitClassDef(JCTree.JCClassDecl tree) {
        // simply log something
    }
}

annotation-processor-demo project build.gradle:

plugins {
    id 'java'
}

group 'org.simple.processor'
version '1.0-SNAPSHOT'

sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17

repositories {
    mavenCentral()
    mavenLocal()
}

dependencies {
    annotationProcessor 'org.simple.processor:simple-processor:1.0-SNAPSHOT'
    implementation 'org.simple.processor:simple-processor:1.0-SNAPSHOT'
}

my processor code somehow depends on internal Java API which is 'com.sun.tools.javac' package and this causes an issue for me when I try to build a demo project:

Execution failed for task ':compileJava'. superclass access check failed: class org.simple.processor.LocalVariableTranslator (in unnamed module @0x6073770b) cannot access class com.sun.tools.javac.tree.TreeTranslat or (in module jdk.compiler) because module jdk.compiler does not export com.sun.tools.javac.tree to unnamed module @0x6073770b

Serhii Kachan
  • 345
  • 4
  • 13
  • All those `--add-exports` compiler args you have only apply to the annotation processor project (when compiling it). Those compiler args aren't automatically included in any project that depends on your annotation processor. Though why are you trying to implement `TreeTranslator`, which is from a non-exported package? Why not implement [`TreeVisitor`](https://docs.oracle.com/en/java/javase/19/docs/api/jdk.compiler/com/sun/source/tree/TreeVisitor.html) or extend an implementation, e.g., `SimpleTreeVisitor`, `TreePathScanner`, or `TreeScanner`? – Slaw Feb 20 '23 at 18:16
  • Or, if you don't need to go that "low level", why not implement/extend something from the `java.compiler` module (instead of `jdk.compiler`)? – Slaw Feb 20 '23 at 18:21
  • @Slaw, thank you for the response. I actually looked into that, but it is exactly about "visiting", but I need to modify the code, like adding/changing pieces to source code, like lombok does. – Serhii Kachan Feb 22 '23 at 14:27
  • Then I _think_ you need to add those `--add-exports` in the project that consumes your annotation processor as well. – Slaw Feb 22 '23 at 16:27
  • I've found the reason. It works well exactly with same setup I provided but using Java 11 – Serhii Kachan Feb 22 '23 at 16:42
  • my annotation processor project is compiled in Java 11, and looks like consumer project works with it when its Java version it 15 or lower... interesting: warning: Supported source version 'RELEASE_11' from annotation processor 'org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor' less than -source '15' 1 warning – Serhii Kachan Feb 22 '23 at 16:49
  • I am just wondering... lombok is definitely compiled not in java 17. However I have a lot of projects on Java 17 and lombok is added there and it works fine. Any ideas how to make it compatible? – Serhii Kachan Feb 22 '23 at 16:54
  • When JPMS was introduced in Java 9, it added stronger encapsulation. But some already-existing code relied on accessing internals of the standard library. So, they relaxed the encapsulation for the standard library so code that was accessible in Java 8 was still accessible in Java 9. You could control this with the `--illegal-access` option, which had a default value of `permit`. But this was always a temporary measure to give libraries time to update. In Java 16, the default value of `--illegal-access` became `deny`. And in Java 17, `--illegal-access` no longer does anything (always `deny`). – Slaw Feb 22 '23 at 22:48
  • Assuming Lombok/Gradle is not doing some strange stuff, my best guess as to why Lombok still works on Java 16+ is that it uses `--add-exports` and/or `--add-opens` when compiling your project. – Slaw Feb 22 '23 at 22:50
  • 1
    Okay, so for Lombok, it looks like they use `Unsafe` to essentially add the `--add-opens` at run-time. Not sure if that's viable for you, but you can see what they do [here](https://github.com/projectlombok/lombok/blob/e5c324c615c1e304b2a9a64bc7f8608a67b0a74e/src/core/lombok/javac/apt/LombokProcessor.java#L483). Another option for you might be to create your own Gradle plugin that both adds your annotation process and configures the compiler arguments. – Slaw Feb 22 '23 at 23:17
  • well yeah, that makes sense! Thank you Slaw, I will try to make my projects compatible! – Serhii Kachan Feb 23 '23 at 08:55

1 Answers1

0

you can add this code to your gradle.properties

org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 \
 --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
 --add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED \
 --add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \
 --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
 --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
Crow
  • 1