私は、現在のモジュール内の特定の注釈を持つすべてのクラスを収集し、それらのそれぞれを参照するクラスを作成する必要がある注釈プロセッサを書いています。
ビットを簡略化するために、これらのソースファイル与えられました:
SRC /メイン/ javaの/ ORG /例/ A.java@Annotation
class A {}
SRC /メイン/ javaの/ ORG /例/ B.java
@Annotation
class B {}
私はクラスを生成します:
ターゲット/生成された、ソース/ ORG /例/ Module.javaclass Module {
String getModuleClasses() {
return Arrays.asList(
"org.example.A",
"org.example.B"
);
}
}
これは、Mavenのから動作しますが、私は、クラスを変更するとA
、IntelliJのは、私の注釈プロセッサAを与えるRoundEnvironment
とA
、単一のルート要素として。
私はGradleのがでインクリメンタルコンパイルをサポートしている理解注釈プロセッサを集約偽物を渡すことによって、RoundEnvironment
注釈プロセッサに注釈を一致するすべてのソースではなく、IntelliJのは、類似した何かを持っていないようです。(Gradleのプロジェクトのために多分除くほか?)
IntelliJのが唯一のクラスをコンパイルするとき、両方のクラスを見つけるための最善の方法は何でしょうかA
?
たぶん、注釈は注釈付きクラスのリストを保つことができる:リストルート要素から各ラウンド削除で、最初のラウンドでリソースファイルからリストを読み、注釈を付けているリスト要素に追加して、戻ってリソースにリストを書きます最終ラウンドでのファイル?
この問題を解決する1つの方法は、あなたが、たとえば、META-INFに風のようなサービスでは、注釈付きの型を格納することができ、構築する間でレジストリのいくつかの並べ替えを使用しています
だからあなたのプロセッサでは、あなたは、処理の最後のラウンドまでコード生成を延期し、あなたのコードを生成した後、あなたは下のファイルにファイル内の型を保存します META-INF
FileObject resource = processingEnv.getFiler()
.createResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/annotatedtypes/"+fileName);
PrintWriter out = new PrintWriter(new OutputStreamWriter(resource.openOutputStream()));
classes.forEach(out::println);
あなたはもちろんの重複したエントリをチェックする必要があります。
コードを生成する前に、いくつかの点で、種類を読んで、それに基づいて、あなたのコードを生成
FileObject resource = processingEnv.getFiler()
.getResource(StandardLocation.CLASS_OUTPUT, "", "META-INF/annotatedtypes/"+fileName);
new BufferedReader(new InputStreamReader(resource.openInputStream())).lines().forEach(classes::add);
ファイルの内容は、次のようなもののようになります。
org.foo.bar.A
org.foo.bar.B
これに伴う問題は、あなたが最後のラウンドにコード生成を延期するときに生成されたコードは、例えば、dagger2のために、他のプロセッサによって選ばれることはありませんし、またいつかファイルはもう存在しないクラスのレコードで終わるかもしれないということです。
あなたのプロセッサ内部の要約では次の操作を行います
- META-INFのファイルから登録タイプを読みます
- あなたのアノテーション付きの要素を取得します。
- それが最後のラウンドである場合は、あなただけの設定のユニークなレコードを持つファイルを更新してコードを生成します。
あなたはファイルのすべてのラウンドを読みますが、最後のラウンドで一度だけ書き込みます。