【问题标题】:Generate java source code under my project's source code package在我项目的源码包下生成java源码
【发布时间】:2020-02-07 04:26:40
【问题描述】:

我有我的注释处理器:

public class MyAnnotationProcessor extends AbstractProcessor {
    ...

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // Here I deal with the annotated element
         ...

        // use JavaPoet to generate Java source file
        TypeSpec generatedClazz = generate_code();
        JavaFile javaFile = JavaFile.builder("com.my.foo", generatedClazz).build();
        javaFile.writeTo(filer);
    }

}

处理上述process回调中的注释元素后,我使用JavaPoet生成Java源代码并为代码创建Java文件。构建我的项目时,除了生成的 java 源代码文件默认转到 build/generated/sources/myApp/com/my/foo 之外,一切正常。如何使生成的 Java 文件位于项目的源代码位置 src/main/java/com/my/foo 中?

我的 gradle 构建:

plugins {
    id 'java'
}

group 'com.my.app'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {

    testImplementation 'junit:junit:4.12'

    implementation 'com.squareup:javapoet:1.11.1'
    implementation 'com.google.guava:guava:28.1-jre'
}

【问题讨论】:

  • 您能否说明您为什么要这样做,或者您想要达到什么目的?除非我记错了,否则注释处理器将出错,它试图创建的类已经存在于正常源中,因此运行你要求的一次将起作用,之后每次都会导致错误。另外:添加有关您如何构建的详细信息(gradle、maven 等),以便做出有助于您设置的答案。
  • 我想在注释处理器中为我的源文件夹生成代码。我在我的 Intellj IDE 中构建它。
  • 如果您可以进一步解释原因,我可以尝试帮助回答,否则我只能说这是不可能或不合理的。请记住,在 IntelliJ 中,即使它构建到 build/generated/ 目录,您仍然可以查看该代码。您希望之后编辑生成的代码吗?将其提交给版本控制?其他生成的代码是否基于它?等
  • 我只是想知道是否可以使用JavaPoet在src/目录下而不是build/目录下生成代码。这就是我提出问题的动机,没有其他原因,这是我的好奇心。我想知道这是否可能。是的,我想在之后编辑生成的代码,可以吗?如果不可能,这也是我的问题的答案。我用 gradle build 更新了我的问题。我不知道我该如何进一步解释。
  • 简短回答:是的,JavaPoet 可以,但不,注解处理器不行。稍后我会写一些更长的东西,但简而言之,您只需在不同的编写器上或直接在文件上调用 writeTo() 以使其在您的源目录中工作。

标签: annotation-processing javapoet annotation-processor


【解决方案1】:

不确定 gradle,但使用 maven,您可以使用 maven-compiler-plugin 中的以下选项卡定义生成的源目录。

<generatedSourcesDirectory>
     ${project.basedir}/src/main/java
</generatedSourcesDirectory>

完整示例请查看以下链接。

https://www.thetechnojournals.com/2019/12/annotation-processor-to-generate-dto.html

【讨论】:

    【解决方案2】:

    坏消息:注释处理器无法做到这一点 - 它们的轮次工作方式的性质意味着在“实际”源所在的同一目录中生成源是没有意义的,因为那些生成的源下次注释处理器运行时将被视为输入。

    好消息:JavaPoet 不知道您实际调用它的方式,因此您可以编写一个简单的 main() 来生成代码,并要求您的 IDE 在构建时调用它,或者将其附加到您的 gradle建造。如果您计划在生成源代码后手动编辑它们,您可能不希望发生这种情况,因为您可能希望保留手动更改,而不是在每次构建时都被覆盖。

    JavaFile.writeTo(...) 方法有几个覆盖,其中只有一个采用注解处理器Filer。使用Filer 有一些优点——很清楚你打算在哪里编写类——但JavaFile.writeTo(File directory) 也意味着以这种方式使用。您不会将您希望 MyClass.java 所在的实际文件传递给它,而只是传递您要写入的源目录。在你的情况下,这大概是javaFile.writeTo(new File("myProject/src/main/java"))

    您可能仍然应该参数化如何调用此 main,以便它知道要使用哪些输入,如何理解您现有的源等。另一方面,如果您的 generate_code() 不需要任何现有的源运行同一个项目,这应该很简单。

    【讨论】:

    • javaFile.writeTo("myProject/src/main/java")的例子是错误的,JavaFile中没有writeTo(java.lang.String)这样的API
    • 已修复,对此感到抱歉 - 我之前只说了两句话,然后就搞砸了......
    • 我有一个自定义注解,我需要在注解处理器中处理被注解的元素,然后在src/ 下生成java 代码。所以,根据你的回答,这是不可能的,对吧?用注解处理器生成单元测试代码到src/main/teset怎么样,有可能吗?
    • 据我所知你运气不好@user842225 - 注释处理器必须循环工作,否则它们将没有意义并且编译器无法调用它们 - 尽管如果你生成到你的构建目录,它们同样适用于“main”或“test”。对我来说真正的问题是:为什么需要在src 下生成代码?如果由于某种原因您无法使用 IDE 或构建工具处理构建目录中生成的源代码,那么您似乎必须在此处定义自己的工具。
    猜你喜欢
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 2015-05-07
    • 2011-06-05
    • 1970-01-01
    相关资源
    最近更新 更多