ESLint `lines-around-directive` 规则详解:指令序言(directive prologue)周围的空行控制

ESLint `lines-around-directive` 规则详解:指令序言(directive prologue)周围的空行控制 ESLintlines-around-directive规则详解指令序言directive prologue周围的空行控制【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslintlines-around-directive是 ESLint 内置的 layout布局类规则用于强制或禁止在 JavaScript 文件的指令序言directive prologue——例如use strict;、use asm;——之前或之后出现空行。本篇以官方文档 docs/src/rules/lines-around-directive.md 为核心骨架结合 lib/rules/lines-around-directive.js 源码与 tests/lib/rules/lines-around-directive.js 测试用例系统讲解该规则的配置方式、判定逻辑、自动修复行为与弃用迁移方案帮助你精确掌控指令序言周围的排版风格。指令序言Directive Prologue是什么JavaScript 规范允许在文件顶部或函数体顶部出现一组连续的字符串字面量表达式语句它们向执行环境声明脚本希望启用某项特性最典型的例子是use strict;严格模式。这一组语句被统称为指令序言directive prologue并且只作用于其所在的文件或函数作用域。// 严格模式作用于整个脚本 use strict; var foo; function bar() { var baz; }var foo; function bar() { // 严格模式只作用于该函数内部 use strict; var baz; }从实现层面看ESLint 在 lib/rules/utils/ast-utils.js 中通过getDirectivePrologue(node)来识别指令序言它只对Program、FunctionDeclaration、FunctionExpression以及函数体为块语句BlockStatement的ArrowFunctionExpression生效从函数体或Program.body的第一个语句开始只要语句是ExpressionStatement且其expression是Literal字符串字面量就将其纳入指令列表一旦遇到任何其他类型的语句便立即停止。注意代码注释中提到() use strict;这种箭头函数隐式返回字符串的写法不是指令序言规则不会对其生效。Rule Details规则判定范围该规则只负责在指令序言整体之前和整体之后即第一个指令之前、最后一个指令之后强制或禁止空行并明确不对指令与指令之间的空行做任何约定。此外除非指令前紧邻注释否则它不会强制要求在指令序言之前加空行。关于空行的判定源码中给出了精确的行差算法hasNewlineBefore(node)lib/rules/lines-around-directive.js取指令节点前一个 tokenincludeComments: true即把注释也算进来若node.loc.start.line - tokenLineBefore 2则视为存在空行hasNewlineAfter(node)lib/rules/lines-around-directive.js借助getLastTokenOnLine(node)拿到与节点处于同一行的最后一个 token再比较下一 token 的行号差是否 2。getLastTokenOnLine之所以存在是因为当尾随分号被换行隔开时分号单独占一行同一行最后一个 token会是倒数第二个 token需要特殊处理。规则的入口同时注册在Program、FunctionDeclaration、FunctionExpression、ArrowFunctionExpression四类节点上lib/rules/lines-around-directive.js因此文件顶层与每个函数体内的指令序言都会被独立检查。规则在 lib/rules/index.js 中注册为按需加载lazy loadingfixable: whitespace表明它支持自动修复。Options两种配置形态规则接受一个选项可以是字符串或对象always默认值——要求指令周围必须有空行never——禁止指令周围出现空行。或使用对象形式分别控制前后两侧{ before: always | never, // 控制指令序言之前的空行 after: always | never // 控制指令序言之后的空行 }对象形式的两侧取值都是必填的。这一点在源码的 schema 校验中有硬性约束lib/rules/lines-around-directive.jsbefore与after只能是always或neveradditionalProperties: false禁止任何多余字段且minProperties: 2要求两个属性必须同时出现。选项的解析逻辑在create(context)入口lib/rules/lines-around-directive.jsconfig context.options[0] || always若为字符串则 before/after 同时取该值若为对象则分别取config.before与config.after。配置示例与正反例always默认错误示例always/* eslint lines-around-directive: [error, always] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, always] */ // comment use strict; use asm; var foo;正确示例always/* eslint lines-around-directive: [error, always] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, always] */ // comment use strict; use asm; var foo;注意观察always下的几个关键细节注释与第一个指令之间需要空行// comment之后有空行再到use strict;指令序言结束最后一个指令与后续语句之间需要空行指令与指令之间如use strict;与use asm;不需要空行当指令序言是整个函数体/文件的唯一内容时如function foo() { use strict; use asm; var bar; }之外没有任何语句的情况规则不会强制在之后补空行——源码中明确若最后一个指令就是 body 的最后一个语句且无尾随注释直接return跳过 after 检查以保证与padded-blocks规则的兼容性lib/rules/lines-around-directive.js。never错误示例never/* eslint lines-around-directive: [error, never] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, never] */ // comment use strict; use asm; var foo;正确示例never/* eslint lines-around-directive: [error, never] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, never] */ // comment use strict; use asm; var foo;在never模式下指令与注释、指令与后续语句之间一律不允许空行指令之间同样不受约束。这里还有一处边界行为文件顶部没有注释时never会检查第一个指令前是否有空行因为文件首行不可能是空行通常都能通过但源码特意指出仅当指令前有注释、或处于Program顶部且expectLineBefore never时才检查 beforelib/rules/lines-around-directive.js目的是不在文件最顶部强制空行并与padded-blocks保持兼容。before after 对象形式{ before: never, after: always }—— 错误示例/* eslint lines-around-directive: [error, { before: never, after: always }] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, { before: never, after: always }] */ // comment use strict; use asm; var foo;{ before: never, after: always }—— 正确示例/* eslint lines-around-directive: [error, { before: never, after: always }] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, { before: never, after: always }] */ // comment use strict; use asm; var foo;{ before: always, after: never }—— 错误示例/* eslint lines-around-directive: [error, { before: always, after: never }] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, { before: always, after: never }] */ // comment use strict; use asm; var foo;{ before: always, after: never }—— 正确示例/* eslint lines-around-directive: [error, { before: always, after: never }] */ // comment use strict; var foo; function foo() { use strict; use asm; var bar; } function foo() { // comment use strict; var bar; }/* eslint lines-around-directive: [error, { before: always, after: never }] */ // comment use strict; use asm; var foo;在配置文件中的写法以上是内联注释/* eslint ... */形式的示例。在实际项目中通常将规则配置在 ESLint 配置文件中如eslint.config.js// eslint.config.js export default [ { rules: { lines-around-directive: [error, always], // 或 lines-around-directive: [error, never], // 或对象形式 lines-around-directive: [error, { before: never, after: always }], }, }, ];规则默认recommended: false不会随eslint:recommended自动启用需要显式配置。同时注意由于该规则针对脚本级指令示例代码均需以脚本模式sourceType: script解析这从文档示例的::: incorrect { sourceType: script }标注可以确认。自动修复Autofix行为lines-around-directive在 meta 中声明了fixable: whitespace支持--fix自动修复。修复逻辑位于 lib/rules/lines-around-directive.js 的fix(fixer)中期望空行但缺失时在指令前插入\nbefore场景或在最后一个 token 后插入\nafter场景出现多余空行时删除指令前的一个字符范围[node.range[0] - 1, node.range[0]]before 场景或删除最后一个 token 后的一个字符[lastToken.range[1], lastToken.range[1] 1]after 场景。这里的删除一个字符正是针对空行中的换行符而空行的判定基于 2的行差因此多出的空行会先被消减一行。对应的修复期望output字段在 tests/lib/rules/lines-around-directive.js 中有大量验证例如use strict;\nvar foo;在always下被修复为use strict;\n\nvar foo;。测试文件还覆盖了许多边界场景包括#!/usr/bin/env nodeshebang 之后紧跟指令、单行/多行注释与指令之间空行的判定、use asm;多指令序言、函数体内的指令检查、以及箭头函数块体() { use strict; ... }的检查等可作为理解规则行为的补充依据。弃用状态与迁移建议该规则在ESLint v4.0.0起被标记为已弃用deprecated并在ESLint v11.0.0移除availableUntil: 11.0.0当前仓库中的实现仍保留deprecated元信息lib/rules/lines-around-directive.js弃用原因被描述为该规则被一个更通用的规则取代。官方推荐的替代方案是社区插件stylistic/eslint-plugin中的padding-line-between-statements规则。该通用规则可以通过配置语句类型对如directive与普通语句之间来完全复刻lines-around-directive的能力并且表达能力更强。在 flat config 下的大致迁移写法// 迁移示例需要安装 stylistic/eslint-plugin import stylistic from stylistic/eslint-plugin; export default [ { plugins: { stylistic: stylistic }, rules: { // 等价于 lines-around-directive: [error, always] stylistic/padding-line-between-statements: [ error, { blankLine: always, prev: directive, next: * }, { blankLine: any, prev: directive, next: directive }, ], }, }, ];迁移写法的语义映射说明blankLine: always表示指令与后续任意语句之间始终保留空行blankLine: any表示指令与指令之间不做要求二者组合可模拟always如需never将always替换为never即可。这里仅给出迁移思路具体配置请以插件官方文档为准。如果使用旧版eslintrc配置格式弃用提示会随 ESLint 版本给出对应警告同时可通过规则 meta 中的replacedBy信息定位替代规则。When Not To Use It何时关闭此规则如果你对指令序言前后是否保留空行没有任何强制的排版约定可以安全地禁用此规则。此外考虑到该规则已弃用且即将移除新项目更推荐直接使用stylistic/eslint-plugin的padding-line-between-statements或其他风格方案从源头避免后续迁移成本。小结lines-around-directive围绕指令序言前后是否保留空行这一个排版维度提供了字符串与对象两种配置形态always/never/{ before, after }支持--fix自动修复并与padded-blocks、lines-around-comment等布局类规则在设计上保持兼容例如仅在指令前存在注释时才对 before 侧提出空行要求、不检查仅有指令序言的函数体尾部。理解其判定细节行差 2视为空行、getDirectivePrologue的指令识别边界后你可以准确预测任意代码的检查结果或借助测试文件 tests/lib/rules/lines-around-directive.js 进一步验证边界行为。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考