前回は,アノテーションプロセッサの基本的な使い方について解説しました。今回は本格的にアノテーション処理を行う時に必要な準備に関して紹介します。

メッセージの出力

アノテーションプロセッサはjavacコマンドによって実行することは前回説明しました。せっかくjavacコマンドで実行するのですから,出力もjavacコマンドと同様にしたいところです。

たとえば,アノテーションの処理中に何らかのエラーが見つかった場合,javacコマンドのコンパイルエラーと同様に出力したくなりますよね。このような用途に使えるのが,javax.annotation.processing.Messagerインタフェースです。

ここでは,先週使用したInfoアノテーションとInfoProcessorクラスにMessagerインタフェースを組み込んでいきましょう。

サンプルのソース (こちらからダウンロードできます)
Info.java
InfoProcessor.java

Messagerオブジェクトを取得するには,javax.annotation.processing.ProcessingEnvironmentインタフェースのgetMessagerメソッドを使用します。しかし,その前にProcessingEnvironmentオブジェクトはどこから取得するのかと思われるかもしれません。

ProcessingEnvironmentオブジェクトはjavax.annotation.processing.AbstractProcessorクラスのprocessingEnvフィールドで定義されています。processingEnvフィールドのアクセス修飾子はprotectedなので,AbstractProcessorクラスを派生させたアノテーションプロセッサであれば,processingEnvフィールドにアクセスすることができます。

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("Info")
public class InfoProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, 
                           RoundEnvironment roundEnvironment) {
        // Messager オブジェクトの取得
        Messager messager = processingEnv.getMessager();
        
        for(TypeElement annotation : annotations) {
            // annotation が使用されている要素を取得
            Set elements 
                = roundEnvironment.getElementsAnnotatedWith(annotation);

            for (Element element: elements) {
                // Info アノテーションを取得
                Info info = element.getAnnotation(Info.class);

                try {
                    messager.printMessage(
                        Diagnostic.Kind.NOTE,
                        "Info at " + element 
                        + "\n   value: " + info.value());
                } catch (IncompleteAnnotationException ex) {
                    messager.printMessage(
                        Diagnostic.Kind.ERROR,
                        "Info アノテーションに value 要素がありません",
                        element);
                }
            }            
        }
        return true;
    }
}

赤字で記述してある部分がMessageオブジェクトを取得している部分です。