2026年8月9日 1 分钟阅读

AI 留下的注释该不该删?用 CCN 做一次可回看的语法树级清理

tinyash 0 条评论

AI 编码助手很擅长把意图写进注释:解释显而易见的赋值、保留已经失效的 TODO、重复函数签名,或者在提交信息里留下 Co-Authored-By。问题不在于「注释一定无用」,而在于批量清理时,正则表达式很容易把字符串里的 //、Python 字符串里的 #,甚至与语法黏连的文本一起误删。

Crap Comment Nuker(CCN) 是一个面向这类收尾工作的交互式 CLI。它不尝试判断某条注释有没有价值,而是让开发者逐块确认;其重点是把「找到候选注释」和「允许写回文件」分开。对于刚经历过 Agent 大规模改动的仓库,这种保守策略比一次性格式化更适合做人工复核。

先说明边界:CCN 的许可证为 openSource★,仓库和 npm 元数据都明确说明它不是 OSI 批准的开源许可证,并对商用和署名有额外条件。本文将它视为可审计、可安装的源码可用工具;在团队或商业项目中使用前,应自行阅读 LICENSE.md

它解决的不是「删注释」,而是安全地缩小审查范围

CCN 当前把 JavaScript 系列交给 Acorn 解析,其他已支持语言使用 Tree-sitter。README 列出的语言包括 JavaScript、TypeScript、TSX、Python、Java、Kotlin、Rust、C 与 C++;工具会基于 AST 的注释范围定位候选内容,而不是扫描字符。

这带来两个实际收益:

  1. "https://example.test" 或 Python 字符串中的 # 不应被误当成注释;
  2. 写回前会重新解析文件,并比较代码 token。若一次编辑导致任意代码 token 变化,CCN 的写入门会拒绝这次改动。

第二点尤其重要,但不应被误解为业务正确性证明。它保护的是「此次注释删除没有改变解析后的代码 token」这个边界;它不会判断你删掉的架构说明、许可证头或安全警告是否本来就该保留。因此,交互确认依然是核心步骤。

从 dry-run 开始,而不是直接清空注释

包名已发布在 npm registry,当前可通过以下命令安装:

npm install -g commentnuker

第一次处理仓库,建议先运行 dry-run,并让工具记录你的选择:

ccn ./src --lang python --dry-run --remember

这里有三个值得保留的习惯:

  • --dry-run 只展示候选,不写文件;
  • --remember 会记录已做过的精确选择,后续运行可复用这些决定;
  • 显式写 --lang python,避免混合仓库里把注意力放在不准备本轮处理的语言上。

确认候选范围后,再去掉 --dry-run。若仓库同时有多种语言,可以不传 --lang,由工具在交互界面中选择;首次处理非 JavaScript 语言时,它会征求同意后下载对应的 Tree-sitter grammar,并缓存到本地。README 表示 JavaScript 使用 Acorn,其他语言的 grammar 采用一次下载、后续离线复用的模式。

一次可复查的清理流程

不要把 CCN 放在 Agent 修改后的第一步。更稳妥的顺序是:先让测试、类型检查和人工 code review 确认功能;再清理真正干扰阅读的生成式注释;最后重新跑质量门禁。

例如,一个 Python 服务可以这样执行:

ccn ./src --lang python --dry-run --remember

ccn ./src --lang python --remember

pytest

CCN 的交互模型是逐个「连续注释块」确认,不是按文件一键清空。对它标记为可能靠近方法、类或常量声明的注释,仍应逐条看:有些 TODO 是噪声,有些却是线上事故后的约束说明。对于多行注释、TODO、FIXME、HACK、NOTE 等,宁可先保留,再在专门的文档重构中处理。

一个实用的判断法是,把候选注释分为三类。第一类是代码已完整表达的机械性解释,例如「循环数组」「返回结果」;这类注释通常可删。第二类是实现和意图之间的桥梁,例如为何不能改成并发、为何某个空值必须保留;删前必须在 PR 中确认约束已转移到测试、类型或设计文档。第三类是操作性信息,例如迁移回滚步骤、密钥轮换提醒、事故链接;它们即使语气粗糙,也不应由清理工具自动处理。

