警告:在上一轮中创建的类型“[在此处插入类]”的文件将不受注释处理

2022-09-02 14:02:40

我将现有的代码库切换到Java 7,并不断收到此警告:

warning: File for type '[Insert class here]' created in the last round 
  will not be subject to annotation processing.

快速搜索显示,没有人命中此警告。

它也没有记录在javac编译器源代码中:

From OpenJDK\langtools\src\share\classes\com\sun\tools\javac\processing\JavacFiler.java

private JavaFileObject createSourceOrClassFile(boolean isSourceFile, String name) throws IOException {
    checkNameAndExistence(name, isSourceFile);
    Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT);
    JavaFileObject.Kind kind = (isSourceFile ?
                                JavaFileObject.Kind.SOURCE :
                                JavaFileObject.Kind.CLASS);

    JavaFileObject fileObject =
        fileManager.getJavaFileForOutput(loc, name, kind, null);
    checkFileReopening(fileObject, true);

    if (lastRound) // <-------------------------------TRIGGERS WARNING
        log.warning("proc.file.create.last.round", name);

    if (isSourceFile)
        aggregateGeneratedSourceNames.add(name);
    else
        aggregateGeneratedClassNames.add(name);
    openTypeNames.add(name);

    return new FilerOutputJavaFileObject(name, fileObject);
}

这是什么意思,我可以采取哪些步骤来清除此警告?

谢谢。


答案 1

警告

警告:在上一轮中创建的类型“[在此处插入类]”的文件将不受注释处理

意味着您正在运行一个注释处理器,使用javax.annotation.processing.Filer实现(通过javax.annotation.processing.ProcessingEnvironment提供)创建新的类或源文件,尽管处理工具已经决定了它的“在最后一轮”。

这可能是问题(因此是警告),因为生成的文件本身可能包含注释处理器忽略的注释(因为它不会再进行一轮)。

以上应该回答您问题的第一部分

这是什么意思,我可以采取哪些步骤来清除此警告?

(你自己已经想通了,不是吗:-))

可以采取哪些步骤?检查注释处理器:

1)你真的必须在最后一轮的 annotaion 处理器上使用 filer.createClassFile / filer.createSourceFile 吗?通常,在代码块中使用 filer 对象,例如

for (TypeElement annotation : annotations) {
...
} 

(在方法过程中)。这可确保注释处理器不会处于其最后一轮(最后一轮始终是具有一组空注释的处理器)。

2)如果你真的无法避免在最后一轮中写入生成的文件,并且这些文件是源文件,请欺骗注释处理器并使用filer对象的“createResource”方法(以“SOURCE_OUTPUT”作为位置)。


答案 2

OpenJDK 测试用例中,由于处理器在最后一轮使用“processingOver()”来写入新文件而产生此警告。

public boolean process(Set<? extends TypeElement> elems, RoundEnvironment renv) {
        if (renv.processingOver()) { // Write only at last round
            Filer filer = processingEnv.getFiler();
            Messager messager = processingEnv.getMessager();
            try {
                JavaFileObject fo = filer.createSourceFile("Gen");
                Writer out = fo.openWriter();
                out.write("class Gen { }");
                out.close();
                messager.printMessage(Diagnostic.Kind.NOTE, "File 'Gen' created");
            } catch (IOException e) {
                messager.printMessage(Diagnostic.Kind.ERROR, e.toString());
            }
        }
        return false;
    }

我修改了一下原始示例代码。添加了诊断说明“文件'Gen'创建”,将“*”掩码替换为“org.junit.runner.RunWith”,并将返回值设置为“true”。生成的编译器日志为:

Round 1:
input files: {ProcFileCreateLastRound}
annotations: [org.junit.runner.RunWith]
last round: false
Processor AnnoProc matches [org.junit.runner.RunWith] and returns true.
Round 2:
input files: {}
annotations: []
last round: true
Note: File 'Gen' created
Compilation completed successfully with 1 warning
0 errors
1 warning
Warning: File for type 'Gen' created in the last round will not be subject to annotation processing.

如果我们从日志中删除我的自定义注释,则很难说文件“Gen”实际上是在“第2轮”(上一轮)创建的。因此,基本建议适用:如果有疑问 - 添加更多日志。


此页面上还有一些有用的信息:http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javac.html

阅读有关“注释处理”的部分,并尝试通过编译器选项获取更多信息:
-XprintProcessorInfo 打印有关要求处理器处理哪些注释的信息。
-Xprint轮次 打印有关初始和后续注释处理轮次的信息。


推荐