警告:在最后一轮中创建的类型为“[在此处插入类]”的文件不会受到注释处理

时间:2012-04-10 18:28:09

标签: java java-7

我将现有代码库切换到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);
}

这意味着什么以及我可以采取哪些步骤来清除此警告?

感谢。

3 个答案:

答案 0 :(得分:3)

警告

  

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

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

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

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

  

这意味着什么以及我可以采取哪些步骤来清除此警告?

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

可采取哪些措施?检查注释处理器:

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

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

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

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

答案 1 :(得分:2)

OpenJDK test case中出现此警告,因为处理器使用“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;
    }

我稍微修改了原始示例代码。添加了诊断注释“File'Gen'created”,将“*”掩码替换为“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 打印有关初始和后续注释处理轮次的信息。

答案 2 :(得分:0)

我探索了java 7编译器选项,我发现了这个:

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

Source

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