如何配置 VS Code 和 Gradle 以通过 Gradle Protobuf 插件使用生成的 Java 代码?

Mat*_*lke 4 java protocol-buffers gradle gradle-plugin visual-studio-code

我正在尝试将 Protobuf 与 Google 的官方 Gradle 插件、Gradle、VS Code 和小型 Java 应用程序一起使用来测试工作流程。

我无法让 VS Code 识别生成的 Java 源代码,并且在终端中,当我尝试使用 Gradle 构建应用程序时,也无法让 Gradle 识别代码。

当我尝试引用生成的代码时,VS Code 显示此信息:

VS Code,编辑名为 App.java 的 Java 文件,其中文本“Person”显示红色下划线

当我尝试构建时,Gradle 显示以下错误:

> Task :app:compileJava FAILED
/home/mattgbi/vscode-gradle-protobuf-repro/app/src/main/java/vscode/gradle/protobuf/repro/App.java:14: error: cannot find symbol
        System.out.println(Person.class);
                           ^
  symbol:   class Person
  location: class App
1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 405ms
4 actionable tasks: 1 executed, 3 up-to-date
Run Code Online (Sandbox Code Playgroud)

我知道我需要添加导入App.java才能使用该类Person。但是,当我尝试调用 VS Code 代码完成工具来执行此操作时,如上所述,代码完成无法帮助我执行此操作。

但是,如果我手动输入 import 语句,VS Code 会说找不到它:

VS Code 错误提示找不到包

然而,此时,Gradle 能够使用 import 语句(即使 VS Code 呈现错误)并且能够完成构建:

> ./gradlew build

> Task :app:compileJava
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

BUILD SUCCESSFUL in 1s
13 actionable tasks: 10 executed, 3 up-to-date
Run Code Online (Sandbox Code Playgroud)

这是一个完整重现问题的 GitHub 存储库:https://github.com/mattwelke/repros/tree/main/vscode-gradle-protobuf-repro

以下是我遇到此问题时完成的步骤:

  1. 使用创建项目gradle init。选择“应用程序”并将所有设置保留为默认值。
  2. 按照https://github.com/google/protobuf-gradle-plugin中的说明将插件添加到我的项目中。将“buildscript”部分添加到文件顶部build.gradleplugins文件部分上方。plugins在部分内添加行id "com.google.protobuf" version "0.8.18",在该部分的行下方id 'application'protobuf {添加从文件底部开始的块,以便我可以让 Gradle 下载并使用它自己的protoc二进制文件。
  3. 按照 Protobuf 的 Java 教程 ( https://developers.google.com/protocol-buffers/docs/javatutorialmessage Person { ) 操作,将页面顶部附近的代码添加到新文件中的应用程序中app/src/main/proto/message.proto
  4. ./gradlew build在 VS Code 终端中构建。
  5. 观察生成的源代码,app/build/generated/source即使控制台中显示错误package com.google.protobuf does not exist
  6. 将依赖项protobuf-java(来自https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java)添加到文件部分build.gradledependencies的文件,以便我的应用程序生成的 Java 源代码能够引用 Protobuf 库。选择版本 3.21.1,因为它是目前的最新版本。添加了 usingimplementation语法。
  7. 在 VS Code 终端中再次构建应用程序./gradlew build。这次在终端中没有观察到错误。
  8. App.java尝试在(下src)中编写引用生成的Person类的源代码。VS Code 找不到它。
  9. 尝试在 VS Code 终端中再次构建应用程序./gradlew build。Gradle也找不到源代码。
  10. 手动添加 import 语句到App.java. 观察 VS Code 显示有关仍然无法找到包的错误。
  11. 尝试在 VS Code 终端中再次构建应用程序./gradlew build。Gradle也找不到源代码。这次 Gradle 成功了。剩下的唯一问题是 IDE 如何识别所有代码(期望的是所有代码,包括生成的代码,都被识别)。

Mat*_*lke 5

我的问题是我没有配置 Gradle(通过build.gradle)来包含生成代码所在位置的新源集。VS Code 在检测到 Gradle 时读取 Gradle 配置以设置类路径,并在检测到它时禁用手动调整类路径,因此配置 Gradle 是唯一的选择。

在将源集添加到 Gradle 配置之前:

在将源集添加到 Gradle 配置 1 之前访问类路径设置

在将源集添加到 Gradle 配置 2 之前访问类路径设置

在将源集添加到 Gradle 配置之前访问类路径设置 2 3

将其添加build.gradle到底部后:

sourceSets {
  main {
    java {
      srcDir 'build/generated/source/proto/main/java'
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

通过 Gradle 设置 1 添加到类路径后

通过 Gradle 设置 2 添加到类路径后

另外,删除app/build目录并运行后./gradlew build再次运行后,我发现我必须从 Java 扩展运行“删除工作区”命令才能使我的工作区恢复到健康状态,其中生成的代码可以被 VS Code 识别。

在阅读插件的自述文件后,我意识到这是问题所在(https://github.com/google/protobuf-gradle-plugin)并阅读他们关于覆盖源集的说明后,我意识到这是问题所在。由于对 Gradle 有点陌生,我忘记了源集的重要性。自述文件描述了插件如何动态地为生成的代码目录设置源集。

我认为因为 VS Code 没有调用任何 Gradle 任务来完成 Java 代码完成等(我认为它使用 Eclipse 工具),但因为它显然使用 Gradle 配置来配置它与 Java 的行为方式,这是解决我的问题的关键是通过在我的文件中显式指定它来手动告诉 VS Code 有关新源集的信息build.gradle