我正在编写一个注解处理器,它需要收集当前模块中具有特定注解的所有类,并编写一个引用每个类的类。
为了简化一点,给定这些源文件:
src/main/java/org/example/A.java@Annotation
class A {}
src/main/java/org/example/B.java
@Annotation
class B {}
我想生成一个类:
目标/生成源/org/example/Module.javaclass Module {
String getModuleClasses() {
return Arrays.asList(
"org.example.A",
"org.example.B"
);
}
}
这适用于 Maven,但是当我修改类 A
时,IntelliJ 给我的注释处理器一个 RoundEnvironment
,其中 A
作为单个根元素.
我知道 Gradle 支持增量编译
aggregating annotation processors
通过将所有源与注释匹配的假 RoundEnvironment
传递给注释处理器,但 IntelliJ 似乎没有任何类似的东西。 (除了 Gradle 项目?)
当 IntelliJ 只编译类 A
时,找到这两个类的最佳方法是什么?
也许注释器可以保存一个被注释类的列表:在第一轮从资源文件中读取列表,在每一轮中从列表中删除根元素并添加到列表中被注释的元素,然后写回列表到最后一轮的资源文件?
最佳答案
解决此问题的一种方法是在构建之间使用某种注册表,例如,您可以将注释的类型存储在服务中,例如 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 文件中读取注册类型
- 获取使用您的注释进行注释的元素。
- 如果是最后一轮,您只需使用唯一记录集更新文件并生成代码。
您每一轮都读取文件,但在最后一轮只写入一次。
关于java - 如何在 IntelliJ 增量构建中获取所有带有注释的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56133377/