使用注释处理器替换代码

2024-01-24

我正在尝试写一个注释处理器 http://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/Processor.html在类上插入方法和字段...并且文档非常稀疏。我没有走得太远,我不知道我是否正确地接近它。

处理环境提供了Filer http://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/Filer.html对象,它具有创建新源文件和类文件的便捷方法。这些工作正常,但后来我试图弄清楚如何读取现有的源文件,它提供的只是“getResource”。所以在我的处理器实现中我这样做了:

@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().replace(".", "/") + ".java"(获取合格的类型名称并将其转换为包和源文件路径)并不是解决该问题的好方法。 API 的其余部分设计得过于过度,但似乎没有一个方便的方法来检索原始源代码。

真正的问题是,编译器会自发地被输出目录中的第二个源文件(“错误:重复类”)扰乱,现在我陷入困境。

我已经编写了其余部分——宏词法分析器和解析器以及用于计算一些数据并插入字段值和方法的东西——但它作为编译器之外的初始步骤运行。除了原始文件不能有 .java 扩展名(以防止编译器看到它们)这一事实之外,这工作得很好。然后我听说注释可以进行代码生成,我认为这会更合适和方便,但我找不到太多指导。


注释处理器背后的目的是允许开发人员添加新类,而不是替换现有类。话虽如此,有一个错误允许您向现有类添加代码。龙目岛计划 http://projectlombok.org/ has 杠杆化的 http://notatube.blogspot.com/2010/11/project-lombok-trick-explained.html这是为了将 getter 和 setter(以及其他东西)添加到编译后的 java 类中。

我用来“替换”方法/字段的方法是从输入类扩展或委托给输入类。这允许您覆盖/转移对目标类的调用。

因此,如果这是您的输入类:

输入Impl.java:

public class InputImpl implements Input{
    public void foo(){
        System.out.println("foo");
    }
    public void bar(){
        System.out.println("bar");
    }
}

您可以生成以下内容来“替换”它:

输入替换Impl.java:

public class InputReplacementImpl implements Input{

    private Input delegate;

    //setup delegate....

    public void foo(){
        System.out.println("foo replacement");
    }
    public void bar(){
        delegate.bar();
    }
}

这就引出了一个问题,你如何引用InputReplacementImpl代替InputImpl。您可以生成更多代码来执行包装,也可以简单地调用预期生成的代码的构造函数。

我不太确定您的问题是什么,但我希望这可以帮助您解决问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用注释处理器替换代码 的相关文章

随机推荐