Skip to content

chore: promote preview to main - #361

Merged
1lck merged 77 commits into
mainfrom
preview
Aug 31, 2026
Merged

chore: promote preview to main#361
1lck merged 77 commits into
mainfrom
preview

Conversation

@1lck

@1lck 1lck commented Aug 31, 2026

Copy link
Copy Markdown
Owner

发布说明

将当前预发布分支 preview 晋级到 main,为下一版正式发布准备代码基线。

说明

  • preview 是持续开发汇总分支;本 PR 包含 v0.3.7 之后累积的开发提交。
  • 已基于当前远端 origin/mainorigin/preview 使用 git merge-tree 检查,未发现文本冲突。
  • 合入后按仓库发版规范创建新的三段式版本标签,并由 macOS/Windows 发布工作流构建产物。
  • Homebrew Cask 元数据会由发布工作流通过独立自动 PR 更新。

请在 CI 全部通过后合入。

Farewell0375 and others added 30 commits August 28, 2026 16:13
Opening a large multi-module Maven workspace left Run and Debug unusable for
as long as the Spring index took, because loadProjectServices awaited it
before loading build-system and run state. Schedule the index instead so run
configurations, test discovery, and the Git refresh that follows no longer
depend on its duration.

Identifying the project during that window was dropped silently, which is
indistinguishable from a broken button. Report the unloaded workspace as an
explicit state, and let the Run and Debug entry points load the project on
demand the way the tool-window entry points already do.

Refs #300
CI 的测试稳定性门禁拒绝了原先的两个 scheduleLoad 测试:轮询里用了真实
Task.sleep,测试替身里用了无界的 DispatchSemaphore.wait()。改成由 actor 模型
保证的同步断言,加上以 objectWillChange 为事件源、带本地超时的等待。

重写后的测试暴露出一个真实缺陷:Swift 的取消是协作式的,reloadTask.cancel()
并不会阻止任务体运行,而 load 里没有取消检查点,所以被取代的那次调度仍然会跑
完一次全量工作区索引,只是结果被 generation 令牌丢弃。为 scheduleLoad 补上
Task.isCancelled 检查,与既有的 scheduleReload 保持一致。

Refs #300
之前只靠编译期类型检查和手动验证,没有测试覆盖这两个入口。

新增的三个测试用一个不可读的工作区让快照返回 unavailable,从而跳过
onSnapshotLoaded,把入口变成唯一能绑定项目的路径。把 AppModel+Development 里
两处 loadProjectServicesIfRunProjectIsUnbound 调用去掉后,Run 与 Debug 两个
测试会失败,而覆盖既有行为的工具窗口测试仍然通过,说明它们确实能抓到回归。

把 objectWillChange 加本地超时的等待器提成 ObservableChangeWaiter,供
SpringFeatureModelTests 与新测试共用,超时收到 5 秒以留出计时预算。

Refs #300
评审指出冷启动入口把"URL 已绑定"当成了"工作区快照已就绪"。快照未完成时
projectFiles 为空,入口仍会绑定 projectURL 并允许确认"识别并生成",而
runConfig.generate 只扫描传入的 paths,于是可能写出缺少 Java 入口的
.lithe/run/generated.json。

把两件事显式分开。新增 ProjectLoadState(idle / loading / bound / ready /
failed):bound 表示已绑定工作区但清单是临时的,只允许读取既有配置;ready 携带
工作区与快照标识,才允许生成。快照标识由 WorkspaceFeatureModel 拥有——它是唯一
应用快照的地方——经 AppModel 与 ProjectDevelopmentFeatureModel 传到 RunService。
snapshotID 缺省为 nil,因此忘记传递的调用方会退到 bound 而不是误判为就绪。

generateRunConfigurations 现在要求当前工作区处于 ready,否则报
projectNotReady(原 projectNotLoaded,改名以覆盖"已绑定但清单不完整")。

MacServiceContainer 增加 workspaceOperations 注入缝,与既有的 moduleStore 等
可选覆盖一致,使 AppModel 层能用可控快照做测试。Search 与本地历史仍使用具体的
RustWorkspaceOperations,它们依赖 WorkspaceOperations 之外的能力。

测试改为断言数据完整性而非仅仅"已绑定":入口测试用受控快照,先阻塞、按下 Run、
断言未就绪且生成被拒且未写出配置,再放行含真实 Java 文件的快照并断言就绪;
ExecutionModuleTests 断言生成实际扫描的清单恰好是快照上报的那份。去掉
RunService 的就绪守卫后,后者会直接暴露 generatedInventories == [[]]。

Refs #300
处理评审的三点。

一、AppModel.swift 与 preview 合并后达到 1806 行,超过 verify-service-boundaries
的 1800 上限。把加载编排移到 AppModel+Development.swift,现为 1781 行。上一轮
本地验证没有先合并 base,所以漏掉了这个失败。

