Android Annotation Processor 从不同的模块访问 Annotated 类

Android Annotation Processor accessing Annotated classes from different modules

我有一个包含 2 个模块的 Android Studio 项目:A 和 B。(我不包括注释处理器和注释模块)

B 依赖于 A。

B 是一个 Android 库模块,A 是简单的 Java 库模块。我在模块 B 上也有一个注释处理器。

我面临的问题是:

我想根据放置在两个模块 - A 和 B 中的注释文件生成一些代码。问题来自注释处理器的工作方式 - 仅使用源代码文件 *.java - 不是编译后的 *.class 文件。不幸的是,在 B 的编译过程中,Annotation Processor 无法访问 A 的那些源文件...

我唯一能想到的一种解决方案,即使是一个丑陋的解决方案,也就是将模块 A 中带有注释 classes 的文件夹作为源集包含到模块 B . 这样我就可以在编译期间让模块 B 访问这些文件。

sourceSets {
    main {
        java {
            srcDirs = ['src/main/java', '../module_A/src/main/java/path/to/annotated/classes/folder']
        }
    }
}

这解决了问题 - 现在注释处理器可以访问来自两个模块的所有带注释的 classes,但是...

不幸的是,它引入了另一个问题...那些来自模块 A 的注释 classes 现在被编译了两次。它们包含在模块 A 的 JAR 文件和模块 B 的 AAR 文件中。

问题 1:是否有另一种方法可以从 B 上的注释处理器 运行 访问模块 A 的那些源文件??? (据我所知,答案是否定的,但正在检查...)

问题2:如何从模块B的AAR最终包中排除那些编译后的文件(重复的)?

问题 3:也许...这是一个绝对错误的方法?有什么建议吗?

提前致谢!

不,仅使用 java.lang.model API 无法实现您想要的效果。至少不是没有一些额外的技巧。

问题不在于二进制与源代码。注释处理器可以使用 Elements#getTypeElement 来检查已编译的 classes 以及源定义的 classes:

Elements elementUtil = processingEnvironment.getElementUtils();
TypeElement integerClass = elementUtil.getTypeElement("java.lang.Integer");
TypeElement myClass = elementUtil.getTypeElement("currently.compiled.Class");

但是您仍然需要在编译 class 路径上有 class 才能观察到它,并且 class 必须正在编译才能对 [=12= 可见].

您可以使用 FastClasspathScanner 之类的工具来解决以后的限制:它将使用自己的机制在编译的字节码中查找注释,并在编译过程中单独向您报告。但是你不能解决 classpath 问题:如果你在编译 classpath 中没有一些依赖,它就不能被处理。因此,您 必须 将模块编译在一起——要么将它们合并为一个(就像您所做的那样),要么通过声明一个依赖另一个。在以后的情况下,您可能无法使用 getElementsAnnotatedWith,但 getTypeElement 和 FastClasspathScanner 可以使用。