java - 如何在 IntelliJ 增量构建中获取所有带有注释的元素?

标签 java intellij-idea annotation-processing

我正在编写一个注解处理器,它需要收集当前模块中具有特定注解的所有类,并编写一个引用每个类的类。

为了简化一点,给定这些源文件:

src/main/java/org/example/A.java
@Annotation
class A {}
src/main/java/org/example/B.java
@Annotation
class B {}

我想生成一个类:

目标/生成源/org/example/Module.java
class 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/

相关文章:

java - 如何将时间戳信息添加到 Maven 工件?

java - eclipse ubuntu 18.04安装java.lang.ClassNotFoundException :

java - 垃圾收集 - 为什么 c3 在此示例中不符合收集条件 (SCJP 6)

java.lang.NoSuchMethodError ,构建过程已损坏

java - 使用 Java 注解处理器了解方法参数的参数化类型

android - 如何减少 React Native Android 应用程序的启动时间

java - java 如何编写replaceAll函数?

java - 在 IntelliJ IDEA 项目中找不到主类 : Java Application

java - 无法在 IntelliJ 中进入 Debug模式的方法?

android - 如何将 gradle BoM 与注释处理器一起使用?