2

Java Compiler API (JSR199) とカスタム注釈プロセッサ (JSR269) を組み合わせています。コンパイラに提供される Java ソース コードの一部の構文エラーにより、診断メッセージが 2 回表示されます。多くの構文エラーは、依然として 1 つの診断メッセージのみを引き起こします。たとえば、不一致の中括弧は 1 つのメッセージのみを生成しますが、修飾識別子が無効なインポートは 2 つの診断メッセージを生成しますが、これは注釈プロセッサが使用されている場合のみです。

問題の原因となるサンプル入力を次に示します。

import javax.xml.bind.annotation; // missing ".*"

public class Test { }

注釈プロセッサの場合、次のものがあります。(プロセスから false を返すことを試みました。また、AbstractProcessor を拡張する代わりに、Processor を手動で実装しようとしました。)

@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes("*")
public class AnnotationProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        return true;
    }
}

コンパイラを呼び出して注釈プロセッサを追加するために使用されるコードの一部を次に示します。

javax.tools.DiagnosticCollector<javax.tools.JavaFileObject> diagnostics =
        new javax.tools.DiagnosticCollector<>();

javax.tools.StandardJavaFileManager fileManager =
        javac.getStandardFileManager(diagnostics, null, null);

fileManager.setLocation(javax.tools.StandardLocation.CLASS_OUTPUT, Arrays.asList(tempDir.toFile()));

javax.tools.JavaCompiler.CompilationTask task =
        javac.getTask(out, fileManager, diagnostics, null, null, compilationUnits);

List<Processor> processors = new ArrayList<>();
AnnotationProcessor ap = new AnnotationProcessor();
processors.add(ap);
task.setProcessors(processors);

Boolean compiled = task.call();

for (Diagnostic<? extends JavaFileObject> diag : diagnostics.getDiagnostics()) {
    out.println(diag.toString());
}

私の出力は次のようになります。

/Test.java:1: error: cannot find symbol
import javax.xml.bind.annotation;
                     ^
  symbol:   class annotation
  location: package javax.xml.bind
/Test.java:1: error: cannot find symbol
import javax.xml.bind.annotation;
                     ^
  symbol:   class annotation
  location: package javax.xml.bind

行を取り出すとprocessors.add(ap);、重複したエラー メッセージが消えます。複数のプロセッサを追加しても、追加の効果はありません。

コンパイラ API を使用しているときに、注釈プロセッサが重複した診断メッセージを引き起こす理由は何ですか? (そして、そのときのいくつかの構文エラーの場合のみ)

4

1 に答える 1

2

仕様によると、注釈処理は一連のラウンドで発生し、常に少なくとも 2 ラウンドの処理が行われます。したがって、Test.javaあなたの例は2回コンパイルされ、プロセッサのプロセスメソッドも2回呼び出されます。自己完結型の例を次に示します。

public class AnnotationProcessor {
    public static final String JAVA_SOURCE = "import javax.xml.bind.annotation; // missing \".*\"\n" +
            "\n" +
            "public class Test { }";

    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    @SupportedAnnotationTypes("*")
    public static class MyProcessor extends AbstractProcessor {

        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            System.out.println("Process : " + roundEnv);
            return true;
        }
    }

    public static void main(String[] args) throws IOException {
        JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = javac.getStandardFileManager(null, null, null);
        Path source = Files.createTempDirectory("stackoverflow").resolve("Test.java");
        Files.write(source, JAVA_SOURCE.getBytes());
        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(source.toFile());
        JavaCompiler.CompilationTask task = javac.getTask(null, null, null, null, null, compilationUnits);
        task.setProcessors(Collections.singleton(new MyProcessor()));
        task.call();
    }
}

出力:

Process : [errorRaised=false, rootElements=[Test], processingOver=false]
Process : [errorRaised=false, rootElements=[], processingOver=true]
C:\Users\Alexey_2\AppData\Local\Temp\stackoverflow4274340620494105881\Test.java:1: error: cannot find symbol
import javax.xml.bind.annotation; // missing ".*"
                     ^
  symbol:   class annotation
  location: package javax.xml.bind
C:\Users\Alexey_2\AppData\Local\Temp\stackoverflow4274340620494105881\Test.java:1: error: cannot find symbol
import javax.xml.bind.annotation; // missing ".*"
                     ^
  symbol:   class annotation
  location: package javax.xml.bind
1 error
于 2014-06-19T21:10:49.480 に答える