IntelliJ IDEA не видит классы, сгенерированные из файлов protobuf в подпроекте

У меня есть проект Gradle с модулями. moduleA содержит только файлы protobuf и создает файл jar с классами, сгенерированными из файлов .proto. moduleB зависит от moduleA (implementation project(':moduleA')).

moduleA
│   build.gradle
│   src
│   └───main
│       └───proto  <-- proto file defining gRPC services
moduleB
│   build.gradle
│   src            <-- code dependent on classes generated from moduleA
build.gradle

Проект работает хорошо, если я создаю/запускаю его из Gradle.

Проблема: IntelliJ IDEA не видит классы, сгенерированные из moduleA в источниках moduleB (импорт выделен красным).

Вопрос: Как заставить IntelliJ IDEA правильно распознавать классы, созданные из .proto файлов?

Я использую IntelliJ IDEA 2020.2.4 (Ultimate Edition).

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
0
3 678
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это то же самое, что и использование прототипа сгенерированного кода в том же модуле, он должен быть там первым, прежде чем его сможет подобрать IDE.

Такие зависимости не могут быть разрешены статически. Сгенерированные прототипы классов доступны только после сборки moduleA. Вам нужно будет собрать moduleA хотя бы один раз (и при необходимости обновить импорт IDE), чтобы сделать сгенерированный код доступным для moduleB.

moduleA строится автоматически каждый раз, когда строится moduleB. Но я также пробовал собирать moduleA вручную - не помогает.
Sasha Shpota 10.12.2020 08:41

В какое место модуль А генерирует исходные файлы? Этот каталог определяется IDE как тип исходного каталога? Можете ли вы поделиться примером проекта?

Andrey 10.12.2020 09:24

- модуль A строится автоматически каждый раз, когда строится модуль B. Не в этом дело. Компиляция всегда может найти сгенерированный код во время сборки. Но вы хотите, чтобы IDE забрала сгенерированный код перед сборкой moduleB. Тогда у вас должен быть сгенерированный код в moduleA available. - Этот каталог определяется IDE как тип исходного каталога? Protobuf-gradle-plugin имеет интеграцию с IDEA, каталог для сгенерированного кода будет автоматически помечен как модуль srcDirs.

voidzcy 10.12.2020 20:08

Обязательно обновите импорт IDE (на панели инструментов Intellij Gradle нажмите «Повторно импортировать все проекты Gradle») после создания кода в moduleA.

voidzcy 10.12.2020 20:13

@voidzcy Я создам пример проекта и поделюсь им с вами. Обновление проекта, его пересборка, пометка каталога сборки как исходного каталога - все это не помогло. Мне пришлось вручную добавить каталог в Grade, как это было предложено в другом ответе

Sasha Shpota 11.12.2020 15:45

Конечно, вы можете открыть проблему на github, если у вас есть минимальный воспроизводимый проект.

voidzcy 12.12.2020 09:40
Ответ принят как подходящий

Чтобы среда IDE разрешала классы и импортировала их из зависимого модуля, эти классы должны существовать и располагаться в исходном каталоге зависимого модуля. Похоже, что классы создаются в каталоге, который IDE не распознает как исходный каталог. Попробуйте добавить этот сгенерированный каталог в качестве исходного набора Gradle. В файл сборки Gradel модуля A добавьте:

sourceSets {
    main {
        java {
            srcDirs = ['build/generated/source/proto/main/java']
        }
    }
}

где 'build/generated/source/proto/main/java' - каталог, в котором генерируются исходники.

Для IntelliJ IDEA есть связанная проблема: IDEA-209418.

Плагин protobuf-gradle-plugin добавляет сгенерированный код в модель IDEA: github.com/google/protobuf-gradle-plugin/blob/… Это должно работать из коробки (и я пробовал это сам). Единственное, сгенерированный код уже должен быть там.

voidzcy 10.12.2020 23:39

@voidzcy Я использую Quarkus. Он генерирует код в другой каталог. Может быть, поэтому Идея не выбирает его.

Sasha Shpota 11.12.2020 15:38

Мы можем сделать что-то подобное для нескольких исходных папок — sourceSets.main.java.srcDir new File(buildDir, 'build/generated/source/proto/main/java')

Avinash Kadam 14.02.2022 16:16

Расположение классов, сгенерированных из файлов .proto, изначально не известно Intellij. Подключаемый модуль Gradle com.google.protobuf регистрирует исходные каталоги с помощью сгенерированного кода, чтобы Intellij мог видеть, когда подключаемый модуль Gradle idea применяется в файле build.gradle модуля A.

См. советы IntelliJ IDEA для плагина com.google.protobuf gradle документацию по плагину protobuf gradle.

Эта настройка работает для меня с Intellij IDEA 2021.1.

Краткий ответ: примените плагин idea gradle к модулю A.

Другие вопросы по теме