二、snapshotID 放进了 .ready 却没参与比较。同一工作区刷新时,
WorkspaceFeatureModel 在发布新快照与调用 onSnapshotLoaded 之间隔着两个 await,
这段窗口里 RunService 仍持有上一份清单却报就绪,重新识别会漏掉新增的入口。
isReady 现在同时比较工作区与快照标识,snapshotID 为 nil 时一律视为未就绪。

三、加载可能只到 .bound,而运行入口只看 configurationStatus。磁盘上已有配置时
会在完整文件列表与 Maven 信息就绪前直接启动,工具链解析因此缺少 Maven 项目。
运行与调试入口改为要求就绪,未就绪时记下 pendingRunAction 并返回;工作区重建
必然以 loadProjectServices 收尾,由它恢复这次操作,因此不需要轮询或等待。

识别现在统一走 AppModel.generateRunConfigurations,先把服务提升到当前快照再执行。
这是 RunService 内部仍可用自身状态判断的前提。

Refs #300
上一版的入口测试只证明了推迟与恢复,没能覆盖评审要的"已有配置 + 快照阻塞"
子场景:真实存储的 inspect 要经 Rust Core,而 Swift 测试二进制不链接它
(bridge.c 提供 weak 桩,isAvailable 为 false),所以 configurationStatus
无法在测试里变成 ready。

给 MacServiceContainer 增加 runConfigurationOperations 可选覆盖,与已有的
workspaceOperations、moduleStore 等注入缝同类。测试用一个直接报 ready 的替身
构造该前提,并记录 launchPlan 请求次数:快照阻塞期间断言运行被推迟、
configurationStatus 确为 ready、launchPlan 从未被请求;放行快照后断言恢复执行
且就绪。

未选择改为链接 Rust 的真实测试:CI 中没有任何任务在链接 Rust 的情况下执行
LitheTests(verify-rust-core.sh 只跑 cargo test、swift build 与独立的桥接验证
程序),因此这样的测试会永远跳过。仓库中已有 9 处依赖 isAvailable 的跳过测试,
不宜再添。

Refs #300
避免 await 前后快照错配,以及快照已消费后入口仍用旧捕获 defer 导致 Run 永久挂起。
让 rebuild 在挂起点后再次拒绝过期 workspace,并把 workspace 与 snapshot 一并传给 onSnapshotLoaded;ensure 失败时停止生成;直接启动与批量服务入口统一走 readiness 守卫并保留 pending 意图。
Restart 走 ensureRunProjectReady/pending 恢复;入口捕获 workspace 区分 stale 与 waiting,避免旧任务 defer 到新工程或清掉对方 pending。
1lck and others added 29 commits August 30, 2026 11:34
同一路径重开时 URL 相同,旧会话的入口任务与旧 rebuild 都会被判为当前。改为每次 open/close 推进世代,入口任务、await 后的守卫与 rebuild 一并比较 URL + 世代。
…ig-load-ordering

冲突解决:
- RunService:保留本分支的 readiness 查询与上游的 Maven 上下文注入。
- AppModel:删除上游在原位修改的旧 loadProjectServices(at:files:),该实现已迁到
  AppModel+Development.swift 并携带快照身份;上游对它的两处调整(执行模块可缺失、
  加载顺序前移)在新实现中已具备等价行为。

合并后为保持本分支契约所做的适配:
- 上游把会话模块图关停改为不阻塞打开流程的任务,它会在按需激活之后落地,把刚激活的
  执行模块拆掉,导致“开完工程立刻按 Run”的延后动作永远无法恢复。改为在打开/关闭时
  同步登记关停任务,Run/Debug 的按需激活先等待它结束。
- 入口测试原先用挂住工作区扫描来模拟未就绪,扫描运行在协作线程池上,12 条并行时把
  线程池占满:自身耗时从 0.07s 涨到 8s,并把上游若干短期限门等待用例挤超时。改为由
  替身直接报告尚无快照、需要时经 refreshCurrent() 发布,并串行化该套件;工具链探测
  改用注入的替身,测试不再依赖本机 JDK。
…ering

fix(macos): 运行配置加载不再等待 Spring 索引
Wait for the workspace Maven load before planning Maven-backed Run configurations so project profiles, settings, skip-tests, and toolchain paths are applied consistently. Add a deterministic regression test for the pending-load race.

Refs #291
Await active and pending editor saves before Maven goals or Run configurations create their launch plans. Surface actionable failures and cover save ordering, failures, and the in-flight auto-save race.
Preserve explicit workspace ownership across Java LSP launch and Maven reload paths, and expose Maven in activity visibility and localization.
feat(macos): integrate Java Debug into preview
feat(windows): add unified Maven tool window
@1lck
1lck merged commit cb04c34 into main Aug 31, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants