简体   繁体   English

注释处理器与其他注释处理器创建的Java注释处理编辑文件

[英]Java annotation processing edit file created by annotation processer with other annotation processor

I am trying to generate a config file for my sourcecode via compiletime annotation processing in Java 8.我正在尝试通过 Java 8 中的编译时注释处理为我的源代码生成一个配置文件。

As far as I understand for each Annotation listed in the getSupportedAnnotationTypes class, the processor gets called once.据我了解,对于getSupportedAnnotationTypes类中列出的每个注释,处理器都会被调用一次。

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> set = new LinkedHashSet<>();
        set.add(MCPlugin.class.getCanonicalName());
        set.add(MCAPIVersion.class.getCanonicalName());
        set.add(MCAuthor.class.getCanonicalName());
        set.add(MCAPIVersion.class.getCanonicalName());
        set.add(MCDepend.class.getCanonicalName());
        set.add(MCLoad.class.getCanonicalName());
        set.add(MCLoadBefore.class.getCanonicalName());
        set.add(MCSoftDepend.class.getCanonicalName());
        set.add(MCCommand.class.getCanonicalName());

        return set;
    }

Actually I don't want to process all those annotations with one annotation processer (Would this be the right way?) because it causes problems with the MCCommand annotation.实际上,我不想用一个注释处理器处理所有这些注释(这是正确的方法吗?),因为它会导致MCCommand注释出现问题。 So my plan was to create another annotation processer, which only processes the MCCommand annotations.所以我的计划是创建另一个注释处理器,它只处理MCCommand注释。

My problem is, that the output of both processers should go into the same output file.我的问题是,两个处理器的输出应该进入同一个输出文件。 (Is that even possible?) (这甚至可能吗?)

I have already tried to reopen the resource file like this (this is also how I open it in the first place):我已经尝试过像这样重新打开资源文件(这也是我首先打开它的方式):

FileObject file = filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "config.yml");

which will only create an error or override the existing file.这只会产生错误或覆盖现有文件。

TlDr: How can I make my annotation processer edit a file generated by another annotation processor? TlDr:如何让我的注释处理器编辑另一个注释处理器生成的文件?

Okay, after hours of going through the sourcecode of the Filer and the FileObject I found a solution / workaround.好的,经过数小时浏览FilerFileObject的源代码后,我找到了解决方案/解决方法。

To be able to get access to the JavacFiler you need to have com.sun.tools as dependency.为了能够访问JavacFiler ,您需要将 com.sun.tools 作为依赖项。

Downcast the Filer to a JavacFiler to get access to more methods.Filer向下转换为JavacFiler以访问更多方法。 The filer has a createResource(...) and a getResource(...) method, which seem to do the same but the difference is that createResource(...) opens a FileObject for writing only and the getResource(...) for reading only.文件管理器有一个createResource(...)和一个getResource(...)方法,它们似乎做同样的事情,但不同之处在于createResource(...)打开一个FileObject仅用于写入,而getResource(...)仅供阅读。

So to be able to edit a file from another Annotation Processor you have to do:因此,为了能够从另一个注释处理器编辑文件,您必须执行以下操作:

  1. open the file as read read only以只读方式打开文件
  2. read the filecontent读取文件内容
  3. close the file关闭文件
  4. reopen the file as write only以只写方式重新打开文件
  5. write the old content to it将旧内容写入其中
  6. add more data添加更多数据
FileObject jfo = filer.getResource(StandardLocation.SOURCE_OUTPUT, "", "test.txt");
String msg = TUtils.JFOToString(jfo);    // Reads FileObject as String
jfo.delete();

jfo = filer.createResource(StandardLocation.SOURCE_OUTPUT, "", "test.txt");
TUtils.writeJFO(jfo, msg + "Hallo ich bin Processor 2");    // Writes String to FileObject
filer.close();

This feels like a hack, but I seems to work.这感觉就像一个黑客,但我似乎工作。

I know this is old, but it might help other people.我知道这是旧的,但它可能会帮助其他人。

You can identify the file path and edit it as normal file (delete, truncate, append...).您可以识别文件路径并将其作为普通文件进行编辑(删除、截断、追加...)。

In the process, the file will be created if it does not exist.在此过程中,如果文件不存在,则会创建该文件。 But the content will not be deleted.但内容不会被删除。

    public Path createIdentifyResource(String file) throws IOException {
        try {
            FileObject fileObject = processingEnv.getFiler().getResource(StandardLocation.SOURCE_OUTPUT,
                    "", file);
            return new File(fileObject.toUri()).toPath();
        } catch (IOException e) {
            FileObject fileObject = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT,
                    "", file);
            return new File(fileObject.toUri()).toPath();
        }
    }

The process is simple.过程很简单。 First try to get the resource as if it exists.首先尝试获取资源,就好像它存在一样。 If it fails, it will attempt to create the resource.如果失败,它将尝试创建资源。 Finally, get the URI and convert it to Path.最后,获取 URI 并将其转换为 Path。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM