diff --git a/MIGRATION.md b/MIGRATION.md index 4b7fb69..26cf425 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -27,8 +27,8 @@ - 领域代码的注释(`//!`、`///`)全部是英文。每个来自 Core 或 Swift 的模块在模块文档里写明来源。 - 宿主侧的接线是分步的:`plugin.json` 现在声明 `backend`(`backend.launch` 为 `packaged`,路径 `bin/lithe-java-backend`),后端把领域命令注册成插件函数, 并承担 API-35 的设置中转(第 5 节:调用方一侧发现并调用 `languageImport.settings`,导出方一侧接收 `languageImport.settingsChanged`, - 再用 `languageServer/notify` 推送给 JDT LS)。语言服务器仍由宿主的 JDT 集成启动(`launch.kind` 为 `runtime`,带 `hostIntegration`), - 改为后端启动要等第 6 节列出的 API-23 等宿主 API 就位,见第 10 节。 + 再用 `languageServer/notify` 推送给 JDT LS)。语言服务器由后端启动(`launch.kind` 为 `backend`,函数 `java.resolveLaunch`, + `requires.serverProcess` 3,不再有 `hostIntegration`),见第 5.8 节;运行/调试/测试的接管见第 10 节。 ## 2. 边界决定 @@ -222,7 +222,7 @@ API-30(调试适配器)、API-37(环境与 l10n)、API-42(内置 Git | 来源 | 新位置 | 状态 | 说明 | | --- | --- | --- | --- | -| `Plugins/mac/Official/JavaSupport/plugin.json@1daaeb525` | `io.github.lithe-idea.java-support/plugin.json` | 已移植并有测试 | 身份改为普通插件:id 从 `dev.lithe.plugin.java-support` 变为 `io.github.lithe-idea.java-support`,`vendor` 改为 `Lithe Community`(`signatureRequirement: none`),删除 `publisherPackage`、`bundledSignatureRequirement` 和 `requires.packageTrust`,见第 9 节;版本仍是 1.1.0。新增后端声明:顶层 `backend`、`pluginFunctions`,`requires.backend: 2`、`pluginFunctions: 1`、`languageServers: 3`,权限 `backend.launch`、`languageServer.request`、`workspace.metadata`,激活事件 `onWorkspaceOpen`,语言服务器的 `requestMethods` 与 `commands`(第 5.7 节);`launch` 和 `hostIntegration` 不变。`repository_pins.rs` 断言社区身份 | +| `Plugins/mac/Official/JavaSupport/plugin.json@1daaeb525` | `io.github.lithe-idea.java-support/plugin.json` | 已移植并有测试 | 身份改为普通插件:id 从 `dev.lithe.plugin.java-support` 变为 `io.github.lithe-idea.java-support`,`vendor` 改为 `Lithe Community`(`signatureRequirement: none`),删除 `publisherPackage`、`bundledSignatureRequirement` 和 `requires.packageTrust`,见第 9 节;版本仍是 1.1.0。新增后端声明:顶层 `backend`、`pluginFunctions`,`requires.backend: 2`、`pluginFunctions: 1`、`languageServers: 3`,权限 `backend.launch`、`languageServer.request`、`workspace.metadata`,激活事件 `onWorkspaceOpen`,语言服务器的 `requestMethods` 与 `commands`(第 5.7 节);`launch` 改为后端解析、删除 `hostIntegration`(第 5.8 节)。`repository_pins.rs` 断言社区身份和后端启动的形状 | | `Plugins/mac/Official/JavaSupport/{icons,templates}/**@1daaeb525` | `io.github.lithe-idea.java-support/{icons,templates}/` | 已移植并有测试 | `backend/tests/repository_pins.rs` 检查清单里每个文件都存在。Maven 图标(`icons/maven*.svg`)、Maven 与 Gradle 构建文件模板(`templates/java/{maven,gradle-kotlin,gradle-groovy,standard-*}`)已移交 Maven、Gradle 插件,本仓库只保留 `templates/java/plain*` 与 Java、Spring Boot 图标,见第 7 节 | | `Plugins/mac/Official/JavaSupport/assemble-package.sh@1daaeb525` | `scripts/assemble-package.sh` | 已移植无测试 | 新增后端二进制:按 `--arch` 用 `cargo build --release --locked -p lithe-java-backend --target ` 编译,`universal` 用 `lipo -create` 合并,放到 `plugin.json` 的 `backend.launch.path`(`bin/lithe-java-backend`)。由 `scripts/verify-package.sh` 校验产物,包括后端存在、可执行、架构与 `--arch` 一致 | | `scripts/macos/prepare/prepare-jdtls.sh@1daaeb525`、`prepare-jdk.sh@1daaeb525` | `scripts/prepare-jdtls.sh`、`scripts/prepare-jdk.sh` | 已移植无测试 | 来源地址和 SHA-256 固定在 `third_party/*/manifest.json`,`repository_pins.rs` 检查格式 | @@ -288,8 +288,8 @@ API-30(调试适配器)、API-37(环境与 l10n)、API-42(内置 Git 状态:**已实现**(Java 一侧)。接口常量、答案校验与合并在 `dj/lsp/languages/jdt_contributions.rs`(纯逻辑,不依赖 SDK), 发现并调用提供方在 `backend/src/plugin_functions.rs`,按工作区维护贡献、推送给 JDT LS、接收 `languageImport.settingsChanged` 的在 `backend/src/settings_session.rs`。宿主中转已由 Core 的 [#1742](https://github.com/1lck/Lithe-IDEA/pull/1742) 实现并合入,后端按已合入的 -方法形状(插件函数协议 4,Rust SDK 0.3.0)调用它,清单已声明(第 5.7 节)。仍缺的只有 `java.configuration.runtimes` 的推送, -它依赖 API-23,见第 6 节。 +方法形状(插件函数协议 4,Rust SDK 0.3.0)调用它,清单已声明(第 5.7 节)。`java.configuration.runtimes` 由启动请求里宿主 +解析出的 `tools.java` 提供(第 5.8 节),不再等 API-23。 ### 5.1 接口函数 ID @@ -319,8 +319,9 @@ API-30(调试适配器)、API-37(环境与 l10n)、API-42(内置 Git 6. **只有至少一个提供方参与(回答或失败)时才推送**:用 `languageServer/notify` 发 `workspace/didChangeConfiguration`, `settings` 整份替换会话里的插件配置。没有任何提供方时什么都不推送——过渡期主仓库的 jdt 宿主集成仍在推送它自己的设置, 插件这边的整份替换会把它覆盖掉;在 Maven/Gradle 插件导出 `languageImport.settings` 之前必须零行为变化。 -7. 推送里 `java.configuration.runtimes` 为空:插件后端目前没有列出 JDK 安装的宿主方法(API-23 `toolchains.list`), - 等它提供后把宿主的候选列表填进来;JDT LS 不会因为缺这个键而删除已登记的 VM。索引根也不在插件推送里,因为 Core 会在插件配置上叠加宿主的索引策略。 +7. 推送里的 `java.configuration.runtimes` 只有一项:宿主在启动请求里解析出的 `java` 工具安装(第 5.8 节),作为默认运行时, + 每次推送都重复它,这样服务器编译的目标和 Run 启动项目用的 JDK 一致。宿主没找到 `java` 工具时不带这个键,JDT LS 不会因为缺键而删除 + 已登记的 VM。列出全机 JDK 仍要等 API-23 `toolchains.list`。索引根也不在插件推送里,因为 Core 会在插件配置上叠加宿主的索引策略。 ### 5.3 超时、失败与状态 @@ -384,8 +385,29 @@ Java 的清单现在这样声明(以已合入的契约 README 为准): - `requires` 写 `backend: 2`、`pluginFunctions: 1`、`languageServers: 3` 和 `serverProcess: 1`,`pluginAPIVersion` 为 4; 后端运行时协商到插件函数协议 4 才能调用中转方法。 - 权限:`backend.launch`、`languageServer.request`(语言服务器列了 `requestMethods`)、`workspace.metadata`(读取工作区根路径需要 `backend` 2)。 -- `languageServers[0]` 声明 `requestMethods: ["workspace/executeCommand"]` 和 `commands: ["java.project.updateSettings"]`; - `launch`(`kind: "runtime"`)和 `hostIntegration`(`id: "jdt"`)保持不变,直到 API-23 就位(第 10 节)。 +- `languageServers[0]` 声明 `requestMethods: ["java/classFileContents", "workspace/executeCommand"]` 和 `commands: ["java.project.updateSettings"]`; + `launch` 是 `{ "kind": "backend", "function": "java.resolveLaunch", "timeoutMilliseconds": 60000 }`(`requires.serverProcess` 3), + 没有 `hostIntegration`、`arguments`、`runtimeDependencies` 和 `initializationOptions`,它们的值都由后端在第 5.8 节的回答里给出。 + +### 5.8 语言服务器启动(serverProcess 3) + +`backend/src/launch.rs` 注册 `java.resolveLaunch`。宿主按契约的 `resolveParams`(`serverID`、`platform.arch`、`stateDirectory`、 +`workspaceStateDirectory`、`logDirectory`、`temporaryDirectory`、`settings`)加工作区上下文调用它,后端: + +- 以后端二进制所在的 `bin/` 的上级为包根,按固定布局定位文件:`language-server/plugins/org.eclipse.equinox.launcher_*.jar`(恰好一个)、 + `language-server/configuration/`、`language-server/lombok/lombok.jar`、`language-server/java-debug` 与 `language-server/java-test/extensions` + 里的扩展包、`runtime//bin/java`。布局常量是 `pub`,`backend/tests/repository_pins.rs` 用它们约束 `scripts/assemble-package.sh` + 和 `scripts/verify-package.sh`,所以 `plugin.json` 不再写这些路径; +- 把 `heapMaxMB`、`logLevel` 两个设置和 `logDirectory/jdt.log` 拼进 JVM 参数(原 `runtimeArguments` 的 `${setting:…}` 与 `${logDir}` 展开), + 把每个工作区的 Equinox 配置复制到 `workspaceStateDirectory` 下再以 `-configuration` 传入,`-data` 指向其中的 `data/`; +- 读取契约里可选的 `tools.java`(宿主按清单 `requiresTools: ["java"]`、按用户选择与发现解析出的安装,带 `home` 与 `version`), + 把它作为 `java.configuration.runtimes` 里唯一且默认的运行时写进 `initializationOptions` 与 `workspaceConfiguration`,并记进设置会话, + 之后每次推送都重复它。原因:Run 用宿主解析的 `java` 工具启动项目,而 JDT LS 默认用自带的 JDK 21 编译,不配默认运行时会出现 + `UnsupportedClassVersionError`(class 65.0 对 61.0)。`tools` 缺失、缺 `home` 或 `version` 时不配置,也不报错; +- 回答 `executable: { kind: "packaged", path }`、`arguments`、`initializationOptions`(原 `hostIntegration` 的 bundles、设置与 + `java_configuration`)、`workspaceConfiguration`、`writablePaths`,以及一个 `language/status` 的就绪门(`service-ready`)。 + +错误码 `launch.invalid_params`、`launch.package_unavailable`、`launch.resource_missing`、`launch.configuration_failed` 与设置中转的错误码不重名。 - 激活事件加 `onWorkspaceOpen`:本插件要主动调用 `languageImport.settings` 并接收语言服务器的状态通知,只导出函数不足以启动后端。 后端是全机一个进程,所有工作区共享。 @@ -396,6 +418,40 @@ Java 的清单现在这样声明(以已合入的契约 README 为准): **信任边界。** 宿主只中转,不传递信任:Maven/Gradle 插件用自己的权限执行,Java 不因此获得权限;Java 只接受 `CONTRIBUTED_SETTINGS_KEYS` 里的键,所以一个提供方既不能改 `java.home`,也不能改别的插件的槽位。 +### 5.9 运行、调试与测试(API-27 / API-29,已实现) + +`backend/src/run.rs` 用三个宿主能力接管了主仓库 Core 与 macOS 原来写死的 Java 运行流程: + +- **行内动作**(`editor/registerActions`,权限 `editor.actions` + `documents.read`):后端在 `initialize` 之后与每次 + `didChangeContexts` 时列出工作区上下文,为每个上下文注册 `.java` 的收集函数 `java.collectActions`。宿主对每个打开的 Java 文档 + 调用它,后端向 JDT LS 请求 `vscode.java.resolveMainMethod` 与 `vscode.java.test.findTestTypesAndMethods`,经领域规则 + `java_run_markers` 得到标记,每个标记一条 `Run '