因此,审查界面中最重要的问题不是「这是不是 AI 写的」,而是「删除后,下一位维护者还能否从代码、测试或文档推导出同样的约束」。如果答案是否定的,保留它,并在后续整理中改写为更短、更准确的说明。

工具还提供 --demo--limit,其中 --demo 会自动接受交互选择,适合演示而不适合未备份的真实仓库;--limit 5 则可把每个文件的候选块数限制在小范围内,便于先评估效果:

ccn ./src --lang typescript --demo --limit 5

把这条命令当作预览工具更合适。真实清理不应该因「注释看起来像 AI 写的」就自动批准。

把它放进 Agent 工作流时要设两道闸

对于 AI 协作仓库,建议把 CCN 放在一个独立提交中,而不是让 Agent 在实现功能时顺手运行。第一道闸是版本控制:先确认工作区干净,执行后用 git diff 审核,必要时只提交已审过的文件。第二道闸是项目原有的测试、lint 和类型检查;CCN 的 token 不变性检查不能替代这些验证。

还有一个常被忽略的取舍:注释不是纯粹的冗余文本。公共 API 的使用限制、数据迁移的操作顺序、性能陷阱和安全原因,通常比实现细节更值得留下。CCN 适合处理的是重复、过期、自动生成且已经被代码或文档覆盖的说明;它不适合替代团队的文档规范。

如果你需要清理的是 Agent 输出中的大量「解释性碎片」,CCN 的价值在于将风险收束为一连串明确、可拒绝的选择。解析器负责识别结构,写入门负责阻止代码 token 变化,而删除决策仍留给了解业务上下文的人。这比用搜索替换批量抹掉注释更慢一点,却更符合生产仓库的审查节奏。

不要把 token 检查当成测试替身

解析和 token 比对解决的是文本改写工具最危险的一类问题:编辑器把可执行语句、字符串字面量或语法边界一起动掉。但它无法覆盖运行时行为。例如,删除一段注释不会改变 Python 的 AST,却可能让值班人员在下一次迁移时漏掉必须先暂停消费者的步骤;删除一个 TODO 不会让单元测试失败,却可能掩盖尚未完成的权限校验。

所以,实际落地时应把「注释清理」看成可逆的维护改动。让它独立成一个小 PR:变更前保存基线,变更后检查 diff,再执行仓库现有的测试、静态检查和构建流程。若仓库包含生成文件、vendor 目录或迁移脚本,先在较小目录试运行,而不要从仓库根目录开始。CCN 的交互和 --limit 适合控制批次,但团队的 CODEOWNERS、分支保护和 review 规则仍应照常生效。

当一条注释被删除后确实暴露出说明缺口,最好的修复不是恢复长篇解释,而是把约束放到能被持续验证的位置:给不变量补测试、给公开行为补类型或 schema、给部署操作补 runbook。这样下一轮清理时,代码旁边才不会重新长出同样的文字债务。

团队采用前的最小清单

在把这类工具加入日常维护前,可以先做一次很小的试点。选择测试完备、历史较短的目录;让一位熟悉模块的人执行预览,另一位审查最终 diff;随后记录三项结果:候选注释中真正删除的比例、被保留的原因,以及是否发现了本应进入文档或测试的知识。这个记录比「一次删掉多少行」更有价值,因为它能反映团队究竟缺少清理工具,还是缺少清晰的注释准则。

还应把生成式代码与人为维护的代码一视同仁。AI 产生的冗长注释可能更显眼,但人工留下的过期 TODO 同样会误导读者;反过来,AI 生成的注释也可能保留了调用条件、兼容性限制或故障背景。按来源判定价值容易形成新的噪声,按可验证的维护价值判定才更可靠。

最后,不要把注释密度当作代码质量指标。一个边界清晰、测试充分的模块通常不需要重复解释;一个跨系统的支付、授权或迁移模块,即使注释较多,也可能是在保存必要的上下文。CCN 提供的是低风险的筛选与编辑机制,不是要求所有仓库达到「零注释」的规范。把它用于减少读者的认知负担,而不是追求表面整洁,才更容易获得稳定收益。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。