我将Java Compiler API (JSR199)与自定义批注处理器(JSR269)结合起来。提供给编译器的Java源代码中的某些语法错误会导致诊断消息出现两次。许多语法错误仍然只导致一条诊断消息。例如,不匹配的大括号只会导致一条消息,而带有无效限定标识符的导入会导致两条诊断消息,但只有在使用批注处理器时才会这样做。
以下是一些将导致问题的示例输入:
import javax.xml.bind.annotation; // missing ".*"
public class Test { }对于批注处理器,我有以下几点。(我尝试过从process返回false,也尝试过手动实现Processor,而不是扩展AbstractProcessor。)
@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时会导致重复的诊断消息吗?(并且只针对某些语法错误)
发布于 2014-06-20 05:10:49
根据specification的说法,批注处理按rounds的顺序进行,并且始终至少有两轮处理。因此,示例中的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:\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 errorhttps://stackoverflow.com/questions/19188842
复制相似问题