Lombok's Java 9+ support story

TL;DR

About Lombok

Lombok Java9 + IntelliJ support

There was a problem that the build did not pass with Java9 + IntelliJ, so I fixed it, but I will write what kind of fix I made.

I have prepared a simple class diagram because I can not explain it without knowing the internal structure of the related part (only the part related to this correction. A small part of the whole)

LombokClassDiagram.png

Classes in the JDK

First, there are the following classes in the javax.tools package as public classes for the JDK. All are classes used to manipulate source code and class files.

The implementation class for the above interface is under the com.sun.tools.javac package. This is the inner class of the JDK.

Lombok implementation around file access

LombokFileObject Lombok uses Annotation Processor for AST conversion, but it interrupts class file writing as well as AST conversion processing. (See PostCompiler.wrapOutputStream () for details. Bytecode rewriting is done. Delete unnecessary code around @SneakyThrows and null check.) (2018/2/22 Corrected because there was a recognition error)

InterceptiongJavaFileObject provides an interrupt to write a file. This class is reflected on the Javac side when initializing LombokProcessor It has become like. This class implements the LombokFileObject interface. LombokFileObject inherits from JavaFileObject.

Lombok passes this to javac for processing, but there is one problem. The javac side is supposed to request the above BaseFileObject or PathFileObject internally (cast inside), so it will not accept the implementation of JavaFileObject interface (honestly, this is a shit implementation of javac) I think,,,) Therefore, you need to prepare a class that inherits BaseFileObject or PathFileObject and transfer it to the Lombok side. Lombok provides the following three Wrapper classes to do this.

At this point, I feel a little unpleasant, but the point is that we have prepared wrappers with different implementations for each version of javac. It is undeniable that there will be more and more in the future as the JDK version goes up. Both classes simply delegate all methods to LombokFileObject.

LombokFileObjects It's finally the production from here. Use LombokFileObjects to do things like wrap JavaFileManager.

First, LombokFileObjects has a Compiler interface. This is a class for wrapping a JavaFileObject and returning a LombokFileObject (implemented with the wrap () method). This also has a different class implementation for javac 6, 7, 9. Each is an implementation that returns the above Javac [679] BaseFileObjectWrapper.

The Compiler returns the LombokFileObjects.getCompiler (JavaFileManager jfm) method. The implementation looks at the JavaFileManager implementation class passed as an argument and returns the appropriate Compiler. There is a list of known JavaFileManager implementation class names called KNOWN_JAVA9_FILE_MANAGERS, which is full of unpleasant feelings.

Problems and workarounds in JDK9

The compiler implementation for javac9 is Java9Compiler. This implementation is a bit more complicated than 6 and 7. This is because PathFileObject, the base class of Java9BaseFileObjectWrapper, requires BaseFileManager in the constructor.

If the JavaFileManager passed to getCompiler () is an instance of BaseFileManager, it's okay (just cast it). But this can be another class. For example, when called from IntelliJ, a class that implements StandardJavaFileManager is passed. In this case, just casting will not work.

For this reason, I have created a new FileManagerWrapper class that inherits from BaseFileManager and modified it to use it for delegation. The pull request is here. This fix has been successfully incorporated and is currently released as 1.16.20. Now I managed to get the build to pass correctly in IntelliJ.

Where

Future tasks

Lombok relies heavily on the JDK's inner class (com.sun.), So it won't work if the internal structure changes with a JDK update. In particular, Java's update cycle has been relatively long until now, but in the future it will be updated every 6 months (although it is every 3 years for LTS), so I think it will have a big impact. In fact, it's already stuck in OpenJDK10 Early Access. Ugh.

Another problem is that it is affected not only by the JDK but also by the implementation of IDEs and build tools (such as Maven / Gradle). Since the core development members of Lombok are based on Eclipse, support for IntelliJ, Netbeans, etc. may be delayed. I'm IntelliJ main, so I'm planning to fix it and contribute.

If you use Lombok firmly, you should be aware that there are such risks.

Recommended Posts

Lombok's Java 9+ support story
Java static story
SonarQube Java 11 support
Java support period
Java8, 9, 10 support period
Java initializer story
Java generic story
A story about Java 11 support for Web services
Summary of Java support 2018
[Java] Aizu Online Judge's story 2
[Java] Aizu Online Judge's story 1
C # and Java Overrides Story
[Java version] The story of serialization
Story of passing Java Gold SE8
Java
Java
CORS support with Angular + Rest (Java)
Story of paiza.jp [Java standard input solution]
HA/DR support in Couchbase (Java SDK commentary)
The story of AppClip support in Anyca
The story received by Java SE11 silver
The story of writing Java in Emacs