Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f19da73
feat(macos):完善类方法跳转与悬停导航交互
arkleselect Oct 28, 2026
3b6f661
fix(macos): 稳定慢查询期间的 Command 悬停光标
arkleselect Oct 28, 2026
eab023c
fix(editor): present Java files after initial import folding
arkleselect Oct 28, 2026
37fad5a
fix(editor): delay Command hover hints and cancel pending hints on leave
arkleselect Oct 28, 2026
69fdfa4
fix(editor): show Command navigation feedback before semantic lookup
arkleselect Oct 28, 2026
70d1391
fix(editor): exclude non-code tokens from Command navigation
arkleselect Oct 28, 2026
55a46a1
fix(editor): color Java comment delimiters as comments
arkleselect Oct 28, 2026
77dfcc4
Merge branch 'codex/class-method-navigation' into codex/navigation-fe…
arkleselect Oct 28, 2026
d8ae09e
feat(macos): preserve navigation toggle implementation for integration
arkleselect Oct 28, 2026
4ec6223
fix(macos): unify welcome actions and clone remote panels
arkleselect Oct 28, 2026
6aa731b
feat(java-support): own optional class and method navigation lifecycle
arkleselect Oct 28, 2026
c6294f3
fix(navigation): sync plugin opt-out across projects and preserve oth…
arkleselect Oct 29, 2026
a2e5654
Merge latest preview and preserve navigation settings and remote pane…
arkleselect Oct 29, 2026
f2d1a5f
fix(i18n): preserve catalog ordering after preview merge
arkleselect Oct 29, 2026
fef7710
test: align Java generator host capabilities and pin Git fixture branch
arkleselect Oct 29, 2026
e9c5922
fix(remote): resolve daemon startup before attaching concurrent clients
arkleselect Oct 29, 2026
178bab9
fix(windows): provide the optional Java requirements snapshot
arkleselect Oct 29, 2026
8ddb5f9
Merge preview and fix navigation chooser and language policy regressions
arkleselect Oct 29, 2026
952c27c
feat(editor): 类方法跳转默认开启并新增 Java 关键字跳过查询设置
arkleselect Oct 29, 2026
0333e71
fix(matrix): 移除已删除的 editor-navigation fixture 证据路径
arkleselect Oct 29, 2026
e483752
Merge remote-tracking branch 'pr-target/preview' into codex/java-supp…
arkleselect Oct 29, 2026
08b97a5
fix(navigation): 仅对 jar 内库类异步查找 sources jar
arkleselect Oct 29, 2026
4ef8e9d
fix(navigation): 撤回 sources jar 快速路径并保留 this/super 构造器跳转
arkleselect Oct 29, 2026
64e8c18
Merge branch 'codex/java-support-navigation' into codex/pr-1561-ci
arkleselect Oct 29, 2026
8bd4fad
test(macos): align rollback symlink assertion with document errors
arkleselect Oct 29, 2026
93ca120
test(git): 为子模块测试的 git submodule add 放宽超时
arkleselect Oct 29, 2026
45abae0
Merge branch 'preview' into codex/java-support-navigation
arkleselect Oct 30, 2026
eeedc21
Merge remote-tracking branch 'origin/preview' into codex/pr-1561-reso…
1lck Oct 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ macOS 保留用户接受的 `FindBarView` 外观。`EditorChromeModel` 有意不
原编辑器的定义跳转和 Markdown 双向滚动继续走平台已有能力:
- Cmd-click(Windows 为 Ctrl-click)、F12 和右键 Go to Definition 在主/分屏 view 使用同一条带 drain 的请求,
发送该 view 捕获的 UTF-16 位置与 revision,关闭 hold 和切换 model 会取消请求;原生端复核后调用原有导航服务。
- Command 悬停通过只读 `definitionHover` 请求查询现有 LSP/产品导航目标;不改变 caret、焦点、历史或结果面板。
手势复用锁定 Monaco 0.55.1 的 `ClickLinkGesture`,装饰复用 `goto-definition-link` 和宿主已注入的
`editorLink.activeForeground`,不另猜颜色。按键释放、拖动、滚动、移出、失焦、编辑、切换或销毁视图
使旧结果失效;失败不缓存,后续手势可重试。点击继续复用原生定义导航,单目标直接打开,多目标才选择。
同文件目标不等于自身声明:只有点击位置在返回的声明区间内才允许查询实现,否则应直接定位同文件方法。
对照 IDEA Community `24bab9a438efb41bd197b295b87136bb98b0b40c` 的
`platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.kt`
(可导航时使用 `REFERENCE_HYPERLINK_COLOR` 与手形)及
`navigation/actions/GotoDeclarationOnlyHandler2.kt`(单目标直接导航、多目标选择)。
不启用 Monaco 完整 definition contribution:它要求提前加载目标文件到 Web 模型库,会绕开宿主的
虚拟文档、只读路径校验与历史所有权;也不复用依赖 Windows LSP store 的平台手势实现。
WebKit 回归验证装饰范围、实际 CSS、松键清除和悬停无导航副作用,Swift 回归保护同文件调用边界。
macOS 的悬停文档面板通过 `popupStyles` 消费 `lithePopupChrome` 同一组表面/边框/文字/阴影 token 和圆角指标,
不套用工具栏 `HoverTooltip` 的另一种视觉角色。正文读取共享 UI 字体,代码保持编程字体;现有只读 Fonts
adapter 允许随包已有的 Inter OTF,仍校验真实路径在字体目录内,不写发行资源、不影响签名或 delta。
普通悬停延迟为 500 ms,依据同 revision 的 `platform/ide-core-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java`
的 `TOOLTIPS_DELAY_RANGE` 初始值,以及 `platform/lang-impl/src/com/intellij/openapi/editor/HoverPopupContext.kt` 的剩余延迟计算。
Community 的 `CtrlMouseHandler.kt` 在语义结果返回后立即显示提示。根据用户对频繁弹出遮挡代码的反馈,
Lithe 有意改用 Monaco Delayed 模式,沿用 macOS 普通文档的 500ms 延迟;候选词的手形、变色与下划线同步显示,
说明面板仍在语义确认后启动延迟,避免为不可导航候选请求说明。反馈是候选状态,查询失败或无目标时撤销;
候选过滤复用 Monaco/TextMate 的 standard token type,注释、字符串和正则正文不显示导航反馈,
Command 点击也走相同过滤;显式 F12 保留语言服务原有语义。词法状态尚未就绪且需大段同步解析时暂不提示,
避免为高频鼠标移动扫描整个文件,不另写正则猜注释。
点击仍通过真实导航解析,不把候选装饰当作已确认目标。复用 Monaco 的延迟、取消、内容、定位及键盘可访问性,不另建计时器;单目标导航会收起旧结果面板。Windows 宿主没有使用该 macOS 入口,未改其实现。

