我正在尝试编写一个注释处理器来插入类上的方法和字段......留档如此稀疏。我走不远,我不知道我是否正确地接近它。
处理环境提供了一个Filer
对象,它具有创建新源文件和类文件的方便方法。这些工作正常,但后来我试图弄清楚如何读取现有源文件,它提供的只是“getResources”。所以在我的处理器实现中,我这样做了:
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
try {
for (TypeElement te : annotations) {
for (Element element : roundEnv.getElementsAnnotatedWith(te)) {
FileObject in_file = processingEnv.getFiler().getResource(
StandardLocation.SOURCE_PATH, "",
element.asType().toString().replace(".", "/") + ".java");
FileObject out_file = processingEnv.getFiler().getResource(
StandardLocation.SOURCE_OUTPUT, "",
element.asType().toString().replace(".", "/") + ".java");
//if (out_file.getLastModified() >= in_file.getLastModified()) continue;
CharSequence data = in_file.getCharContent(false);
data = transform(data); // run the macro processor
JavaFileObject out_file2 = processingEnv.getFiler().createSourceFile(
element.asType().toString(), element);
Writer w = out_file2.openWriter();
w.append(data);
w.close();
}
}
} catch (Exception e) {
e.printStackTrace();
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
}
return true;
}
我的第一个困惑是我不禁觉得element.asType(). toString()。替换(".", "/") ".java"
(获取合格的类型名称并将其转换为包和源文件路径)不是解决问题的好方法。API的其余部分设计过度,但似乎没有一种方便的方法来检索原始源代码。
真正的问题是,然后编译器会被输出目录中的第二个源文件(“错误:duplicate class”)打乱,现在我被卡住了。
我已经编写了其余的内容——一个宏词法分析器和解析器等等,用于计算一些数据并插入字段值和方法——但它是编译器之外的第一步。除了原始文件不能有. java扩展名(以防止编译器看到它们)之外,这很好。然后我听说注释可以进行代码生成,我认为这会更合适和方便,但我找不到太多指导。
我不知道这个提示是否符合您的需求,但您的想法将与依赖注入(例如Spring)一起工作。
相反,Lombok直接操作抽象源代码树,这比生成源代码复杂得多。这里的问题是,Java编译器模块是公开的(Jigsaw)。
另一种替代方法是使用字节码api,比如ByteBuddy,在运行时代理原始类。如果不想为实例化类编写代码,这也需要依赖项注入。这里的魔力是配置类中类型集合的自动连接字段。如果你对此感兴趣,请告诉我。然后我会在这里补充更多细节。
有点晚了:),但一个解决方案可能是在构建过程中使用Byte Buddy的transformer。参见https://github.com/raphw/byte-buddy/tree/master/byte-buddy-maven-plugin.
注释处理器背后的意图是允许开发人员添加新类,而不是替换现有类。也就是说,有一个bug允许您向现有类添加代码。ProjectLombok利用这一点将getter和setter(以及其他内容)添加到编译的java类中。
“替换”方法/字段的方法是从输入类扩展或委托给输入类。这允许您覆盖/转移对目标类的调用。
因此,如果这是您的输入类:
inputinpl。爪哇:
public class InputImpl implements Input{
public void foo(){
System.out.println("foo");
}
public void bar(){
System.out.println("bar");
}
}
您可以生成以下内容来“替换”它:
我mpl.java:
public class InputReplacementImpl implements Input{
private Input delegate;
//setup delegate....
public void foo(){
System.out.println("foo replacement");
}
public void bar(){
delegate.bar();
}
}
这就引出了一个问题,如何引用InputReplace ementImpl
而不是InputImpl
。您可以生成更多代码来执行包装,也可以简单地调用预期生成的代码的构造函数。
我不太确定你的问题是什么,但我希望这能对你的问题有所启发。
我的处理器中有一个简单的注释,如下所示: 这适用于java文件,但一旦我将文件转换为kotlin,注释的导入就不再有效。为什么? 我需要改变什么才能让他的注释也在Kotlin中工作?从文档中,我可以看到kotlin与java注释100%兼容,所以我有点困惑这里有什么问题...如果处理器不工作,需要调整以与kotlin一起工作,我会理解,但我不知道为什么导入本身不工作... 我说的图书馆在这里:ht
需要注释处理器的帮助。我创建了一个简单的注释处理器,它使用@autoservice注释来检查注释的字段是否为最终字段。但它没有显示任何编译时错误。这是我的配置 注释: 注释处理器: pom文件: 测试文件:
众所周知,我们可以像ProjectLombook的工作人员一样,使用自定义注释和Java注释处理器自动生成代码。但是我们可以从编译的源代码中删除带注释的代码吗? 我试着在网上搜索它,但只出现了“生成代码”主题和“如何生成带有一个注释的服务器”教程。当我在寻找从prod应用程序“编译”调试消息的方法时,我想到了这一点。我可以理解,拥有调试/测试和生产代码不是一个好的实践,但有时需要保持简单。我认为这
我是一名android开发人员,但这对java开发人员来说是一个问题:我在注释处理器行为方面遇到了一些棘手的问题。 现在我一直在开发两个项目:一个-具有自定义注释和处理这些自定义注释的处理器(lib-project)和使用此lib-project(test-project)的测试应用程序。我使用Eclipse IDE作为开发人员工具(ADT)。 我遇到了这样一个麻烦:我的lib项目作为jar li
我喜欢使用Lombok,但它需要在IDEs设置中启用注释处理器。因为开发人员使用不同的IDE,CI/CD有自己的编译流程,而且我真的不想解释初级开发人员为什么需要选中此复选框,我正在寻找一种方法来避免选中此复选框。理想的情况下,我想让一个年轻人来运行git clone,然后/格拉德卢跑。Gradle是否可以完全设置注释处理器(无需手动单击)? 如果它能在比IntelliJ IDEA更多的地方工作,
我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?