freefair / gradle-plugins

Gradle Plugin Collection
https://docs.freefair.io/gradle-plugins/current/reference/
MIT License
215 stars 32 forks source link

delombok does not find all modules on module path #824

Open A-Willems opened 1 year ago

A-Willems commented 1 year ago

After we migrated our project to the Java Module System we encountered that not all modules on the modulePath are recognized.

The attached example is a simple gradle project that can be used to reproduce the problem: module-sample.zip

First, gradlew :application:run shows that the module-info.java is implemented correctly and the program executes as it should.

My module-info.java looks like this:

module delombok.sample.app {
    exports delombok.sample;

    requires lombok;
    requires org.slf4j;
    requires com.google.gson;
    requires org.apache.commons.lang3;

    opens delombok.sample to com.google.gson;
}

My delombok task allows to run with or without modulePath, so it's easier to reproduce the problem from command line:

delombok {
    dependsOn tasks.findByName('cleanDelombok')

    verbose = true

    if (project.hasProperty('withModulePath')) {

        modulePath = configurations.runtimeClasspath
    }
}

Calling gradlew :application:delombok does not set the delombok modulePath and produces the following output:

/home/user/tmp/module-sample/application/src/main/java/module-info.java:5: error: module not found: org.slf4j
    requires org.slf4j;
                ^
/home/user/tmp/module-sample/application/src/main/java/module-info.java:6: error: module not found: com.google.gson
    requires com.google.gson;
                       ^
/home/user/tmp/module-sample/application/src/main/java/module-info.java:7: error: module not found: org.apache.commons.lang3
    requires org.apache.commons.lang3;
                               ^

This shows, that there are three modules (org.slf4j, com.google.gson and org.apache.commons.lang3) that cannot be found. In this case it is not surprising as the modulePath was not set.

Finally calling gradlew -PwithModulePath :application:delombok produces:

/home/user/tmp/module-sample/application/src/main/java/module-info.java:5: error: module not found: org.slf4j
    requires org.slf4j;
                ^
/home/user/tmp/module-sample/application/src/main/java/module-info.java:6: error: module not found: com.google.gson
    requires com.google.gson;
                       ^

In this case, the module path of the delombok task is set (which I confirmed in the temporarily generated delombok.options). Now, the Apache Commons module was found, but SLF4J and GSON were still missing.

The question is: Am I doing something wrong or is this a problem within the delombok task?

Regards, Achim

larsgrefer commented 1 year ago

Could be this bug from lombok itself: https://github.com/projectlombok/lombok/issues/2829

moaxcp commented 4 months ago

It looks like the solution was a plugin that skips module-info.java when delombok is run. Maybe this is an option you can add to the Delombok task?

moaxcp commented 3 months ago

This is what I came up with to fix my issue in gradle.

  delombok {
    modulePath = classpath
  }

This is how I came about my fix.

delombok fails to compile module-info and a lot of classes for missing modules for example lombok

error: module not found: lombok

I decided to try logging and it showed a lombok options file is used. This is what it had.

--format=pretty
--target=/home/john/projects/x11/x11-protocol/x11-protocol-bigreq/build/generated/sources/delombok/java/main
--classpath=/home/john/projects/x11/x11-protocol/x11-protocol-core/build/libs/x11-protocol-core-0.18.0.jar:/home/john/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.32/17d46b3e205515e1e8efd3ee4d57ce8018914163/lombok-1.18.32.jar

There is no module-path and this is the problem. I also noticed the task has a configuration for modulePath. Then I had an idea. What if I just assign the classpath to modulePath. This is what the options file had after using modulePath = classpath.

--format=pretty
--target=/home/john/projects/x11/x11-protocol/x11-protocol-bigreq/build/generated/sources/delombok/java/main
--classpath=/home/john/projects/x11/x11-protocol/x11-protocol-core/build/libs/x11-protocol-core-0.18.0.jar:/home/john/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.32/17d46b3e205515e1e8efd3ee4d57ce8018914163/lombok-1.18.32.jar
--module-path=/home/john/projects/x11/x11-protocol/x11-protocol-core/build/libs/x11-protocol-core-0.18.0.jar:/home/john/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.32/17d46b3e205515e1e8efd3ee4d57ce8018914163/lombok-1.18.32.jar

It works! I hope this helps anyone having this issue.

@A-Willems I think in your case you should use the compile classpath but it might be easier to assign the delombok.classpath property to the delombok.modulePath property as I have done.

I think in the case where you want to compile without modules you have to exclude the module-info somehow.