- Markdown split 将原有 `MarkdownScrollPosition` binding 接回 Monaco,沿用来源与 revision 防回环;
只在该视图启用滚动消息,33 ms 合并连续输入,切换文档或接收预览滚动时撤销旧回传。
滚动消息不改文本或 undo;普通源码编辑不向原生工作台持续发送滚动状态。
Expand Down Expand Up @@ -640,6 +665,17 @@ Swift 同步桥接把内部位置字段编码为 `character`,Rust 要求 `utf1
共用资源构建。代价是新增一条需要逐步收敛的 Web 桥接路径。独立宿主仍仅保存实验副本;
工作台版通过 Lithe 保存真实文件,不能把两者的保存行为混淆。
工作台同步字体大小、字体族、明暗外观、原生配色主题、背景透明状态及折行。

macOS Java 导入区默认折叠使用 Monaco 0.55.1 `foldingImportsByDefault`,由宿主显式启用。
`javaFolding` 桥接复用既有 `AppModel.javaStructure` / Core 的词法结构结果,把零基行号转换为 Monaco
的一基范围;没有新增正则解析器,也不等待 JDTLS 初始化。Core 的 imports 范围要求至少两条导入,
其余类体、方法和注释仅提供手动折叠范围,不默认收起。词法范围的精度沿用现有 Core,若将来需要
完整语义折叠,应替换为已有 LSP foldingRange 能力,不在前端另做 Java 解析。
Monaco 自身保存已应用默认折叠的标志和手动折叠状态,随已有标签页/分屏视图状态恢复;不在每次激活
或输入后执行 foldAll。请求等待已有编辑同步链,原生与前端均拒绝版本、文件位置或模型生命周期已变化
的结果。真实 WebKit 验证初始导入折叠、类体展开、手动展开后切换标签和源码不变;Swift 检查直接调用
Core 验证普通/static 导入的范围及单条导入不产生折叠。Windows 入口未启用这个选项。

默认字体跟随全局 JetBrains Mono 2.304。WebKit 的网页进程不会继承原生进程的
CoreText 注册,因此 `MonacoWorkbenchAssets` 从安装包现有 `Fonts` 目录只读
提供 TTF;编辑器 HTML 用 `@font-face` 引用同一字型,加载后重新度量 Monaco。
Expand Down Expand Up @@ -793,3 +829,81 @@ UTF-16 编辑、保存屏障、Worker 和迟到语义结果;Swift 串行回归
- `macos/Sources/Lithe/Platform/MacOS/MonacoWorkbenchEditor.swift`
- `macos/Sources/Lithe/Models/Editor/EditorDocument.swift`
- `macos/Sources/Lithe/Application/Features/DocumentFeatureModel.swift`


### 悬停说明显隐回归(macOS)

对照 Community `cdc10bf305a5ceb5377c1d919de33e5f009cf15d` 的
`platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.kt` 与
`platform/lang-impl/src/com/intellij/openapi/editor/EditorMouseHoverPopupManager.java`:Command 提示与普通说明
不是同一个显隐状态。已有普通说明时不新建 Command 提示;松开 Command 只关闭本次 Command 打开的提示。
命令点击、Esc、编辑、切换模型、视口滚动、编辑器组件失焦和窗口失焦清理提示及未完成的导航悬停结果。
鼠标进入说明面板、选择文字或点击链接继续交给 Monaco sticky hover 处理,避免用编辑区 mouseleave
无条件关闭交互面板;但尚未显示的延迟提示必须在移出时取消,避免移走后才弹出。所有窗口监听随编辑器销毁移除,迟到结果仍需通过 generation/文档快照检查。
Command 提示采用上游信息标签的 6/6/5/6 内边距,去掉首尾段落额外外边距;外层依旧消费 Lithe 共享
popup chrome,不复制另一套主题。普通说明维持 500ms 和 Monaco 文档排版。
真实 WebKit 生命周期回归检查松键、Esc、滚动、失焦、编辑、切换模型、移入提示及普通说明不受松键影响,
并检查取消后的请求不能重开面板。组件回归不等同于完整应用的人工视觉验收。


### 实现选择器的原生弹窗生命周期(macOS)

`LanguageImplementationChooserView` 原先直接叠在 EditorAreaView 上,既没有原生弹窗的外部点击/Esc
关闭机制,也没有完整焦点归属。现在通过 `litheDropdown` 的持久锚点呈现,关闭 binding 调用 `dismissImplementationChooser()`,仅在选择器仍显示(用户取消)时转交
`closeLanguageNavigationResults()` 重置 operation;选中目标已先隐藏列表,随后到达的关闭回调不能取消正在加载的虚拟源码。插件关闭、切换工作区等强制清理仍无条件重置 operation,迟到结果不能恢复已取消列表。
选中目标后关闭,切换编辑标签同样关闭;键盘上下选择、Return 确认走已有 dropdown 键盘入口,
搜索输入法组合期间不截获确认键。共享 presenter 负责外部点击、Esc、失焦、屏幕边界和监听清理。
外框由共享 `litheContextMenuSurface` 唯一绘制;搜索框与结果行分别使用 `LitheSearchField` 和
`LitheDropdownRowStyle`,去掉独立 7pt 圆角、缩放过渡和至少 220pt 的空白高度,列表按行数收缩。
依据 IDEA Community 的 `platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java`
`showNotEmpty`:用 PopupChooserBuilder 呈现目标列表、选择后导航,并在取消回调中取消后台更新。
本轮只修复选择器的承载和样式;声明/用法/实现的查询语义分流仍是独立待修问题,不能把布局修复当成语义已对齐。
验证:原生共享弹窗回归覆盖深浅主题、菜单与自定义内容的 Esc、关闭后重开、点击外部关闭;相关导航测试同时运行。


Command 悬停的光标反馈不再依赖异步返回后才创建的文字 span:候选词命中时立即在所属编辑视图上设置
指针状态,只覆盖代码行及其子元素;候选词同时显示链接色与下划线,无目标回复再撤销。文字重绘与慢语言服务回复不会
把候选词重新变回编辑光标。无目标/失败的结果在当前手势内保持,防止逐像素移动反复请求造成小手与
I-beam 交替;移出词、松键或文档/视图生命周期变化后可以重新查询。取消同时移除视图指针状态,迟到
响应不得恢复。原生 WebKit 回归用显式请求到达/释放闸门模拟慢服务,检查等待期间、重绘、负结果及松键后
的真实 computed cursor,不使用时间睡眠。


Java 首帧通过统一 `attachModel` 等待 Monaco `FoldingController.getFoldingModel()` 后发布:切换到 Java
模型前仅暂时隐藏该编辑视图,完成 setModel、保存状态恢复及初始折叠后同步 render,再恢复原 opacity/inert。容器用 opacity 隐藏,避免 Monaco 自身重绘覆盖内部 visibility;准备期间 inert 禁止输入。
主编辑器与分屏复用该顺序,同一模型更新和非 Java 文件不等待;不使用固定 sleep,也不重复实现折叠规则。
这消除了先呈现全部 imports、随后异步收起的布局跳变,代价是首次内容呈现等待已有折叠计算;原生请求
仍受现有桥接超时控制,finally 保证错误路径恢复可见性。真实 WebKit 通过折叠 provider 的显式闸门验证
等待期间不可见,完成后的首个可见状态已经折叠,并继续覆盖手动展开状态的标签恢复。


Java TextMate 的 `punctuation.definition.comment` 是注释边界,不是普通代码标点。
共享 `tokenRole` 在通用 punctuation 之前将其映射为 comment,使 `//`、`/*`、`*/` 与正文
使用相同主题色,也保持其注释 token 类型;除法运算符继续使用普通标点规则。
真实 WebKit 在深浅主题验证行注释、块注释和文档注释的前景色及类型,不另外写 CSS 颜色覆盖。


