ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ESLint spaced-comment 规则全解析:统一 `//` 与 `/*` 后的注释空格风格

ESLint spaced-comment 规则全解析:统一 `//` 与 `/*` 后的注释空格风格 ESLint spaced-comment 规则全解析统一//与/*后的注释空格风格【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint本文是 ESLint 内置spaced-comment规则的完整技术指南围绕注释起始符//、/*之后是否强制保留空白的风格一致性展开。无论你的团队偏好// 注释的宽松排版还是需要兼容//-分隔线、/**JSDoc、/*!版权头等特殊注释形态本文都将结合规则源码与测试用例带你掌握always/never、exceptions、markers、block.balanced全套配置并理解其底层正则匹配与自动修复原理可直接落地到.eslintrc或 flat config 配置中。规则背景与动机部分风格指南要求或禁止在注释起始符//或/*之后紧跟一个空白字符。从可读性角度看//、/*之后保留空白如// This is a comment让注释正文更容易被阅读、与符号本身区分开而注释掉整段代码时如//someCode()紧贴//不保留空白反而更方便因为保留空白会在代码前留下多余空格影响还原。spaced-comment规则正是用于在注释起始符后强制执行统一且一致的空格策略同时针对各种文档注释风格提供了丰富的豁免机制。规则类型为suggestion建议类不涉及运行时正确性并支持自动修复fixable: whitespace。该规则在 ESLint 核心中已标记为弃用deprecated since v8.53.0可用至 v11.0.0由 ESLint Stylistic 维护的stylistic/eslint-plugin中的同名规则继承具体元数据见 lib/rules/spaced-comment.js 与 docs/src/_data/rules_meta.json但作为风格规则的经典实现其配置语义与正则设计仍极具参考价值。仓库中还保留了与之关联的旧规则文档 spaced-line-comment本文聚焦于spaced-comment本身。规则选项总览规则接受两个选项第一个选项为字符串取值always或never默认alwaysalways//或/*之后必须至少有一个空白字符never其后不得有任何空白字符。第二个选项为对象可含exceptions与markers两个键也可进一步细分到line/block子对象。第二个选项的完整结构与规则 schema 一致见 lib/rules/spaced-comment.jsspaced-comment: [error, always, { line: { markers: [/], exceptions: [-, ] }, block: { markers: [!], exceptions: [*], balanced: true } }]其中exceptions字符串模式数组视为规则的豁免。只要该模式从注释开头起连续重复到行尾或到*/若为单行块注释规则便不报警。注意当第一个参数为never时exceptions被忽略源码中createAlwaysStylePattern仅在requireSpace为真时使用 exceptions见 lib/rules/spaced-comment.js。markers字符串模式数组用于 docblock 风格注释的标记例如额外的/代表 doxygen、vsdoc 等文档工具读取的注释其后必须另有字符。markers无论第一个参数是always还是never都生效。line/block子对象可分别为行注释和块注释定义独立的exceptions与markers。其中block额外支持布尔键balanced默认false用于控制行内块注释两端是否对称留白。marker 与 exception 的本质区别marker 只出现在注释开头标志注释的特殊性质如 JSDoc 的*、doxygen 的/、!版权标记其后的空格规则独立判定exception 可以出现在注释串的任意位置只要是该模式从头开始连续重复即可豁免。一句话总结exception 解决这段注释本身就是装饰字符的问题marker 解决这段注释是机器可读的文档/指令的问题。第一个选项always与neveralways以下代码在always下为错误不正确示例/*eslint spaced-comment: [error, always]*/ //This is a comment with no whitespace at the beginning /*This is a comment with no whitespace at the beginning */启用block.balanced: true后两端都必须留白下面代码为错误/* eslint spaced-comment: [error, always, { block: { balanced: true } }] */ /* This is a comment with whitespace at the beginning but not the end*/以下代码在always下为正确/* eslint spaced-comment: [error, always] */ // This is a comment with a whitespace at the beginning /* This is a comment with a whitespace at the beginning */ /* * This is a comment with a whitespace at the beginning */ /* This comment has a newline */注意块注释以换行开头时/*后直接换行不会触发always的报错因为换行本身已经是分隔符同样JSDoc 风格的注释天然合法/* eslint spaced-comment: [error, always] */ /** * I am jsdoc */原因在于源码中*会被自动加入 markers 列表parseMarkersOption的concat(*)逻辑见 lib/rules/spaced-comment.js/**被视为带 marker 的注释开头无需再要求空格。never以下代码在never下为错误/*eslint spaced-comment: [error, never]*/ // This is a comment with a whitespace at the beginning /* This is a comment with a whitespace at the beginning */ /* \nThis is a comment with a whitespace at the beginning */启用block.balanced: true时结尾空白同样报错/*eslint spaced-comment: [error, never, { block: { balanced: true } }]*/ /*This is a comment with whitespace at the end */以下代码在never下为正确/*eslint spaced-comment: [error, never]*/ /*This is a comment with no whitespace at the beginning */以及 JSDoc 风格marker 豁免无需空格/*eslint spaced-comment: [error, never]*/ /** * I am jsdoc */第二个选项exceptionsexceptions用于放行装饰性注释典型场景是代码块分隔线。以下配置spaced-comment: [error, always, { exceptions: [-, ] }]表示允许//----、//这类从头连续重复的纯装饰注释。区分两种情况若exceptions配置在顶层则对行注释和块注释同时生效若配置在line/block子对象中则只对对应类型的注释生效子对象优先于顶层见 lib/rules/spaced-comment.js 中(config[type] config[type].markers) || config.markers的取值优先级。错误示例/* eslint spaced-comment: [error, always, { block: { exceptions: [-] } }] */ //-------------- // Comment block //--------------说明这里 exception 只配置给block块注释因此//------行注释仍会被要求空格/* eslint spaced-comment: [error, always, { exceptions: [-, ] }] */ //------ // Comment block //------说明exception 模式必须从头连续重复混合序列------无法匹配单个模式/* eslint spaced-comment: [error, always, { exceptions: [-, ] }] */ /*------*/ /* Comment block */ /*------*//* eslint spaced-comment: [error, always, { line: { exceptions: [-] } }] */ /*-------*/ // Comment block /*-------*/说明exception 只配给line块注释/*---*/仍会被检查/* eslint spaced-comment: [error, always, { block: { exceptions: [*] } }] */ /******** COMMENT *******/说明*是默认 marker/********会被识别为 marker 后未跟空格/合法 exception 序列而报错期望expectedExceptionAfter对应测试见 tests/lib/rules/spaced-comment.js。正确示例/* eslint spaced-comment: [error, always, { exceptions: [-] }] */ //-------------- // Comment block //--------------/* eslint spaced-comment: [error, always, { line: { exceptions: [-] } }] */ //-------------- // Comment block //--------------/* eslint spaced-comment: [error, always, { exceptions: [*] }] */ /**************** * Comment block ****************/说明末尾****************/是连续*重复到*/符合 exception 规则pattern 需匹配到行尾或*/。/* eslint spaced-comment: [error, always, { exceptions: [-] }] */ //------- // Comment block //------- /*-------*/ // Comment block /*-------*/说明-整体作为一个模式连续重复时匹配成功/* eslint spaced-comment: [error, always, { block: { exceptions: [-] } }] */ /*-------*/ // Comment block /*-------*//* eslint spaced-comment: [error, always, { block: { exceptions: [*] } }] */ /***************/ /******** COMMENT *******/说明块注释内部的COMMENT行不需要任何修饰因为 exception 只作用于注释开头到*/的连续重复区域。底层的 exception 匹配原理在always模式下源码通过createAlwaysStylePattern构造开头的校验正则先是marker 或空随后是createExceptionsPattern生成的空白或 exception 序列见 lib/rules/spaced-comment.js。其拼接逻辑为无 exceptions 时^\s单个 exception 如-^(?:\-$)即(?: 空白 | \-到行尾 )多个 exception 如-、^(?:\s|(?:\-|)$)复合模式如--^(?:\s|(?:\-||(?:\-\-))$)。注意(?:$|[换行字符集])保证了 exception 序列必须延续到注释内容结束行尾或换行这正是连续重复到行尾语义的来源。而对never模式createNeverStylePattern只关心 marker 后的空白^([markers])?[ \t]exceptions 不参与见 lib/rules/spaced-comment.js这与文档中exceptions 在never下被忽略的说明完全一致。第二个选项markersmarkers用于放行 docblock 风格注释典型如 doxygen 的///、/*!、/*!以及 ESLint 自身的指令注释/*global*/、/*eslint-disable*/等。错误示例/* eslint spaced-comment: [error, always, { markers: [/] }] */ ///This is a comment with a marker but without whitespace说明marker/存在但其后缺少空格marker 之后的正文仍需满足always的空白要求/*eslint spaced-comment: [error, always, { block: { markers: [!], balanced: true } }]*/ /*! This is a comment with a marker but without whitespace at the end*/说明balanced: true下*/前缺空格/*eslint spaced-comment: [error, never, { block: { markers: [!], balanced: true } }]*/ /*!This is a comment with a marker but with whitespace at the end */说明never模式下 marker!后不能有空格且balanced要求结尾也无空格。正确示例/* eslint spaced-comment: [error, always, { markers: [/] }] */ /// This is a comment with a marker/*eslint spaced-comment: [error, never, { markers: [!] }]*/ //!This is a line comment with a marker /*!this is a block comment with a marker subsequent lines are ignored */说明never模式下 marker 之后不允许空格但注释的后续行不受影响marker 只作用于注释开头/* eslint spaced-comment: [error, always, { markers: [global] }] */ /*global ABC*/说明global被标记为 marker 后/*global ABC*/这类 ESLint 全局变量指令注释不再要求/*后有空格。markers 的经典用法还包括 JSDoc*默认加入、/*eslint-disable-line ...*/、/*eslint eqeqeq:0, curly: 2*/等指令注释对应测试均可在 tests/lib/rules/spaced-comment.js 中找到。测试还覆盖了 marker 与 exception 组合的场景例如///--------marker/ exception-在always下合法见 tests/lib/rules/spaced-comment.js。marker 的默认行为与边界*自动加入无论你是否配置 markers*都会作为 JSDoc marker 被加入见 lib/rules/spaced-comment.js因此/**、/* *等 JSDoc 注释天然豁免。纯 marker 注释被忽略当注释内容为空或仅由 marker 组成时规则直接跳过node.value.length 0 || rule.markers.has(node.value)见 lib/rules/spaced-comment.js。这允许//#endregion、/*foo*/这类纯标记注释通过对应 issue #12036 的修复。Shebang 注释被排除Program监听器中先filter(token token.type ! Shebang)再检查保证#!/usr/bin/env node不受影响见 lib/rules/spaced-comment.js 与测试validShebangProgram。块注释的balanced选项block.balanced默认false只作用于块注释/* ... */用于控制两端对称balanced: truealways/*后至少一个空白且*/前至少一个空白balanced: truenever/*后、*/前均不得有空白balanced: false不强制结尾空白规则。典型正确示例/* eslint spaced-comment: [error, always, { block: { balanced: true } }] */ /* 注释 */ var a 1; /* comment */ function foo(/* height */a) { }对应never balanced的正确形态是/*comment*/。需要注意balanced只影响块注释行注释// ...不会受其约束测试中有明确用例见 tests/lib/rules/spaced-comment.js。在源码实现中balanced决定endRegex的形态always模式下结尾正则要求空白或 exception 序列直到末尾createExceptionsPattern(exceptions) $never模式则要求[ \t]$不可出现见 lib/rules/spaced-comment.js。当always balanced且结尾缺少空白时会报告expectedSpaceBeforenever balanced结尾出现空白时报告unexpectedSpaceBefore。自动修复Autofix行为该规则fixable: whitespace可通过eslint --fix自动修正。修复逻辑位于reportBegin与reportEnd见 lib/rules/spaced-comment.jsalways模式在//或/*含 marker 部分之后insertTextAfterRange插入一个空格结尾缺失时在*/前插入空格never模式用replaceTextRange删除注释头与 marker 之间的空白结尾多余空白则直接删除。测试文件中的output字段即为修复后的预期结果例如//An invalid comment NOT starting with space → 修复为 // An invalid comment NOT starting with space // An invalid comment starting with space → 修复为 //An invalid comment starting with space见 tests/lib/rules/spaced-comment.js。需要留意的是若 exception 模式被破坏如分隔线末尾混入了不匹配字符修复会插入空格并报告expectedExceptionAftermessageId 列表见 lib/rules/spaced-comment.js此时需人工修正装饰线。综合配置示例以下是一个覆盖常见场景的推荐配置JSON兼容.eslintrc与 flat config 的 rules 对象spaced-comment: [error, always, { line: { markers: [/], exceptions: [-, , , *, #, !#] }, block: { markers: [!, global, eslint], exceptions: [*, -], balanced: true } }]该配置可实现普通注释强制////*留白alwaysdoxygen 的///与版权头/*!、指令/*global、/*eslint免检markers装饰分隔线//-----、//、/**** ... ****/免检exceptions行内块注释/* comment */两端对称balanced。消息与定位规则内置了 6 条可本地化的 messageId见 lib/rules/spaced-comment.js便于在自定义 formatter 或 IDE 提示中区分场景messageId含义unexpectedSpaceAfternever下//或/*后出现空格/制表符unexpectedSpaceAfterMarkernever下 marker 后出现空格/制表符expectedSpaceAfteralways下注释头后缺少空格expectedExceptionAfteralways下注释头后既非空白也非合法 exception 序列unexpectedSpaceBeforenever balanced下*/前出现空白expectedSpaceBeforealways balanced下*/前缺少空白所有检查在Program阶段一次性遍历sourceCode.getAllComments()完成因此对单行注释、块注释、行内注释如function foo(/* height */a)全覆盖。小结spaced-comment通过主开关 豁免层的两段式设计在严格性与灵活性之间取得了良好平衡always/never确立基线exceptions放行装饰字符markers放行文档与指令注释block.balanced进一步约束行内块注释的两端对称。理解其背后的正则拼接策略marker 可选 空白/exception 序列见 lib/rules/spaced-comment.js可以帮助你在遇到复杂注释形态时准确预判规则行为也能为迁移到 ESLint Stylistic 的维护版本stylistic/eslint-plugin中的spaced-comment打下基础。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进