news 2026/9/13 3:05:41

ESLint no-warning-comments 规则详解:用注释规范拦截 TODO、FIXME 与 XXX

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESLint no-warning-comments 规则详解:用注释规范拦截 TODO、FIXME 与 XXX

ESLint no-warning-comments 规则详解:用注释规范拦截 TODO、FIXME 与 XXX

【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint

本篇技术指南以 ESLint 内置规则no-warning-comments为核心,讲解如何通过配置termslocationdecoration三个选项,在代码评审与发布前自动拦截注释中遗留的 TODO、FIXME、XXX 等警示性词汇,并结合仓库源码与测试用例深入剖析其匹配原理(大小写不敏感、整词匹配、装饰字符跳过等),帮助你在实际项目中快速落地这一"注释卫生"检查。

为什么需要禁用警示性注释

开发者在编写尚未完成或需要复查的代码时,常常会随手留下注释作为标记。最常见的形式如下:

// TODO: do something // FIXME: this is not a good idea

这些注释的本意是提醒"这块代码还没有就绪、还需要复查",但问题在于:它们很容易被遗忘。代码进入生产环境时,这些 TODO/FIXME 往往仍然残留在源码中,既不美观,也容易掩盖真正的问题。no-warning-comments规则的作用,就是把这些警示性词汇当作"定时炸弹"来排查——只要注释中出现了配置的词汇,ESLint 就立即报告错误,促使开发者在代码达到生产就绪状态前,要么修复代码、要么删除注释。

该规则在 lib/rules/no-warning-comments.js 中实现,其规则类型为suggestion(建议型规则),默认不包含在 recommended 配置中,需要显式开启(见 docs/src/_data/rules.json)。

Rule Details:规则如何工作

简单来说,这条规则会检查源码中的全部注释,凡是注释内容中包含配置项里指定的任一词汇(term),就会产生一条违规报告。它遍历注释节点的方式非常直接——在Program()节点事件中取出所有注释,过滤掉 Shebang 后逐一检查:

Program() { const comments = sourceCode.getAllComments(); comments .filter(token => token.type !== "Shebang") .forEach(checkComment); }

其中checkComment会调用commentContainsWarningTerm对注释内容逐一进行正则测试,命中的每个词汇都会触发一条报告,消息模板为:

Unexpected '{{matchedTerm}}' comment: '{{comment}}'.

一个值得注意的细节是:规则会豁免 ESLint 自身的指令注释(如/* eslint no-warning-comments: "error" */)。源码中通过astUtils.isDirectiveComment(node)/\bno-warning-comments\b/u正则双重判断,只有当注释本身就是配置本规则的指令时才跳过,否则即使是/* eslint one-var: 2 */这类其他规则指令,只要其内容命中了配置的词汇(例如将eslintone加入 terms),依然会被报告(参见 tests/lib/rules/no-warning-comments.js 中的对应测试)。isDirectiveComment的实现位于 lib/rules/utils/ast-utils.js。

Options:三个配置项详解

该规则接受一个对象字面量配置,共三个选项:

选项类型默认值说明
termsstring[]["todo", "fixme", "xxx"]要匹配的警示词汇列表
locationstring"start"匹配位置,可选"start"(注释起始处)或"anywhere"(注释任意位置)
decorationstring[][]location"start"时,注释起始处会被忽略的装饰字符

terms:自定义警示词汇

terms是可选的词汇数组,默认值为["todo", "fixme", "xxx"]。匹配规则有两条关键约束:

  • 大小写不敏感fix既能匹配FIX,也能匹配fIxMe这类混合大小写写法。测试用例中专门验证了// any fIxMe/* any FIXME */均会命中(见 tests/lib/rules/no-warning-comments.js);
  • 整词匹配(word boundary)fix可以匹配FIX,但不会匹配fixingaffix这类包含该词作为子串的单词。

词汇还支持由多个单词组成,例如配置"really bad idea"就可以匹配包含这一整句的注释。

location:匹配位置

location默认值为"start",即只检查注释的起始位置。这里的"起始"指的是跳过空白、换行以及decoration中指定的字符之后的第一处内容。另一个可选值是"anywhere",此时会在注释的任意位置查找词汇。

decoration:起始装饰字符

decoration默认为[],仅在location: "start"时生效。许多开发者喜欢用连续的星号、斜杠等字符美化注释(如/***** TODO ... *****/或 JSDoc 风格的多行注释/** ... */),这些"装饰性"字符如果不忽略,会干扰start位置对词汇的识别。配置decoration后,注释起始处的任意空白序列与这些字符都会被跳过。location"anywhere"时,此选项会被忽略

默认配置下的代码示例

以下代码演示了默认配置{ "terms": ["todo", "fixme", "xxx"], "location": "start" }的行为。

不正确的代码示例(应当被报告):

