Сгенерировать исходный код Java в пакете исходного кода моего проекта

У меня есть процессор аннотаций:

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?

Моя сборка градиента:

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'
}

person Leem.fin    schedule 09.10.2019    source источник
comment
Можете ли вы объяснить, почему вы хотите это сделать или чего вы пытаетесь достичь? Если я не ошибаюсь, обработчик аннотаций выдаст ошибку из-за того, что класс, который он пытается создать, уже существует в обычных источниках, поэтому однократный запуск того, что вы просите, будет работать, и каждый раз после этого будет возникать ошибка. Также: добавьте подробности о том, как вы строите (gradle, maven и т. д.), чтобы можно было дать ответ, который поможет вашей настройке.   -  person Colin Alworth    schedule 10.10.2019
comment
Я хочу сгенерировать код в исходную папку в процессоре аннотаций. Я создаю его в своей среде Intelj IDE.   -  person Leem.fin    schedule 10.10.2019
comment
Если вы можете пойти немного дальше и объяснить, почему, я могу попытаться помочь с ответом, в противном случае все, что я могу сказать, это то, что это невозможно или неразумно. Помните, что в IntelliJ, даже если он собирается в каталог build/generated/, вы все равно можете просмотреть этот код. Ожидаете ли вы впоследствии отредактировать сгенерированный код? Зафиксировать его в системе контроля версий? Основан ли на нем другой сгенерированный код? и т. д.   -  person Colin Alworth    schedule 10.10.2019
comment
Я просто хочу знать, можно ли использовать JavaPoet для генерации кода в каталоге src/ вместо каталога build/. Это мотивация моего вопроса, никакой другой причины, это мое любопытство. Я хочу знать, возможно ли это. Да, я хочу потом отредактировать сгенерированный код, возможно ли это? Если это невозможно, это также ответ на мой вопрос. Я обновил свой вопрос с помощью gradle build. Я не знаю, как я могу объяснить дальше.   -  person Leem.fin    schedule 10.10.2019
comment
Краткий ответ: да, это возможно с JavaPoet, но не с процессорами аннотаций. Позже я напишу кое-что более подробное, но вкратце вы просто вызовете writeTo() для другого устройства записи или непосредственно для файла, чтобы заставить его работать в вашем исходном каталоге.   -  person Colin Alworth    schedule 10.10.2019


Ответы (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() не нужны какие-либо существующие источники из того же проекта для запуска , это должно быть довольно просто.

person Colin Alworth    schedule 10.10.2019
comment
Ваш пример javaFile.writeTo("myProject/src/main/java") неверен, такого API writeTo(java.lang.String) в JavaFile нет - person Leem.fin; 11.10.2019
comment
Исправлено, извините за это - я сказал правильное мышление всего двумя предложениями раньше, а затем облажался ... - person Colin Alworth; 12.10.2019
comment
У меня есть пользовательская аннотация, мне нужно обработать аннотированный элемент в процессоре аннотаций, а затем сгенерировать Java-код под src/. Итак, судя по вашему ответу, это невозможно, верно? Как насчет создания кода модульного теста для src/main/teset с процессором аннотаций, возможно ли это? - person user842225; 12.10.2019
comment
Насколько я знаю, вам не повезло @ user842225 - обработчики аннотаций должны работать циклами, иначе они не будут иметь смысла, и компилятор не сможет их вызывать - хотя, если вы создаете в своем каталоге сборки, они одинаково хорошо работают для основного или тест. Реальный вопрос для меня: почему вам требуется генерировать код под src? Если по какой-либо причине вы не можете использовать возможности вашей среды IDE или инструмента сборки для обработки сгенерированных исходных кодов в каталоге сборки, то, похоже, вы должны определить здесь свой собственный инструментарий. - person Colin Alworth; 12.10.2019

Не уверен насчет gradle, но с помощью maven вы можете определить сгенерированный исходный каталог, используя вкладку ниже в плагине maven-compiler-plugin.

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

Для полного примера проверьте ссылку ниже.

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

person Ashok Prajapati    schedule 05.12.2019