### 定义跳转按需启用(macOS)

Java Support 插件清单提供默认关闭的“启用类和方法跳转(Command+点击 / F12)”,通过 settings 3 的
editorNavigation 声明将设置、默认值及语言归属一起交给插件。唯一值源是现有插件设置存储;编辑器全局
开关已删除。语义解析仍交给插件中的 JDTLS,宿主只实现声明触发的通用手势,不新增 Java 符号索引。既有用法、继承标记、
诊断、补全与普通文档悬停属于独立能力,不随此开关停服,也不把共享语言进程的内存承诺为零。

启用时为每个编辑视图创建 Monaco DisposableStore(上游提供的资源集合);关闭时释放整个集合中的手势、
动作和事件订阅,清理链接装饰、指针与自己拥有的延迟提示。现有分屏同步更新,新分屏读取当前开关。
原生入口同时拒绝关闭期间的定义请求,重置结果面板的 operation;菜单动作也禁用。不能只在鼠标回调中
加一个布尔判断,因为那样仍会保留专属监听。复用 Monaco 的资源集合即可,不需要再造插件加载器。

关闭会使已发出的请求失去发布资格,不再产生新定义请求;已经进入共享语言服务的请求仍按现有的完成/超时
生命周期结束。本轮没有扩展语言服务协议为请求级取消,也不会为取消一个跳转而杀掉共享 JDTLS。
因此这里保证的是关闭后不再开展跳转专属活动,而非关闭瞬间进程 RSS 必须下降或所有在途请求物理中断。

