18

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

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

快速搜索显示没有人遇到此警告。

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

从 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);
}

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

谢谢。

4

3 回答 3

5

警告

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

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

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

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

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

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

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

1)你真的必须在注释处理器的最后一轮使用 filer.createClassFile / filer.createSourceFile 吗?通常在代码块内使用文件管理器对象,例如

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

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

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

于 2013-04-19T22:38:09.487 回答
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 打印有关要求处理器处理哪些注释的信息。
-XprintRounds打印有关初始和后续注释处理轮次的信息。

于 2012-04-12T10:08:15.130 回答
0

我浏览了 java 7 编译器选项,发现了这个:

-implicit:{class,none} 控制为隐式加载的源文件生成类文件。要自动生成类文件,请使用 -implicit:class。要禁止生成类文件,请使用 -implicit:none。如果未指定此选项,则默认为自动生成类文件。在这种情况下,如果在进行注释处理时生成了任何此类文件,编译器将发出警告。如果明确设置此选项,则不会发出警告。请参阅搜索类型。

来源

您可以尝试隐式声明类文件吗?

于 2012-04-11T19:59:35.490 回答