Gradle 无法使用 annotationProcessor 生成的源代码编译代码

Gradle can not compile the code with the generated sources by annotationProcessor

如何使用 annotationProcessor 生成的源代码使 gradle build/compile 成为一个项目?

我有一个包含 2 个模块的项目

app-annotation -> 是定义一个注解和 AbstractProcessor

后继者的模块

app-api -> 包含带有前一个模块注释的实体

我们的想法是为每个实体生成默认的 CRUD 存储库和服务,如果需要也可以扩展一些服务。

问题是,它会生成所有需要的 java 文件(甚至 Intellij Idea 也能看到这些文件),但是一旦我想扩展其中一项服务,它就会在编译时失败,因为我在编译我的 class 时明白没有它的 superclass 是在之后生成的。 如果我这样做然后只重新编译我的 class 那么就可以了 此外,eclipse 以某种方式编译时完全没有错误,只有当我使用 Idea 或 gradlew build.

构建时

为了修复它,使用了下面的解决方案,但它看起来不太好

configurations {
    preProcessAnnotation
}

def defaultSrcDir = "$projectDir/src/main/java"
def entitySources = "$projectDir/src/main/java/com/abcd/app/entity"
def generatedSources = "$buildDir/generated/sources/annotationProcessor/java/main"
def generatedOutputDir = file("$generatedSources")

// Explicitly run the annotation processor against the entities
task preProcessAnnotation (type: JavaCompile) {
    
    source = entitySources
    classpath = sourceSets.main.compileClasspath
    destinationDirectory = generatedOutputDir
    options.sourcepath = sourceSets.main.java.getSourceDirectories()
    options.annotationProcessorPath = configurations.getByName("preProcessAnnotation") 
    
    options.compilerArgs << "-proc:only"    
    options.encoding = "ISO-8859-1"
}

// Explicitly specify the files to compile
compileJava {
    dependsOn(clean)
    dependsOn(preProcessAnnotation)

    def files = []
    fileTree(defaultSrcDir).visit { FileVisitDetails details -> 
        files << details.file.path 
    }
    fileTree(generatedSources).visit { FileVisitDetails details -> 
        files << details.file.path 
    }   
    source = files
    
    options.compilerArgs << "-Xlint:deprecation"
    options.compilerArgs << "-Xlint:unchecked"
    options.encoding = "ISO-8859-1"
}
....

dependencies {

    preProcessAnnotation project(':app-annotation')

    // Generate the crud repositories and services
    compile project(':app-annotation')
    implementation project(':app-annotation')
    ...
}

很好奇Lombok、Dagger2等类似的代码生成框架是如何正常运行的

PS。我觉得应该更简单吧?

如您所知 - 任何代码生成都必须在编译之前完成。

更简洁的方法是将代码生成逻辑/注释作为依赖项。

task codeGen {
    // creates under build/genSrc
}

//add to default source set
sourceSets.main.java.srcDir "build/genSrc"

//this has access to all code
compile.dependsOn codeGen

最后,都是我的错,我用错误的方法保存了生成的java文件。

// Wrong!
javax.annotation.processing.Filer#createResource(StandardLocation.SOURCE_OUTPUT, packageName, className + ".java")
// Correct
javax.annotation.processing.Filer#createSourceFile(packageName + "." + className)