Lombokのカスタムアノテーションを作ろうとして諦めたメモです。
3行でまとめ:
- Lombokのアノテーション実装ではJava内部クラス(コンパイラ関連)を参照する。
- Java9 以降、Java内部クラスの参照方法がビルドシステムやIDEで大きく変わり、難易度がめちゃくちゃ高くなった。
- アノテーションを集約するメタアノテーション的なのもLombokでは未対応なので、打つ手なし、ギブアップ。
作ろうとした経緯:
-
@Value
大好きなんだけど、Eclipse上からlombokが作成したgetterの利用箇所を Ctrl + Shift + F で逆引きできない。というかしづらい。- ソースコード上にはgetterは無いので当然といえば当然。
- 一応、Outlineビューで表示すれば getter も見えるので、その getter を右クリックして "References" メニュー選べば参照箇所逆引きできるけど、まぁめんどいっちゃめんどい。
- 参考: https://stackoverflow.com/questions/42644923/eclipse-with-lombok-search-for-getter-and-setter-usages
- そもそも Immutable なデータ構造体として
@ToString @EqualsAndHashCode @AllArgsConstructor
をまとめて付けたいがための@Value
で、個人的な好みとして getter 要らない。データ構造としてのフィールドはpublic final
でえーやろ、という割り切り。 - よし、カスタムアノテーション作ってみるか・・・ な~に、
@Value
のソースパクって、@Getter
機能呼び出してるところ削ればおしまいじゃろ。
ということで、まずは Lombok でカスタムアノテーション作るイロハをググった:
-
java - Create custom annotation for Lombok - Stack Overflow
-
Implementing a Custom Lombok Annotation | Baeldung
うん、予想はしてたけど Java のバイトコードのガチ操作でめんどくさそうだし難易度も高い。止めようかな・・・。
いやいや、そもそも作りたいのは @Value - @Getter
なのだから、@Value
のソースコードはどうなってる?
- アノテーション
- 実装本体
- https://github.com/rzwitserloot/lombok/blob/v1.18.12/src/core/lombok/javac/handlers/HandleValue.java
-
handleFlagUsage(...)
はぱっとみた感じ、設定ファイルから読み込んで@Value
使ってOK/NGあたりをチェックしてるっぽいので、カスタムアノテーションとしてコピペする分には不要。 -
deleteAnnotationIfNeccessary(...)
関連も experimental 時代の互換性対応ぽいので、これもカスタムアノテーションとしてコピペする分には不要。 - あとは以下のように他の handler の組み合わせを順に呼んでるだけなので、これコピペして handleGetter の呼び出しだけ削ればOKそう。
handleFieldDefaults.generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode);
handleConstructor.generateExtraNoArgsConstructor(typeNode, annotationNode);
handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true, List.<JCAnnotation>nil());
handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
handleToString.generateToStringForType(typeNode, annotationNode);
ここまででコピペ自体は行けそうだが、ふと「あれ・・・そういえば com.sun.tools 系使ってるよな・・・。この辺、java9のmodule導入の影響ガチで受けてるとこだし、どうすりゃいいんだ・・・」と途方に暮れる。
とりあえず java8 時代までの com.sun.tools を maven で扱うときの記事をググった。
-
Java/Maven3/tools.jarを使う時のトラブルシュート(<scope>=system, <systemPath>) - Glamenv-Septzen.net
-
java - Missing artifact com.sun:tools:jar - Stack Overflow
そうそう、こんな感じでした。では java9 でどうなったかちょっとぐぐってみると・・・
-
Accessing com.sun.tools.javac.util from Java 9 - Stack Overflow
-
Java Platform, Standard Edition Oracle JDK 9移行ガイド, リリース9
-
Declare maven dependency on tools.jar to work on JDK 9 - Stack Overflow
-
java - Build error: missing artifact com.sun:tools:jar:1.6 - Stack Overflow
めっちゃ雲行き怪しい。というかすでに阿鼻叫喚。ヤバい。
これに Eclipse 側の対応も・・・と軽くぐぐってみると、若干内容は異なるものの、いずれもJava内部クラスへのアクセスで苦労されてる様子:
- Java - 制限されているクラスのアクセスについて|teratail
- Java - eclipseでアクセス制限エラーが発生する|teratail
これはまずい。maven/pom.xml の調整がまずヤバそうだし、それとEclipse側の組み合わせも複雑さを跳ね上げてる。
そもそも、(今回の調査で初めて知った)サードパーティ製のLombokカスタムアノテーションを集めた https://github.com/peichhorn/lombok-pg も、そしてLombok 本体もビルドは Ant を使ってる様子。Eclipse IDE用にも結構調整入ってる雰囲気。(IDEに組み込むものなのか、IDEで開発するときのためのものかまでは不明だけどどちらにしても結構面倒くさそう)
トドメに、Java9 以降でLombokメンテすることの大変さが忍ばれる記事発見。
- Lombok の Java9以降対応の話 - Qiita
うーん、カスタムアノテーションがだめだったら、既存のアノテーションを集約するメタアノテーション的なのは作れないかな?とググってみたが・・・
-
java - Is it possible to use Lombok annotations as a meta-annotation? - Stack Overflow
-
Allow usage of annotations as meta-annotations · Issue #557 · rzwitserloot/lombok · GitHub
-
Feature Request: Allow multiple lombok's annotations to be aggregated into one · Issue #1226 · rzwitserloot/lombok · GitHub
どうやら難しそうで未対応とのこと。
以上を考えるに、そもそもやりたいのは以下のアノテーションを付けるのを簡単にしたいだけ・・・にも関わらず、実現するためのコストが異常に高い。
@AllArgsConstructor
@EqualsAndHashCode
@ToString
(場合によっては @With )
よって、今回はカスタムアノテーションを作成するのは一旦あきらめ、無難に必要なものだけコピペしてくことにする。