dsh-code-metrics
v0.1.0
Published
Code metrics for DeepSeek Harness: file_metrics (LOC / comment rate / function count / longest function), complexity (McCabe-approximated cyclomatic complexity per file and per function), hotspots (big × complex files ranked). Heuristic, zero runtime depe
Maintainers
Readme
dsh-code-metrics
DeepSeek Harness 的代码度量工具箱:file_metrics 统计 LOC / 注释率 / 函数数 / 最长函数,complexity 估算圈复杂度(McCabe 近似),hotspots 按「代码行 × 复杂度」挑出最该重构的大而复杂文件。只读、零运行时依赖,启发式扫描而非完整解析。
- 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-code-metrics
- npm:https://www.npmjs.com/package/dsh-code-metrics
功能说明
「哪个文件该优先重构?」、「这段函数是不是太绕?」——看代码行数不够,还要看它的复杂度和体积的综合风险。圈复杂度(cyclomatic complexity)衡量函数里有多少独立执行路径,越高越容易藏 bug、越难改。
本插件用启发式扫描给出三档指标,帮你把代码库的状态量化出来:
- 体量(
file_metrics):总行 / 代码行 / 注释行 / 空白行 / 注释率,以及函数数、最长函数、最长行、文件大小。注释率低往往意味着文档缺失。 - 复杂度(
complexity):文件级与函数级的 McCabe 近似值。判定点 =if/for/while/case/catch/&&/||/??/ 三元;复杂度 = 1 + 判定点数。常用经验:复杂度 ≥ 10 就要小心,≥ 20 强烈建议拆分。 - 热点(
hotspots):代码行 × 复杂度排序,数值越大,代表「又大又绕」,是重构回报最高的地方。
扫描是启发式的:识别 JS/TS 的函数用「字符串/注释剥离 + 括号配平」近似,不是完整 AST 解析,个别边界可能不精确,但用于排序和趋势判断足够。
安装
npm install dsh-code-metrics安装后在 cordis.patch.yml 中加入:
- insert:
- id: code-metrics
name: "dsh-code-metrics"使用说明
file_metrics
统计单个代码文件(或文本)的基础度量。text 传正文或 path 传文件;语言按扩展名自动判定,也可用 lang 覆盖。
来源:(内联文本);语言:javascript(自动判定)
总行数 16;代码行 13;注释行 1;空白行 2;注释率 7.1%
函数 2 个;最长函数 10 行(calc,第 3 行起)
最长行 59 字符;文件大小 300 B参数:text / path;lang;max_chars / max_size。
用户:这个 .py 文件有多长、注释多不多
助手:调用
file_metrics,path传文件,自动识别 python 并统计
用户:这段代码函数数、最长函数是哪个
助手:调用
file_metrics,text传代码(默认按 JS 处理)
complexity
估算文件级与函数级圈复杂度。JS/TS 会列出复杂度最高的几个函数;其他语言只给文件级。
来源:(内联文本);语言:javascript
文件级圈复杂度:6(McCabe 估算,基线 1 + 5 个判定点)
函数复杂度 Top 2:
1. calc 复杂度 5(第 3 行起,10 行)
2. greet 复杂度 2(第 14 行起,3 行)
说明:判定点 = if/for/while/case/catch/&&/||/??/三元;复杂度为启发式估算。参数:text / path;lang;top(默认 5);max_chars / max_size。
用户:这个文件复杂度最高的函数是哪个,排前几名
助手:调用
complexity,path传文件、top=5,看函数级排序
用户:这段逻辑绕不绕
助手:调用
complexity,text传代码,看文件级与函数级复杂度
hotspots
扫目录(或单文件),按「代码行 × 复杂度」把大而复杂的文件排出来。默认只对 JS/TS 家族打分,非 JS/TS 文件计数为跳过。
扫描路径:./src;代码文件 6 个(跳过非 JS/TS 3 个)
热点 Top 5(评分 = 代码行 × 复杂度):
1. src/a.js 代码行 120 × 复杂度 25 = 3000
2. src/b.js 代码行 80 × 复杂度 12 = 960
说明:评分仅作排序参考,不代表一定存在缺陷。参数:path(目录或文件)/ text;exclude(逗号分隔);top(默认 5);max_files / max_size / max_chars。
用户:整个 src 目录里最该先重构的文件有哪些
助手:调用
hotspots,path=src、exclude=node_modules,取评分最高的几个
典型场景
- 重构选点:
hotspots按评分把「大而复杂」的文件列出来,作为重构优先级清单。 - 复杂度门禁:PR 里新增函数复杂度过高时,
complexity给出依据,触发拆分讨论。 - 代码健康周报:定时跑
file_metrics+complexity,跟踪注释率、平均函数复杂度随迭代的变化。 - 接手遗留代码:新团队接手时先
hotspots定位高风险文件,从最有价值处入手。 - 评审辅助:评审时对可疑函数跑
complexity,把「感觉绕」变成「复杂度 18,建议拆」。 - 文档覆盖自查:注释率偏低时提醒补文档 / 加注释。
- 代码体检脚本:CI 里对核心目录跑 metrics,超出阈值即告警。
安全边界
- 只读:三个工具都不写入、不修改、不删除文件;测试含源文件 size/mtime 不变的只读性断言。
- 不访问网络:度量全部在本地完成,无任何外部请求,也不外发源码。
- 不执行代码:只做文本扫描与计数,不
eval、不解析语义、不运行被测代码。 - 二进制与超大文件:跳过 NUL 字节二进制文件与超过
max_size的文件,hotspots还限制max_files。 - 启发式结论,非权威:函数识别用括号配平近似,复杂度是 McCabe 估算——可能漏识别(如个别箭头 / 解构参数)或多计(字符串里的关键字已剥离,但 TS 可选参数、泛型可能被当三元)。结果用于排序与趋势判断,不应作为唯一裁决依据。
- 不输出完整敏感内容:度量结果只含行数 / 复杂度 / 函数名等结构化数据,不回显源码正文。
其他插件集成说明
| 协作插件 | 集成方式 | |---|---| | dsh-import-graph | metrics 定位高风险文件后,用 import-graph 看它的依赖影响面 | | dsh-code-check | metrics 给体量 / 复杂度,code-check 做具体 lint 规则,互补 | | dsh-test-report | 高复杂度函数的测试失败率可交叉印证,指引拆分优先级 | | dsh-credential-scan | 重构 / 移动文件前,先扫一遍目标文件是否含密钥 | | dsh-doc-outline | 对生成的 README / 文档跑 metrics 里的注释率,提醒补文档 | | dsh-bench-compare | 重构前后各跑一次 metrics,量化复杂度下降幅度 |
版本说明
- 0.1.0(2026-10-07):初始版本。
file_metrics:总行 / 代码行 / 注释行 / 空白行 / 注释率、函数数、最长函数、最长行、文件大小;多语言注释风格识别,JS/TS 支持函数统计complexity:文件级与函数级 McCabe 近似圈复杂度;判定点 = if/for/while/case/catch/&&/||/??/三元hotspots:目录扫描按「代码行 × 复杂度」排序,支持 exclude / max_files,非 JS/TS 计数跳过- 字符串 / 模板 / 注释先剥离再做括号与关键字统计,避免误判
- 二进制拒绝、多层上限、只读断言
RoadMap
v0.2(计划)
- 增加
diff_metrics:对两次版本的文件度量做差值,量化复杂度 / 注释率变化 - 函数识别扩展到解构参数、默认参数、async 方法等更多箭头 / 方法形态
- 复杂度报告支持
threshold高亮(≥10 警告、≥20 强烈建议)
v0.3(展望)
- 增加
trend:跨时间统计代码量 / 复杂度 / 注释率,输出趋势序列 - 支持更多语言的函数与复杂度识别(Python def、Go func)
- 与 CI 联动:核心目录指标超阈值即拒绝合并
FAQ
Q:圈复杂度是怎么算的?
McCabe 近似:复杂度 = 1 + 判定点数。判定点包括 if、for、while、case、catch、&&、||、??、三元运算符。数值越大代表独立执行路径越多,越难测试和维护。
Q:函数识别准吗?
启发式,大部分常见形态(function、const f = () => {}、method() {})能识别,个别边界(解构参数、带泛型的箭头函数等)可能漏。用于排序和趋势够用,不建议当严格的行号依据。
Q:为什么字符串里的 if / && 不会被误计?
扫描前先把字符串、模板字面量、注释替换为空白(保留换行),再做括号与关键字统计,所以字符串内容不参与判定点计数。
Q:可选链 ?. 和空值合并 ?? 会算成复杂度吗?
?? 算 1 个判定点,?. 不算(已排除);三元 ? : 计入。TS 的可选参数 ?: 可能被近似当成三元,属已知小误差,已尽量用前后字符排除。
Q:hotspots 的评分合理吗?
代码行 × 复杂度 是常用的「风险体积」启发,只反映「又大又绕」的程度,不代表有 bug。具体是否重构,还需结合测试、依赖、业务重要性综合判断。
Q:非 JS/TS 文件能算复杂度吗?
file_metrics 支持多语言的行 / 注释统计;complexity 对非 JS/TS 只给文件级估算(无法识别函数)。hotspots 默认只对 JS/TS 家族打分。
Q:注释率怎么算?
注释行 ÷(代码行 + 注释行)。整行注释与块注释按行计入;代码 // 注释 这类混行算代码行。
Q:文件很大会不会卡?
hotspots 跳过超过 max_size(默认 10240 KB)的文件并用 max_files(默认 500)限流;单文件工具也有 max_size 保护。
源码与发布地址
- 源码:https://github.com/geeklei/dsh-plugins/tree/main/dsh-code-metrics
- npm:https://www.npmjs.com/package/dsh-code-metrics
许可证
MIT
