InMemoryJavaCompiler: test for Java 8 compatibility [message #1857533] |
Tue, 14 February 2023 10:10  |
Eclipse User |
|
|
|
We are generating Java code that should be Java 8 compatible. To test this, we use the `org.eclipse.xtext.xbase.testing.InMemoryJavaCompiler` class with `JavaVersion.JAVA8`.
However, I've just ran into an issue where I've accidentally used a Java 9 feature, but our unit tests didn't fail, causing me to believe it was Java 8 compatible and releasing, only having to find out later that projects depending on our DSL where failing to build.
The feature that I used is the static method `List::of`, which doesn't exist until Java 9.
In short, what I've found out by digging into the source code of `InMemoryJavaCompiler` and related classes:
- Passing `JavaVersion.JAVA8` results in the `-source` and `-target` flags being set to Java 8. What I actually need instead is to set the `-release` flag to Java 8, which would also override the `-bootclasspath` to be Java 8 compatible.
- The class used to represent compiler options, i.e., `org.eclipse.jdt.internal.compiler.impl.CompilerOptions`, doesn't seem to support the `-release` flag. A snippet from `CompilerOptions::getMap`:
optionsMap.put(OPTION_Compliance, versionFromJdkLevel(this.complianceLevel));
optionsMap.put(OPTION_Release, DISABLED); // ----------------------------------------> see this line
optionsMap.put(OPTION_Source, versionFromJdkLevel(this.sourceLevel));
optionsMap.put(OPTION_TargetPlatform, versionFromJdkLevel(this.targetJDK));
In essence, this means I'm only able to unit test that we're not using Java 9+ language features, but I'm not able to test that we're not using Java 9+ standard library features.
Is there a way to fix this? Or does the internal Eclipse compiler being used just not have support for the `-release` flag?
[Updated on: Tue, 14 February 2023 10:12] by Moderator Report message to a moderator
|
|
|
|
|
|
Re: InMemoryJavaCompiler: test for Java 8 compatibility [message #1857594 is a reply to message #1857580] |
Thu, 16 February 2023 11:37  |
Eclipse User |
|
|
|
@Ed Willink That's not a problem. Compilation with Java 8 works perfectly, and the tests will fail whenever I use a language feature from a newer Java version.
However, the tests don't fail when I use a class or method of the standard library from a newer Java version, e.g., `List.of()` which was added to the standard library since Java 9. And this is actually the intended and documented behaviour. From https://openjdk.org/jeps/247: (see emphasized)
Quote:javac provides two command line options, -source and -target, which can be used to select the version of the Java language accepted by the compiler and the version of the class files it produces, respectively. By default, however, javac compiles against the most-recent version of the platform APIs. The compiled program can therefore accidentally use APIs only available in the current version of the platform. Such programs cannot run on older versions of the platform, regardless of the values passed to the -source and -target options. This is a long-term usability pain point, since users expect that by using these options they'll get class files that can run on the the platform version specified by -target.
That's the motivation for the `-release` flag, which was introduced in Java 9 to compile for older platforms. The problem is that the API of the Eclipse compiler doesn't seem to support the `-release` flag.
[Updated on: Thu, 16 February 2023 11:39] by Moderator Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.03873 seconds