3

我有一些代码在编译时通过 java APT 生成一些服务,在 java9 之前,我通过 APT 生成 java 源代码,并使用 Google AutoService 在 META-INF/services 文件夹下生成服务文件,现在我想升级它以使用Java9模块描述(module-info)放服务定义,但我失败了,见下面的代码:

final String MODULE_FILE_NAME = "module-info";
        Writer srcWriter = null;
        try {
            this._logger.info("Generate module file for -> {}", module.getName());
            JavaFileObject fileObj = builderContext.getFiler().createSourceFile(MODULE_FILE_NAME);
//            FileObject fileObj = builderContext.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", MODULE_FILE_NAME);
            srcWriter = fileObj.openWriter();
            temp.process(model, srcWriter);
        } catch (Exception ex) {
......

编译代码,下面会抛出异常:

> Task :uapi.service:compileJava
注: Loading external handlers...
注:      uapi.annotation.internal.ModuleHandler
注:      uapi.annotation.internal.NotNullHandler
注: Start processing annotations...
注:      Annotation Module on [uapi.service]
注: Generating sources...
注: Generate module file for -> uapi.service
错误: An error was risen when generate module for - uapi.service
错误: Illegal name module-info
错误:     jdk.compiler/com.sun.tools.javac.processing.JavacFiler.checkName(JavacFiler.java:695)
        jdk.compiler/com.sun.tools.javac.processing.JavacFiler.checkNameAndExistence(JavacFiler.java:715)
        jdk.compiler/com.sun.tools.javac.processing.JavacFiler.createSourceOrClassFile(JavacFiler.java:489)
        jdk.compiler/com.sun.tools.javac.processing.JavacFiler.createSourceFile(JavacFiler.java:426)
        uapi.codegen.internal.AnnotationProcessor.generateModule(AnnotationProcessor.java:164)
        uapi.codegen.internal.AnnotationProcessor.process(AnnotationProcessor.java:142)
        org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
        org.gradle.api.internal.tasks.compile.processing.NonIncrementalProcessor.process(NonIncrementalProcessor.java:45)
        org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
        org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.access$401(TimeTrackingProcessor.java:37)
        org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:99)
        org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:96)
        org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.track(TimeTrackingProcessor.java:117)
        org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.process(TimeTrackingProcessor.java:96)
        jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:980)
        jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:896)
        jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1222)
        jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1334)
        jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1258)
        jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:936)
        jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
        jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:147)
...

如果我使用builderContext.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", MODULE_FILE_NAME)生成模块信息文件,可以创建该文件,但似乎 javac 不编译它。

我检查了 Filer 接口的 javadoc,它说:

文件创建方法采用可变数量的参数,以允许将原始元素作为提示提供给工具基础架构,以更好地管理依赖关系。原始元素是导致注释处理器尝试创建新文件的类型或包(表示包信息文件)或模块(表示模块信息文件)。

但是createSourceFilecreateClassFile似乎都只支持 java 类型和包(package-info):

创建一个新的源文件并返回一个对象以允许对其进行写入。可以创建类型或包的源文件。

那么如何在编译时生成模块信息文件呢?或者我必须在编译时使用像 ASM 这样的字节码工具来生成 module-info.class 文件?

4

0 回答 0