资讯详情

Unison 中 `dependents` 与 `delete.term` 的联动使用:fix4898 回归测试解读

📅 2026/10/10 8:40:11 | 华诺云谱 👁 阅读
Unison 中 `dependents` 与 `delete.term` 的联动使用:fix4898 回归测试解读
编程语言编译器语言运行时开发工具【免费下载链接】unisonA friendly programming language from the future项目地址https://gitcode.com/gh_mirrors/un/unison点击查看免费下载本篇文章以仓库中的回归测试 transcriptfix4898.md为主体深入讲解 Unison 命令行工具 UCM 中「查看依赖关系 → 按编号删除定义」的完整工作流包括dependents如何列出某个定义的全部直接依赖者、delete.term如何消费这些编号参数、删除前如何做安全校验以及出错后如何通过undo/reflog回退。读者将学会用一套可复现的脚本安全地清理代码库中的死代码并理解其背后的源码实现原理。一、这份 transcript 在测什么fix4898.md位于 unison-src/transcripts/idempotent/ 目录属于 Unison 仓库中「幂等 transcriptidempotent」测试体系的一部分。这类文件不是普通的说明文档而是一段可执行的命令行回放脚本UCM 会按顺序执行其中ucm代码块里的每条命令并把真实输出与预期输出比对以此充当回归测试。该文件对应 GitHub issue #4898文件名中的 fix4898 即修复编号。它验证的核心场景非常聚焦在一个定义double之上构建另一个依赖它的定义redouble用dependents double查出依赖者借助dependents输出的编号参数1. redouble直接用delete.term 1删除它确认删除成功并提示undo/reflog撤销路径。整个脚本只有约 50 行但它串起了 UCM 中「依赖查询」与「定向删除」两个高频能力的联动——这也是它作为回归测试的价值所在一旦编号参数传递、删除命令解析或输出渲染发生回归该 transcript 会立刻失败。二、完整可复现脚本以下是从原文完整继承的脚本可直接在 UCM 会话中逐步执行 builtins.merge Done.double : Int - Int double x x x redouble : Int - Int redouble x double x double xLoading changes detected in scratch.u. double : Int - Int redouble : Int - Int Run update to apply these changes to your codebase. add Okay, Im searching the branch for code that needs to be updated... Done. dependents double Dependents of: double Terms: 1. redouble Tip: Try view 1 to see the source of any numbered item in the above list. delete.term 1 I deleted these terms: 1. redouble Tip: You can use undo or use a hash from reflog to undo this change.脚本流程分四步合并内置库 → 编写并加载两个定义 →add写入代码库 → 查询并删除。下面逐条拆解每个环节的命令语义与底层实现。三、逐条命令解析3.1builtins.merge准备内置库transcript 的第一条命令是builtins.merge。它将 Unison 语言的内置类型与函数如Int、Nat、等合并进当前分支使得后续.ur文件中的Int - Int类型注解可以正常解析。所有以builtins.merge开头的 transcript 都遵循同一约定测试从“空代码库 全量内置定义”的干净状态开始。3.2 编写定义并检测变更紧接着的 Unison 代码块定义了double : Int - Int double x x x redouble : Int - Int redouble x double x double x其中redouble调用了double构成一条「redouble依赖double」的边。UCM 加载scratch.u后:added-by-ucm标记表示这些输出是由工具自动追加到 transcript 中的列出新增的两个定义并提示Run update to apply these changes——此时改动还只存在于暂存文件尚未写入代码库。3.3add把定义写入代码库add将 scratch 文件中的定义持久化到当前项目分支。注意其输出中有Okay, Im searching the branch for code that needs to be updated...即使新定义本身没有依赖待更新的既有定义UCM 仍会例行扫描分支确认无需更新后报告Done.。这与add的实现有关——它需要在提交前检查新定义是否引用了代码库中已存在的名称。3.4dependents double查询直接依赖者 dependents double Dependents of: double Terms: 1. redouble Tip: Try view 1 to see the source of any numbered item in the above list.这是整个测试的关键步骤。dependents命令查询给定定义的直接依赖者输出中1. redouble是一个「编号参数numbered argument」后续任何接受名称参数的命令如view 1、delete.term 1、edit 1都可以直接用这个编号代替冗长的完整名称或哈希。3.5delete.term 1按编号定向删除delete.term是限定为「只删除 term不碰类型」的删除命令1直接引用上一步dependents输出列表中的第一项redouble。删除成功后I deleted these terms: 1. redouble Tip: You can use undo or use a hash from reflog to undo this change.删除提示附带了两条回退路径undo撤销上一步操作或从reflog项目分支的因果哈希历史中找回先前的状态哈希以恢复。这也印证了删除操作在 UCM 中不是破坏性的——代码库历史causal hash 链始终可回溯。四、dependents命令的源码实现dependents的处理函数是handleDependents位于 unison-cli/src/Unison/Codebase/Editor/HandleInput/Dependents.hs。从源码结构看它有两个分支handleDependents hq do codebaseRefs - resolveHQName hq if defnsAreEmpty codebaseRefs then handleFileDependents hq else handleCodebaseDependents codebaseRefshandleCodebaseDependents当名字能在代码库中解析到时走数据库查询路径。核心调用是Operations.directDependentsWithinScope (Branch.deepDefnsIds namespace) ...即只在当前项目分支范围内查找直接依赖者这对应另一份 transcript delete-namespace-dependents-check.md 中修复的 #4997 回归此前delete.namespace会错误地检查整个代码库而非当前分支。handleFileDependents当名字在代码库中找不到时回退到「最近一次类型检查通过的 scratch 文件」中查找——这覆盖了「某个定义及其全部依赖者已被移出命名空间、只存在于文件里例如一次失败的 update 之后」的常见场景。源码还处理了一个重要细节依赖索引目前只支持「类型」粒度因此如果被查询的依赖集合中包含构造器代码会额外做一次“水合hydrate”校验逐个读取依赖者的实际 term/type过滤出真正直接引用目标集合的条目Dependents.hs 中的Set.filterM分支。4.1 编号参数是怎么来的dependents输出之所以能被delete.term 1消费是因为处理函数在返回结果前调用了(dependentNames.types dependentNames.terms) map (SA.HashQualified . HQ.toHQ . fst) Cli.setNumberedArgs见 Dependents.hs。setNumberedArgs把本次查询结果注册为「编号参数上下文」此后命令解析器遇到1、2等纯数字时会依次映射到列表中的哈希限定名hash-qualified name。这正是view 1/delete.term 1能直接工作的机制——transcript 里的Tip: Try view 1...就是该机制对用户的提示。4.2 输出渲染「Dependents of: double … Terms: 1. redouble」这段输出由 unison-cli/src/Unison/CommandLine/OutputMessages.hs 中的ListDependents分支渲染实际排版函数为listDependentsOrDependencies同文件 L4455-L4514。要点包括标题固定为Dependents of: target与dependencies命令共用同一排版函数仅labelStart参数不同按Types:/Terms:分节每节用P.numberedList生成编号列表末尾的Tip: Try view 1...会在“目标定义不在 scratch 文件时”追加因为view目前无法直接查看 scratch 文件中的定义见该函数中的注释OutputMessages.hs。五、delete.term的依赖安全校验delete.term由 unison-cli/src/Unison/Codebase/Editor/HandleInput/Delete.hs 中的handleDelete处理。transcript 里删除能成功是因为redouble是唯一依赖double的定义删掉它不会留下任何「无名字的悬空依赖」。源码中的判定逻辑是dependents - Operations.directDependentsWithinScope scope nameless if defnsAreEmpty (zipDefnsWith Set.difference Set.difference dependents targetIds) then ... -- 可以安全删除 else ... -- 存在目标之外的依赖者拒绝删除见 Delete.hs也就是说删除前会计算「将要失去最后一个名字的定义集合nameless」的直接依赖者再减去本次删除目标本身如果差集为空所有依赖者都是被删对象删除放行否则进入失败分支。5.1 删除失败时会发生什么如果delete.term的目标仍有外部依赖者UCM 不会硬删。失败分支Delete.hs会计算传递闭包Operations.transitiveDependentsWithinScope找出所有受影响的定义基于当前分支创建一个update-*命名的临时 update 分支把所有依赖被删定义的代码以-- The definitions below depend on the deleted definitions./-- Please fix the errors and run update.的注释头写回 scratch 文件提示DeleteFailure让用户修复后再update。这种「拒绝 转储到 scratch 引导 update」的设计保证了代码库中永远不会出现名称悬空的定义。另外还有delete.term.forcehandleDelete True分支可绕过检查但源码注释明确说明它主要用于删除构造器或清理lib.*等特殊场景日常不建议使用。六、相关能力的延伸围绕「依赖者」这个主题仓库中还有若干可交叉验证的资料HTTP API 版本api-dependents.md 展示了GET /api/projects/scratch/branches/main/getDefinitionDependents?name...接口支持按名称或纯哈希0qbc2dfom7查询依赖者并以 JSON 返回results数组无依赖者时返回空数组。dependents/dependencies对拍测试dependents-dependencies.md 覆盖了类型、构造器、scratch 文件回退等边界场景并明确指出「对构造器的依赖者查询目前会退化为报告其所属结构类型的依赖者」。edit.dependents命令edit-dependents-command.md 演示了edit.dependents Foo会把Foo及其传递依赖者一并装入 scratch 文件适合批量迁移场景。命名空间删除的依赖检查delete-namespace-dependents-check.md 是 #4997 的回归测试展示delete.namespace在删除仍被引用的命名空间时如何列出Dependency / Referenced In并拒绝操作。七、小结fix4898.md用一条极简脚本锁定了 UCM 的核心工作流dependents负责“看见依赖关系”delete.term负责“安全地移除定义”二者通过编号参数机制无缝衔接。从源码看这一体验背后是handleDependents对“代码库 / scratch 文件”双来源的解析、directDependentsWithinScope的按分支范围查询、setNumberedArgs的编号上下文注册以及handleDelete在删除前的依赖差集校验与失败时的“转储 update 引导”策略。对于日常使用者这套脚本本身就是最佳实践模板删除任何可能被引用的定义前先dependents摸底再放心地用编号删除万一删错undo与reflog随时可以还原现场。赞分享编程语言编译器语言运行时开发工具【免费下载链接】unisonA friendly programming language from the future项目地址https://gitcode.com/gh_mirrors/un/unison点击查看免费下载相关推荐Unison 延迟引用与幂等回归测试深入解读 fix1926 TranscriptUnison 延迟引用与幂等回归测试深入解读 fix1926 Transcript 本篇指南聚焦 Unison 仓库中一份极具代表性的幂等idempoten编程语言编译器语言运行时开发工具Unison 回归测试解读Doc2 文档块中的 {name} 引用如何安全渲染fix5506Unison 回归测试解读Doc2 文档块中的 {name} 引用如何安全渲染fix5506 本篇文章以 Unison 仓库中的回归测试转录文件 unis编程语言编译器语言运行时开发工具Unison 回归测试解析fix2358 与 delay.impl 调用约定修复Unison 回归测试解析fix2358 与 delay.impl 调用约定修复 导读 fix2358 是 Unison 语言仓库当前仓库 gh_mirro编程语言编译器语言运行时开发工具上一篇M1 Mac电池管理利器Battery工具安装与使用指南下一篇DLSS Swapper 使用指南三步切换游戏 DLSS 版本并安全回退创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