
ESLintno-duplicate-case规则全解杜绝 switch 中重复的 case 测试表达式【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint本篇技术指南围绕 ESLint 内置规则no-duplicate-case展开深入讲解它如何发现并阻止switch语句中重复的case测试表达式duplicate test expressions覆盖规则配置、判定原理、正确与错误示例、边界情况以及何时应当关闭该规则。读完本文你将能准确理解该规则的检测语义在项目配置中正确启用它并能识别其词法等价token 级相等判定策略的适用范围与局限。该规则是 ESLint 内置核心规则之一规则实现位于 lib/rules/no-duplicate-case.js官方文档对应文件为 docs/src/rules/no-duplicate-case.md。规则概述这是怎样一个问题型规则在 JavaScript 的switch语句中如果多个case子句的测试表达式相同往往意味着开发者复制了一段case代码却忘记修改测试表达式属于典型的复制粘贴遗留缺陷。no-duplicate-case规则正是为此而生它禁止在switch语句的case子句中出现重复的测试表达式。从规则元数据meta可以看出它的定位见 lib/rules/no-duplicate-case.jstype: problem该规则报告的是可能引发程序逻辑错误的问题代码而非单纯的风格问题docs.recommended: true该规则已被官方eslint:recommended推荐配置收录开箱即用即可生效schema: []规则不接受任何配置选项messages.unexpected: Duplicate case label.命中时输出统一的报错信息重复的 case 标签。在官方文档中该规则的rule_type同样标记为problem见 docs/src/rules/no-duplicate-case.md与源码中的元数据保持一致。何时会触发判定的核心机制该规则只在遍历到SwitchStatementswitch 语句节点时进行检测。核心逻辑位于 lib/rules/no-duplicate-case.js其工作流程可以概括为遍历当前switch语句的每一个case子句跳过default子句其test属性为null将当前case的测试表达式test节点与之前已出现的所有测试表达式逐一比对若发现与之前的表达式等价equal则在该case子句处报告unexpected错误否则将当前表达式记入已见集合继续向后检测。等价判定基于 token 的逐字比较两个测试表达式是否相同的判定函数equal见 lib/rules/no-duplicate-case.js做了两件事先比较两个 AST 节点的type类型不同直接判为不同类型相同则调用工具函数equalTokens做进一步比较。equalTokens定义在共享工具模块 lib/rules/utils/ast-utils.js 中其实现是分别取出两个节点对应的全部源码 token 序列先比较 token 数量是否一致再逐个比较每个 token 的type词法类型与value字面值。只要任意一处不一致即判为不等价。这种token 级逐字比较的机制带来两个重要推论空格、换行、注释不影响判定例如p.p.p1与p .p\n/* comment */\n.p1在 token 层面完全一致会被判定为重复测试用例 tests/lib/rules/no-duplicate-case.js 验证了这一点语义相同但写法不同不视为重复例如f(a 1)与f(a1)的 token 序列相同会被判为重复但1与1、1与true这类数值等价但词法不同的表达式不会触发规则见下文正确示例。错误示例会被该规则报告的场景官方文档给出了三类典型的错误代码见 docs/src/rules/no-duplicate-case.md场景一直接重复的数字字面量/*eslint no-duplicate-case: error*/ const a 1, one 1; switch (a) { case 1: break; case 2: break; case 1: // duplicate test expression break; default: break; }场景二重复的变量标识符switch (a) { case one: break; case 2: break; case one: // duplicate test expression break; default: break; }场景三重复的字符串字面量switch (a) { case 1: break; case 2: break; case 1: // duplicate test expression break; default: break; }值得留意的是以上三组示例均以/*eslint no-duplicate-case: error*/行内注释的方式显式开启规则。在实际项目中由于该规则已被eslint:recommended收录只要启用了推荐配置即可生效无需逐文件声明。此外测试套件还覆盖了更多会命中的复杂形态见 tests/lib/rules/no-duplicate-case.js连续多个case共享相同标签switch (a) { case a: case a: }同一switch中出现两次以上重复switch (a) { case a: break; case b: break; case a: break; case c: break; case a: break; }会同时报告两处错误第 3 个与第 5 个case错误信息均使用messageId: unexpected复杂成员表达式重复p.p.p1出现两次带函数调用的表达式重复f(true).p1、f(a 1).p1、f(a 1 ? 2 : 3).p1等出现两次方法调用表达式重复([1, 2]).toString()出现两次跨行且夹杂注释的视觉不同但 token 相同的表达式p. p // comment\n .p1与p .p\n/* comment */\n.p1均被视为与p.p.p1重复。正确示例什么情况不会被误报官方文档给出了三组对应的正确代码见 docs/src/rules/no-duplicate-case.md将上述错误示例中的重复项替换为不重复的case 3/case 3即可通过检查/*eslint no-duplicate-case: error*/ const a 1, one 1; switch (a) { case 1: break; case 2: break; case 3: break; default: break; } switch (a) { case one: break; case 2: break; case 3: break; default: break; } switch (a) { case 1: break; case 2: break; case 3: break; default: break; }更进一步测试套件的valid用例见 tests/lib/rules/no-duplicate-case.js揭示了该规则宁可放过不可错杀的保守设计以下情况均不会被报告类型不同不算重复case 1与case 1、case 1与case true在 token 层面字面值不同即使数值上可能相等仅含default的 switchswitch (a) { default: break; }没有可比较的测试表达式对象属性路径不同p.p.p1与p.p.p2函数调用参数不同f(true).p1与f(true, false).p1、f(a 1).p1与f(a 2).p1、f(a 1 ? 2 : 3).p1与f(a 1 ? 2 : 3).p1、f1().p1与f2().p1即使两个函数体完全相同只要标识符不同即不重复数组字面量元素不同([1, 2]).toString()与([1]).toString()不同 switch 语句之间互不影响两个独立的switch各自出现case a不会互相判重未定义的全局标识符case toString单独出现不会被误报。这些用例清晰地说明该规则做的是基于源码文本token的语法级比对而不是运行时求值层面的语义比对因此它不会去判断两个表达式是否可能计算出相同的值。Options无配置项开箱即用该规则没有任何可配置选项在源码中体现为schema: []见 lib/rules/no-duplicate-case.js官方文档的 Options 一节也明确写明 This rule has no options见 docs/src/rules/no-duplicate-case.md。这意味着使用时只能像下面这样以纯开关方式配置// eslint.config.jsflat config export default [ { rules: { no-duplicate-case: error, // 或 warn / off }, }, ];由于docs.recommended: true在eslint:recommended推荐配置中该规则默认以error级别开启项目无需任何额外配置即可获得此项检查。何时不应该使用该规则官方文档明确给出了唯一需要关闭该规则的场景见 docs/src/rules/no-duplicate-case.md在极少数情况下case子句中相同的测试表达式会产生不同的值——这必然意味着这些表达式在依赖并制造副作用。此时你必须禁用该规则。典型的例子是利用自增副作用的写法switch (a) { case i: foo(); break; case i: // eslint-disable-line no-duplicate-case bar(); break; }这里的两个case i在 token 层面完全相同规则会将其报告为重复但由于i每次求值都会改变i的值两个case实际比较的是不同时刻的取值属于刻意依赖副作用的稀有写法。此时可以在具体行尾使用// eslint-disable-line no-duplicate-case注释按行豁免如上例所示也可以在整个文件中使用文件级禁用注释或直接在配置中将该规则置为off。需要特别强调的是这种写法极易引发难以排查的诡异行为官方文档将其限定为in rare cases极少数情况日常编码中不应作为绕过规则的常规手段。实战总结与进一步阅读no-duplicate-case是 ESLint 内置规则中最典型的低成本高收益问题型规则之一何时触发同一switch内出现 token 级完全相同的case测试表达式如何判定type相同 equalTokens逐 token 比较数量、词法类型、字面值见 lib/rules/utils/ast-utils.js判定粒度空格、换行、注释不影响结果1与1、1与true不视为重复配置方式无选项no-duplicate-case: error并已纳入eslint:recommended豁免方式依赖副作用的稀有写法可借助eslint-disable-line按行豁免或整体关闭。如果你想进一步验证该规则在各种边界输入下的行为可以直接阅读其完整测试套件 tests/lib/rules/no-duplicate-case.js其中覆盖了本文提到的全部正反用例规则实现与文档的对应关系可分别查阅 lib/rules/no-duplicate-case.js 与 docs/src/rules/no-duplicate-case.md。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考