验证:真实 WebKit 测试控制慢请求返回顺序,覆盖关闭、重开、旧回复、重复开关无重复点击和现存/新建分屏;
PluginSettingsTests 验证插件声明、默认关闭、持久化、跨项目通知、禁用撤销、关闭面板和旧操作失效,以及项目模型/插件管理器不被通知订阅保留。未声明开关的其他语言保留既有点击与 F12,不增加悬停查询;WebKit 覆盖 XML 属性、配置文件、其他语言,以及 100 轮开关后监听归零和模型数量稳定。


导航策略使用每份文档的插件语言 ID,而非 Monaco 的语法 ID:`bash` 对应 `shell`、`properties` 对应 `ini`,
不同插件语言也可共用同一种语法。模型保留插件身份;省略语言的同文档更新保持该身份,显式改变身份时即使
语法不变也释放旧手势并使在途语义结果过期。真实 WebKit 回归覆盖别名的开关及悬停、共用语法的主视图/分屏独立策略、
同模型身份切换。Swift 受控回复回归覆盖选择实现 → 关闭回调 → 延迟虚拟源码到达,以及加载期间关闭功能、用户取消。
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
## 决策

- **远程实现只保留一个 crate**:`rust/lithe-remote/` 内部分为 `client`、`protocol`、`server` 三个模块,共用一个版本和依赖入口。协议类型始终可用,Cargo feature(构建时选择哪些代码和依赖)默认只启用 `client`;Core 的正常依赖明确只选客户端,Linux/macOS 的真实服务测试额外启用 `server`。打包必须用 `--no-default-features --features server --bin lithe-remote-server`,不能让工作区其他包的 feature 合并把客户端带入远端发布物。可执行文件仍叫 `lithe-remote-server`,安装路径、握手和协议版本不变;协议单独构建不需要 SHA-256 或主机适配依赖,客户端不引入 `trash` 或服务端平台代码。
- **守护进程启动必须有确定结果**:并发连接可能各自启动候选进程。代理必须等自己启动的候选已经写入会话锁的 PID,或已退出,才连接 socket;不能因为别的候选已发布 socket 就提前握手,否则显式关闭后,迟到的候选还会接管锁并留下新进程。复用已有锁文件和子进程退出状态,不增加协议、目录或长期监听;等待沿用启动期限,失败时终止并回收本次启动的候选,成功的守护进程继续跨断线保留。
- **占位根目录**:`MacRemoteWorkspaceRoots` 在 `Application Support/Lithe/RemoteWorkspaces/<连接 id>/<远程路径哈希>/<文件夹名>` 创建一个空目录,用它作为工作区根。目录名是远程文件夹名,所以项目名显示正确。它不在 app bundle 里,不影响签名和 Sparkle 增量包;里面没有用户数据,跨启动保留,让按根目录保存的项目状态得以延续。
- **注册表**:`RemoteWorkspaceRegistry` 记录每个占位根对应的连接、远程路径和 Core 会话 id。打开远程项目时登记,同一个根再次打开时,旧会话会被替换并断开。
- **路由**:组合根(`MacServiceContainer`,负责组装依赖的地方)把本地实现包进 `RemoteRoutingWorkspaceOperations` 和 `RemoteRoutingFileOperations`。路由层对端口里的**每个**方法都显式转发:如果只覆盖一部分,没覆盖的方法会悄悄走协议扩展里的默认实现,本地文件的行为就变了。
Expand Down Expand Up @@ -48,6 +49,10 @@

