ccusage 项目 Rust 代码相似度检测实战:用 similarity-rs 定位重复代码并安全重构
2026/9/20 15:13:04 网站建设 项目流程

ccusage 项目 Rust 代码相似度检测实战:用 similarity-rs 定位重复代码并安全重构

【免费下载链接】ccusagenpx ccusage项目地址: https://gitcode.com/gh_mirrors/cc/ccusage

ccusage 是一个以 Rust 为核心实现的开源 CLI 工具(npx ccusage),其生产代码分布在rust/cratesrust/adapters的多个 crate 中,包含大量 parser、loader、report 模块,天然容易积累重复的函数、impl 方法和并行结构体。本文基于仓库中reduce-similarities技能文档,讲解如何使用 Nix dev shell 内置的similarity-rs工具对.rs文件做相似度扫描、解读分数并制定重构决策。读完本文,你将掌握相似度检测的完整命令组合、每个 CLI 参数的作用边界,以及"哪些重复必须重构、哪些重复应该保留"的分诊方法。

similarity-rs 从哪来:Nix dev shell 中的similarity工具

similarity-rs并不是独立的第三方二进制,而是随 ccusage 的 Nix 开发环境一起提供。在 nix/dev-shell.nix 的buildInputs列表中可以看到similarity被显式加入(第 62 行),与ast-grepripgrepfdjust等开发工具并列:

similarity ast-grep ripgrep fd

因此,工具的实际命令名是similarity(skill 文档中写作similarity-rs,指代同一个 CLI)。使用方式有两种:

  • 已在 Nix dev shell 内(例如通过direnv allow初始化环境后):直接运行similarity-rs
  • 在 shell 之外:需要前缀direnv exec .进入开发环境再执行,例如direnv exec . similarity-rs .

开发环境的初始化与依赖安装由nix/dev-shell.nixshellHook负责:它会比较pnpm-lock.yamlnix/tools/*/bun.lock的时间戳,在 lockfile 更新后自动执行just install,确保工具链与依赖一致(见 nix/dev-shell.nix)。

需要说明的是,这个技能只负责Rust代码的重复检测。TypeScript/JavaScript 侧的重复代码不在本工具职责范围内,应转由typescriptast-grep技能处理(见 .agents/skills/reduce-similarities/SKILL.md 的边界说明,以及 AGENTS.md 中的技能路由表)。

基本用法:一次扫描,两个关键参数

similarity-rs直接对路径执行扫描,默认扫描当前目录.,也可以显式传入路径:

# 扫描整个仓库 similarity-rs . --threshold 0.85 --min-lines 5 # 只扫描某个 crate(例如 codex 适配器) similarity-rs rust/adapters/codex --threshold 0.85 --min-lines 5

--threshold 0.85:相似度门槛

--threshold控制报告的灵敏度,0.85 表示"相似度达到 85% 及以上"的代码片段才会被报告。分数越高说明两段代码越接近:

  • 100% 匹配:完全相同的代码块;
  • 95%~100%:几乎一致,仅少量差异;
  • 85%~95%:结构相同、细节有别。

阈值越高报告越少、越精确;调低阈值可以挖掘更多"形似而神异"的候选,但噪声也会增加。

--min-lines 5:最小片段行数

--min-lines过滤掉过短的匹配。小于该行数的代码(如一两行的赋值)不值得报告,避免把常见的短小惯用法误报为重复。

--experimental-types:补上类型定义这一路

这是本工具最容易踩的坑:函数扫描与类型定义扫描是分开的两趟 pass,因此默认运行会"静默漏掉"并行的 struct 和 enum 定义:

similarity-rs . --threshold 0.85 --experimental-types

也就是说,默认跑一次只覆盖函数、方法层面的重复;如果你正在排查"几个结构体字段完全相同"这类问题,必须加上--experimental-types才会看到结果。技能文档特别提醒:默认运行会静默错过并行的 structs 和 enums,这是代码评审时最常见的漏检场景。

其他辅助参数

  • --print:直接打印匹配到的代码片段,便于肉眼比对,而不是只给出行号或分数;
  • --skip-test:当形如 fixture 的测试函数淹没真实发现时,加上它跳过测试代码,让生产代码的重复浮出水面;
  • --help:查看全部剩余参数(similarity-rs --help)。

分诊(Triage):分数只是起点,不是结论

工具给出的"相似度分数"只是线索,是否值得重构取决于代码的语义角色。技能文档给出了明确的分诊规则,按分数与形态分类:

值得重构的场景

检测形态推荐做法
100% 完全匹配提取共享函数或泛型(shared function / generic)
95%~100% 且跨越不同类型改为带 trait bound 的泛型函数
多个类型上有重复的 impl 方法用带默认实现的 trait 收敛
85%~95% 的 match 分支或错误处理提取共享 helper 或宏(macro)
字段完全相同的并行 struct提取共享基类(base struct)或泛型 struct

这五种形态覆盖了 ccusage 代码库中最常见的重复来源:多个 adapter 的 parser/report 模块之间,往往存在高度相似的 match 分支、错误处理链和字段布局,是--threshold 0.85最值得关注的对象。

应该放过的场景

以下情况通常不要动,强行重构反而降低可读性:

  • 简短的new()构造函数;
  • 简单的From/Intotrait 实现;
  • 任何可以通过derive宏自动生成的样板代码。

这一条与仓库的实际代码风格一致:rust/adapters下的 parser 大量使用#[derive(Debug, Default, Deserialize)]等派生宏(例如 rust/adapters/amp/src/parser.rs 中的类型定义),这类代码正是"derive 已处理、无需手写去重"的典型——它们不应该出现在重构清单里。

报告规范:输出 before/after,而不是分数列表

技能文档对输出提出了明确要求:每个存活的候选(surviving candidate)必须以具体的 before/after 形态报告,而不是罗列一堆相似度分数。原因是:

  • 分数只说明"像",不说明"怎么改";
  • before/after 给出可评审、可落地的重构方案,让代码评审者一眼看出改动意图。

例如,针对一个 100% 匹配的重复,报告应呈现为"重构前:两处相同函数体;重构后:提取为共享函数并两处调用",而不是"发现 3 对相似代码,分数 0.95"。

在评审流程中的定位

reduce-similarities是 ccusage 代码评审工作流中的一个环节,与 .agents/skills/rust/SKILL.md 配合使用——后者在第 33 行明确指出:"拆分大模块或排查重复时,使用reduce-similarities"。典型的触发场景包括:

  • 评审.rs文件时发现重复的函数或 impl 方法;
  • 发现并行定义的 struct 与 enum(需要加--experimental-types);
  • 准备提取共享 helper 之前,先用工具确认重复范围。

整个技能体系通过 AGENTS.md 的路由表与 nix/agent-skills.nix 的打包机制分发:sync-agent-skills会把.agents/skills目录下的技能(含本技能)链接到.claude/skills供 Agent 在任务中按需加载。

小结

similarity-rs在 ccusage 项目中是一把"重复代码探测器":来自 Nix dev shell,一条命令即可扫描整个仓库;--threshold--min-lines控制报告灵敏度,--experimental-types补齐类型定义扫描,--skip-test排除 fixture 噪声。拿到分数后,遵循"100% 提取共享函数、跨类型提取泛型、重复 impl 收敛为 trait、match/错误处理提取宏、并行 struct 提取基类"的分诊规则,同时放过new()From/Into与 derive 样板——最后以 before/after 形态输出重构建议,就能把相似度扫描真正转化为可落地的代码质量改进。

【免费下载链接】ccusagenpx ccusage项目地址: https://gitcode.com/gh_mirrors/cc/ccusage

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询