/*eslint no-warning-comments: "error"*/ /* FIXME */ function callback(err, results) { if (err) { console.error(err); return; } // TODO }

上面的多行注释以FIXME开头、行注释以TODO开头,两处都会命中默认词汇,因此都被判为错误。

正确的代码示例(应当通过检查):

/*eslint no-warning-comments: "error"*/ function callback(err, results) { if (err) { console.error(err); return; } // NOT READY FOR PRIME TIME // but too bad, it is not a predefined warning term }

这里NOT READY FOR PRIME TIME并不在默认的terms列表中,且默认location: "start"模式下,位于注释中段的内容本来也不会被检查,因此代码通过检查。

组合 terms 与 location:匹配任意位置

termslocation: "anywhere"组合,可以做到在注释全文中查找警示词汇,适合对注释质量要求更严格的团队。

不正确的代码示例,配置为{ "terms": ["todo", "fixme", "any other term"], "location": "anywhere" }

/*eslint no-warning-comments: ["error", { "terms": ["todo", "fixme", "any other term"], "location": "anywhere" }]*/ // TODO: this // todo: this too // Even this: TODO /* * The same goes for this TODO comment * Or a fixme * as well as any other term */

// TODO: this// todo: this too中的词汇位于注释开头,// Even this: TODO中的词汇位于注释末尾,多行块注释中的TODOfixmeany other term分布在正文各处——由于anywhere模式会在任意位置查找,以上全部会被报告。

正确的代码示例,同样的配置:

/*eslint no-warning-comments: ["error", { "terms": ["todo", "fixme", "any other term"], "location": "anywhere" }]*/ // This is to do // even not any other term // any other terminal /* * The same goes for block comments * with any other interesting term * or fix me this */

这里的关键在于整词匹配的边界行为:

  • to do中间有空格,不是一个完整词,不会命中todo
  • any other term中间的空格序列被正则压缩处理(源码中以/\s+/u折叠空白),但termany other之间被空白隔开,并非连续的any other term,因此不命中;
  • any other terminalany other后面紧跟terminal而不是term,整词边界使term无法命中;
  • fix me thisfixme被空格分隔,不是fixme
  • 注意:location: "anywhere"模式下decoration选项会被忽略。

Decoration Characters:处理装饰字符

location为默认的"start"时,decoration可以指定一组在注释起始处被忽略的字符。

不正确的代码示例,配置为{ "decoration": ["*"] }

/*eslint no-warning-comments: ["error", { "decoration": ["*"] }]*/ //***** todo decorative asterisks are ignored *****// /** * TODO new lines and asterisks are also ignored in block comments. */

第一条注释虽然以//*****开头,但星号作为装饰字符被忽略,后面的todo依然会被定位到注释"起始处";第二条块注释起始处的换行、星号同样被跳过,TODO仍然命中。

不正确的代码示例,配置为{ "decoration": ["/", "*"] }

/*eslint no-warning-comments: ["error", { "decoration": ["/", "*"] }]*/ ////// TODO decorative slashes and whitespace are ignored ////// //***** todo decorative asterisks are also ignored *****// /** * TODO new lines are also ignored in block comments. */

当同时把/*加入decoration后,//////这类斜杠装饰、*****这类星号装饰以及换行都会被忽略,注释"起始"处的词汇照样命中。

正确的代码示例,配置为{ "decoration": ["/", "*"] }

/*eslint no-warning-comments: ["error", { "decoration": ["/", "*"] }]*/ //!TODO preceded by non-decoration character /** *!TODO preceded by non-decoration character in a block comment */

!不在decoration列表中,也不是空白字符,因此它无法被跳过,导致TODO不再位于"起始处",两条注释都不会被报告。这正是decoration机制的边界所在:起始处只能被空白与显式声明的装饰字符跳过

源码级原理:正则如何生成

为了深入理解上述行为,我们来看规则核心的convertToRegExp函数(见 lib/rules/no-warning-comments.js)。每个配置的词汇都会被转成一个正则:

  • location: "start"时,前缀为^[\s<decoration字符>]*,即允许起始处出现任意空白与装饰字符,然后紧跟转义后的词汇本体;
  • location: "anywhere"时,若词汇以单词字符开头,则前缀为\b(词边界);若以单词字符结尾,则后缀为\b
  • 正则标志固定为iu——i提供大小写不敏感,u提供 Unicode 大小写折叠,这正是fIxMeFIX都能被识别的原因;
  • 词汇中的正则特殊字符会先经escape-string-regexp转义,因此把[litera|$][aeiou]这类含特殊字符的字符串当作词汇也完全安全(测试见 tests/lib/rules/no-warning-comments.js 与 tests/lib/rules/no-warning-comments.js)。

例如默认配置下TODO的匹配正则形如/^[\s]*todo\b/iu;配置decoration: ["*"]后则变为/^[\s\*]*todo\b/iu

另外,报告消息中的注释内容有一个 40 字符的展示上限(源码常量CHAR_LIMIT = 40):报告时会按空白分词拼接注释文本,超过 40 个字符的部分用...省略。这在超长或含多行内容的注释上体现得很明显,例如测试中// TODO: something really longer than 40 characters的报告内容被截断为"TODO: something really longer than 40...",超长 URL 注释甚至直接显示为"..."(见 tests/lib/rules/no-warning-comments.js)。

如何开启该规则

由于该规则不在eslint:recommended中,需要手动在配置文件里开启。在 flat config(新版 ESLint 默认)中:

// eslint.config.js export default [ { rules: { "no-warning-comments": "error", // 自定义配置示例 "no-warning-comments": ["error", { "terms": ["todo", "fixme", "xxx", "hack"], "location": "start", "decoration": ["*", "/"] }] } } ];

在旧的 eslintrc 风格配置中:

{ "rules": { "no-warning-comments": ["error", { "terms": ["todo", "fixme", "xxx"], "location": "anywhere" }] } }

严重级别同样支持"warn""error"。该规则的schema校验(见 lib/rules/no-warning-comments.js)还约束了:location只能是"start""anywhere"decoration中每个字符必须是单个非空白字符(pattern: "^\\S$")、至少 1 项且不能重复。需要特别注意的是,由于decorationminItems: 1约束,传空数组[]会被判定为配置非法,不配置该选项时应直接省略。

When Not To Use It:何时不该用

no-warning-comments并非放之四海而皆准,文档明确给出了两类"不适用"场景:

  1. 历史包袱过重的大型代码库:如果代码库在开发时没有"禁止使用警示词汇"的约定,历史遗留的 TODO/FIXME 可能多达数百条。此时一次性开启会产生海量警告/错误,如果你没有时间全部修复,反而会掩盖其他更有价值的警告,或让人对警告"脱敏"、不再关注。
  2. 词汇本身过于常用:同理,不要把注释语言里高频出现的词汇配置进terms。例如中文注释里常见的"待办""问题"等泛化词,或与业务领域强相关、必然反复出现的词,配置进去只会导致噪音。

建议的落地方式是从"warn"级别开始,配合location: "start"与保守的terms列表逐步推行,待存量注释清理完毕后再升级为"error"

小结

no-warning-comments用一套极其轻量的正则机制,把"注释卫生"纳入自动化检查管线:默认拦截todo/fixme/xxx,支持大小写不敏感与整词匹配,支持在start/anywhere两种位置检查,并可用decoration优雅处理各种装饰性注释风格。配合源码中 lib/rules/no-warning-comments.js 的正则生成逻辑与 tests/lib/rules/no-warning-comments.js 中 600 余行的完整测试用例,你可以精准预测它对任何注释的判定结果,将其作为代码评审前的一道自动防线。

【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 3:03:42

Shell命令的七层解码:从输入到系统调用的完整执行链

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/13 3:03:40

质数判定、分解质因数与筛质数:C++ 实现与优化全解析

刷算法题或者做数论相关项目的人&#xff0c;基本都绕不过质数这个概念&#xff1a;质数判定、分解质因数、筛质数这三件事&#xff0c;表面上看起来是三个独立问题&#xff0c;实际上背后是同一个数学事实的三种应用——一个合数一定存在一个不超过自身平方根的质因子。这句话…

作者头像 李华
网站建设 2026/9/13 3:02:54

营销自动化多源数据OLAP架构演进与实战指南

做营销自动化的同学应该都撞过同一堵墙&#xff1a;运营同事非常兴奋地跑过来说&#xff0c;"我想圈一下昨天加购但没付款、并且过去30天打开过App超过5次、最好还看过A商品详情页的用户&#xff0c;给他们推一张100减10的券。"听起来平平无奇对吧&#xff1f;但在你…

作者头像 李华
网站建设 2026/9/13 3:01:20

电驱系统开发实战:从功率标定到NVH与可靠性避坑指南

我在这行干了十几年&#xff0c;从最早做工业伺服电机&#xff0c;到后来一头扎进新能源车用电驱系统&#xff0c;见过的、踩过的坑确实不少。平时在各种技术群里&#xff0c;大家聊得最多的是谁的功率密度高、谁的转速能拉到两万五&#xff0c;但很少有同行愿意静下心来聊聊那…

作者头像 李华
网站建设 2026/9/13 3:01:18

用 ce-explain 在改动前理解某子系统的实现方式与设计原因

用 ce-explain 在改动前理解某子系统的实现方式与设计原因 【免费下载链接】compound-engineering-plugin Official Compound Engineering plugin for Claude Code, Codex, Cursor, and more 项目地址: https://gitcode.com/GitHub_Trending/ev/compound-engineering-plugin …

作者头像 李华