## 考虑过的备选方案

### 看到 socket 就立即连接,或延长退出等待

已有 socket 只证明某个守护进程已就绪,不证明本次启动的候选已退出。迟到候选能在显式关闭之后创建新会话,延长测试等待无法消除这条时序。代理等待自己的候选明确去留会增加少量有界轮询,但保证已完成连接不再遗留尚未作出启动决定的候选。

### 保留三个 crate,或合并后默认编译全部模块

三者总是随同一份协议一起维护,没有独立发布需求,保留三个包只会增加依赖入口和路径维护。全部默认编译又会把只适用于 Linux/macOS 的服务端带进 Windows 客户端。采用单包加可选 feature,减少顶层模块而保留平台和依赖边界;代价是验证必须覆盖纯协议、纯客户端、纯服务端和两端一起启用四种组合,并继续检查远端二进制大小。
Expand Down Expand Up @@ -82,6 +87,8 @@

## 验证

- `./scripts/remote/verify-remote-workspace.sh --tests` 覆盖守护进程启动与退出:用未释放标准输入的候选进程和已过期截止时间,确定性验证已有 socket 不能绕过启动决定,并验证锁归属本候选、候选已退出两条成功路径;并发连接集成测试确认显式关闭后锁释放。Linux CI 与 macOS 本机分别覆盖各自适配器,本机通过不能代替 Linux 验证。

```bash
./scripts/macos/test/test-macos.sh --filter RemoteConnections
./.agents/skills/write-stable-tests/scripts/test-stability-macos.sh -- --filter 'RemoteWorkspaceRoutingTests|RemoteDirectoryObservationTests'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,13 @@ cargo test --manifest-path rust/Cargo.toml -p lithe-core remote::
- `rust/lithe-core/src/remote/`
- `rust/lithe-remote/src/client/launch.rs`
- `scripts/remote/build-remote-servers.sh`


### 远程开发主面板的统一呈现

主入口从 SwiftUI sheet 改为已有 `LitheCenteredPopup` 的有标题表单模式,与打开项目和 Git 表单
共用窗口外框、居中定位、父窗口事件隔离及 `animationBehavior = .none`;不再使用系统 sheet 展开动作。
取消与保存成功通过显式回调复位 `isRemoteConnectionsPresented`,原生窗口关闭走同一 binding;
内容消失仍调用 `feature.close()` 清理连接任务。输入框、按钮样式、业务动作与面板尺寸保持原实现,
认证提示与目录浏览的内部 sheet 不在本次迁移范围内。验证复用 `LitheCenteredPopupTests` 的打开、
父窗口跟随、无动画、关闭清理与嵌套选择器场景,以及远程连接/路由回归;真实 SSH 登录仍需独立验收。
Loading
Loading