编译器 API + 注释处理 == 双诊断消息



我正在将Java编译器API(JSR199(与自定义注释处理器(JSR269(相结合。提供给编译器的 Java 源代码中的某些语法错误导致诊断消息出现两次。许多语法错误仍然只导致一条诊断消息。例如,不匹配大括号只会导致一条消息,但具有无效限定标识符的导入会导致两条诊断消息,但仅在使用注释处理器时。

下面是一些会导致问题的示例输入:

import javax.xml.bind.annotation; // missing ".*"
public class Test { }

对于注释处理器,我有以下内容。(我尝试过从进程中返回 false,我也尝试手动实现处理器而不是扩展抽象处理器。

@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 时会导致重复的诊断消息吗?(并且仅适用于某些语法错误(

根据规范,注释处理按轮次顺序进行,并且始终至少有两轮处理。因此,示例中的Test.java被编译两次,处理器的 process 方法也被调用两次。下面是一个自包含的示例:

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:UsersAlexey_2AppDataLocalTempstackoverflow4274340620494105881Test.java:1: error: cannot find symbol
import javax.xml.bind.annotation; // missing ".*"
                     ^
  symbol:   class annotation
  location: package javax.xml.bind
C:UsersAlexey_2AppDataLocalTempstackoverflow4274340620494105881Test.java:1: error: cannot find symbol
import javax.xml.bind.annotation; // missing ".*"
                     ^
  symbol:   class annotation
  location: package javax.xml.bind
1 error

最新更新