ESLint 核心术语全解析:从 AST 到 Violation 的完整技术指南
【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint
本篇技术指南以 ESLint 官方术语表为核心骨架,系统梳理 ESLint 生态中最常被提及的 30 余个核心概念——包括抽象语法树(AST)、配置体系(Flat Config、Config Object、Override)、规则机制(Rule、Severity、Fix、Suggestion)、分析流程(Parser、ESQuery、Report)等。读完本文,你将掌握 ESLint 的完整技术词汇表,能够准确理解官方文档、插件源码与社区讨论中的术语含义,并能在实际配置中正确运用这些概念。文中所有关键术语均结合当前仓库的源码实现与官方文档进行印证,帮助你建立从"术语"到"实现"的完整认知链路。
一、语法表示层:AST、Node 与 ESTree
Abstract Syntax Tree (AST)
抽象语法树(AST)是代码语法的一种结构化表示。源代码中的每一个片段在 AST 中对应一个 节点(Node),每个节点可以拥有任意数量的属性,其中部分属性用于存储子节点,从而形成一棵树状结构。
ESLint 采用的 AST 格式是 ESTree 标准。规则(Rule) 会接收一棵 AST,并在发现 违规(Violation) 时在 AST 的对应位置上报违规信息。换句话说,AST 是 ESLint 理解源代码的中间语言——无论是内置规则还是插件规则,全部围绕 AST 展开工作。
Node
节点(Node)是 AST 中的一段代码。每个节点代表源代码中的一种语法类型。例如,在1 + 2;的 AST 中,1 + 2就是一个BinaryExpression(二元表达式)节点。ESLint 使用 ESQuery 库来解析 选择器(Selector),让规则能够在 AST 中精确搜索目标节点。
ESTree
ESTree是 ESLint 用来将 JavaScript 语法表示为 AST 的格式标准。例如,代码1 + 2;的 ESTree 表示大致如下:
{ "type": "ExpressionStatement", "expression": { "type": "BinaryExpression", "left": { "type": "Literal", "value": 1, "raw": "1" }, "operator": "+", "right": { "type": "Literal", "value": 2, "raw": "2" } } }静态分析(Static Analysis) 工具(如 ESLint)的典型工作方式,就是把语法转换为 ESTree 格式的 AST 后再进行处理。
源码印证:AST 与遍历逻辑在仓库中位于 lib/linter/source-code-visitor.js 与 lib/linter/source-code-traverser.js。规则通过访问者(visitor)模式在遍历 AST 时被逐个触发,这一点在后文 Rule 一节中还会展开。
二、配置体系:Config File、Config Array 与 Config Object
Config File(Configuration File)
配置文件(Config File)是保存 ESLint 解析文件方式与运行规则偏好的文件。ESLint 配置文件命名为eslint.config.(c|m)?(j|t)s形式,即:
eslint.config.jseslint.config.mjseslint.config.cjseslint.config.ts/eslint.config.mts/eslint.config.cts(TypeScript 配置需额外设置)
每个配置文件导出的是一个 配置数组(Config Array),数组中包含一个或多个 配置对象(Config Object)。例如,下面的eslint.config.js以error级别启用prefer-const规则:
import { defineConfig } from "eslint/config"; export default defineConfig([ { rules: { "prefer-const": "error", }, }, ]);若项目在package.json中声明了"type": "commonjs",则eslint.config.js需使用 CommonJS 格式:
const { defineConfig } = require("eslint/config"); module.exports = defineConfig([ { rules: { semi: "error", "prefer-const": "error", }, }, ]);更完整的配置说明参见 Configuration Files。
Config Array
配置数组(Config Array)是配置文件内的配置对象数组。数组中的对象按顺序求值:后面的对象可以覆盖前面对象已设置的配置。这一"后写优先"(last-wins)语义是理解 ESLint 配置合并规则的基础——配置对象中没有显式声明的键不受影响,只有重复声明的键才会被覆盖。
Config Object
配置对象(Config Object)是配置文件的条目,包含 ESLint 在一组文件上执行所需的全部信息。每个配置对象可能包含以下属性(部分):
| 属性 | 作用 |
|---|---|
name | 配置对象的名称,用于错误信息与 config inspector 中标识 |
files | glob 模式数组,指定该配置对象应用于哪些文件 |
ignores | glob 模式数组,指定该配置对象不应用于哪些文件 |
language | 用于 lint 的语言,格式为"pluginName/languageName"(默认"js/js") |
languageOptions | 语言相关的解析设置(ecmaVersion、sourceType、globals、parser、parserOptions) |
linterOptions | lint 过程相关设置(noInlineConfig、reportUnusedDisableDirectives、reportUnusedInlineConfigs) |
processor | 预处理器对象或插件内处理器名称 |
plugins | 插件名称到插件对象的映射 |
rules | 已配置的规则集合 |
settings | 供所有规则共享的名称-值信息 |
配置对象能够描述:在哪些文件上运行、如何处理不同文件类型、引入哪些插件、以及如何运行规则。默认情况下 ESLint 会 lint 匹配**/*.js、**/*.cjs和**/*.mjs的文件。详细说明参见 Configuration Files > Configuration Objects。
三、规则执行机制:Rule、Severity、Violation、Report
Rule
规则(Rule)是检查 AST 是否符合预期模式的代码。当规则的预期未被满足时,它会创建一条 违规(Violation)。ESLint 内置了大量针对常见 JavaScript 问题的规则,更多规则可通过 插件(Plugin) 加载。规则是 ESLint 的核心构建单元——"规则校验你的代码是否满足某项预期,以及不满足时该做什么",内置规则总览参见 Core Concepts > Rules。
从源码结构看,仓库中的每条内置规则都是一个独立模块,位于 lib/rules/ 目录下(如 lib/rules/no-undef.js、lib/rules/semi.js 等),并在 lib/rules/index.js 中统一注册导出。
Severity
严重级别(Severity)决定规则以何种级别运行(如果运行的话)。ESLint 支持三个严重级别:
"off"(0):不运行该规则。"warn"(1):运行规则,但除非配合--max-warnings标志,否则不会因其违规而让进程以非零状态码退出。"error"(2):运行规则,一旦产生任何违规,进程即以非零状态码退出。
源码印证:severity 的字符串/数字归一化逻辑位于 lib/shared/severity.js。其中的
normalizeSeverityToString与normalizeSeverityToNumber两个函数都接受"off"/0、"warn"/1、"error"/2的任意一种写法,并将其统一为内部标准值;传入其他值则抛出Invalid severity value错误。这说明"字符串与数字两种写法等价"并非文档口头约定,而是有强制性的实现保证。
规则配置的完整说明参见 Configure Rules。
Violation
违规(Violation)是规则对代码中不符合其预期的区域给出的指示。每条违规都指明源代码中的一段范围(range)和一条错误消息(message),还可能附带一个 修复(Fix) 和/或 建议(Suggestion),用于说明如何改进违规代码。
源码印证:规则通过
context.report()上报违规,例如 lib/rules/no-undef.js 中针对未定义标识符调用context.report({ node: identifier, messageId: "undef", data: identifier }),其消息模板'{{name}}' is not defined.定义在该规则的meta.messages中。违规信息的聚合与文件级报告处理位于 lib/linter/file-report.js。
Report
报告(Report)是单次 ESLint 运行产生的全部违规的集合。当 ESLint 处理源文件时,它会为每个源文件生成 AST,并将该 AST 传递给每个已配置的规则;各规则产生的违规会被打包收集,最终交给 格式化器(Formatter) 呈现给用户。这条流水线——源码 → 解析 → 规则遍历 → 违规收集 → 格式化输出——正是 ESLint 的核心工作流。
Override
覆盖(Override)指某个 配置对象(Config Object) 或 内联配置(Inline Config) 设置了新的严重级别和/或规则选项,从而取代此前设置的严重级别和/或选项。
以下配置文件在*.test.js文件中把no-unused-expressions从"error"覆盖为"off":
import { defineConfig } from "eslint/config"; export default defineConfig([ { rules: { "no-unused-expressions": "error", }, }, { files: ["*.test.js"], rules: { "no-unused-expressions": "off", }, }, ]);而下面的内联配置则将no-unused-expressions设为"error":
/* eslint no-unused-expressions: "error" */覆盖机制与配置数组"后写优先"的求值顺序一脉相承:靠后的配置对象或文件内的内联注释,可以精确地针对特定文件/代码段调整规则行为。扁平配置的合并实现可参考 lib/config/flat-config-array.js。
Inline Config(Configuration Comment)
内联配置(配置注释)是一种源代码注释,用来把规则配置为不同的严重级别和/或选项组合。内联配置使用与配置文件类似的语法,可以按名称指定任意数量的规则、它们的新严重级别以及可选的新选项。例如,下面的内联配置注释同时关闭了eqeqeq规则,并把curly规则设为"error":
/* eslint eqeqeq: "off", curly: "error" */你也可以使用数字等价写法:
/* eslint eqeqeq: 0, curly: 2 */如果规则带额外选项,可使用数组字面量语法,数组第一项始终是严重级别:
/* eslint quotes: ["error", "double"], curly: 2 */内联配置注释还可以附带描述(用两个或更多连续-与配置分隔):
/* eslint eqeqeq: "off", curly: "error" -- Here's a description about why this configuration is necessary. */ESLint 还支持通过linterOptions.reportUnusedInlineConfigs(默认"off")报告未生效的内联配置注释。完整用法参见 Rules > Use configuration comments。
四、修复能力:Fix、Suggestion 与格式化规则
Fix
修复(Fix)是规则违规的一种可选附加信息,描述如何自动纠正该违规。修复一般"安全"到可以自动应用——它们不应改变代码行为。当使用--fix标志运行时,ESLint 会尝试在报告中应用尽可能多的修复,但不保证所有修复都会被应用(例如修复之间存在冲突时)。常见的编辑器扩展也会自动应用修复。
规则违规除了修复之外,还可能包含不安全、不会自动应用的文件改动,即 建议(Suggestion)。
源码印证:修复器(fixer)API 位于 lib/linter/rule-fixer.js,它提供
insertTextAfter、remove、replaceText等方法来描述代码改动;多条修复的实际落盘由 lib/linter/source-code-fixer.js 完成(该模块负责冲突消解与排序)。--fix标志的说明见 Command Line Interface。
Suggestion
建议(Suggestion)是规则违规的另一种可选附加信息,描述用户如何手动调整代码以解决违规。建议通常不安全,不能自动应用,因为它们会改变代码行为。ESLint 本身不会直接应用建议,但会把建议提供给可能选择应用它们的集成方(例如编辑器扩展)。规则违规中可能同时包含可安全自动应用的 修复(Fix) 与需要人工判断的建议。
修复与建议的区别可归结为两点:修复不改业务逻辑、可由 CLI--fix或编辑器自动应用;建议可能改变业务逻辑、只能通过编辑器集成手动应用。文档约定中,可能提供修复的规则用 🔧 标记,可能提供建议的规则用 💡 标记(见 Rules 列表页)。
Formatting (Rule) 与 Stylistic (Rule)
格式化规则(Formatting Rule)是只关注格式化问题(如分号、空白)的规则,不改变应用逻辑,属于 风格规则(Stylistic Rule) 的子集。ESLint已不再推荐使用格式化规则,并已弃用其内置的格式化规则,转而推荐使用专门的格式化工具(如 Prettier、dprint),或使用社区提供的格式化相关 lint 规则。
风格规则(Stylistic Rule)强制的是某种偏好而非逻辑问题,涵盖格式化规则、命名约定以及等价语法之间的一致性选择。ESLint 的内置风格规则已功能冻结:除支持新的 ECMAScript 版本外,不会再获得新功能。这是 2020 年规则政策调整与 2023 年格式化规则弃用决定的延续(相关背景可参见仓库中的 rule-deprecation.md)。
Formatter(Linting)与 Formatter(Tool)
格式化器(Formatter,Linting 场景)是呈现 ESLint 生成 报告(Report) 的包。ESLint 内置了多个报告器,包括stylish(默认)、json、html等。更多信息参见 Formatters。
格式化器(Formatter,工具场景)则是指一种快速重排代码、但不改变其逻辑或名称的 静态分析 工具。格式化器通常只修改代码的"琐碎部分"(trivia)——分号、间距、换行、空白等,而这些改动一般不会改变代码的 AST。生态中常见的格式化工具包括 Prettier、dprint 等。需要强调的是:ESLint 是 linter 而非 formatter,但 ESLint 规则确实可以对源代码应用格式化改动(即前述格式化规则)。
五、查询与解析:Parser、ESQuery、Selector
Parser
解析器(Parser)是包含一个方法的对象,该方法读取字符串并将其转换为标准化格式。ESLint 使用解析器将源代码字符串转换为 AST 形状。默认情况下,ESLint 使用内置的Espree解析器,它生成的 AST 与标准 JavaScript 运行时和版本兼容。
自定义解析器让 ESLint 能够解析非标准 JavaScript 语法,通常随共享配置或插件一并提供,因此使用者一般无需直接接触它们。例如@typescript-eslint/parser就让 ESLint 能够解析 TypeScript 代码。使用解析器的详细说明参见 Configure a Parser。仓库中解析器服务的实现位于 lib/services/parser-service.js。
ESQuery
ESQuery是 ESLint 用来解析 选择器(Selector) 语法以查询 AST 中 节点(Node) 的库。ESQuery 将CSS 选择器语法解释到 AST 节点属性上。典型的 ESQuery 选择器包括:
BinaryExpression:选择所有类型为BinaryExpression的节点BinaryExpression[operator='+']:选择所有operator为+的BinaryExpression节点BinaryExpression > Literal[value=1]:选择所有value为1、且直接父节点是BinaryExpression的Literal节点
源码印证:ESLint 对 ESQuery 的封装位于 lib/linter/esquery.js。该模块不仅转发了
esquery库的parse/matches能力,还做了两层增强:一是选择器缓存——用selectorCache(一个Map)缓存已解析的选择器,避免重复解析开销(parse函数在 lib/linter/esquery.js#L288-L310);二是复杂度分析——analyzeParsedSelector统计每个选择器的属性查询数与标识符数,据此计算特异性(specificity)用于排序(ESQueryParsedSelector.compare)。这意味着 ESLint 能够为规则自动推导出"哪些节点类型可能触发该选择器",从而在遍历 AST 时只投递可能匹配的节点,提升 lint 性能。
Selector
选择器(Selector)是描述如何在 AST 内搜索 节点(Node) 的语法。ESLint 规则(Rule) 使用 ESQuery 选择器来定位需要检查的节点。选择器语法是编写自定义规则时最常用的工具之一,它让开发者可以用类似 CSS 的方式(类型选择器、属性选择器、子代组合器、伪类等)精准描述"要检查哪类代码"。
六、全局与上下文:Global Declaration、Global Variable
Global Declaration
全局声明(Global Declaration)是向 ESLint 描述某个应在运行时存在的 JavaScript 全局变量(Global Variable) 的方式。全局声明通知那些检查全局变量正确使用的 lint 规则。例如,no-undef规则会对"引用了未在配置的全局变量列表中定义的全局变量"产生违规。在 配置文件 中,全局变量被定义为 JavaScript 对象(languageOptions.globals)。配置全局变量的方法参见 Configure Language Options > Specify Globals。
源码印证:lib/rules/no-undef.js 的实现展示了全局声明的实际消费方式:规则在
Program:exit时获取全局作用域,遍历globalScope.through中的每个引用(即作用域中"穿透"出来的未解析标识符),对每个引用上报违规。其可选选项typeof(默认false)用于控制是否对typeof操作符中的变量引用告警——规则中通过hasTypeOfOperator判断父节点是否为typeof一元表达式。
Global Variable
全局变量(Global Variable)是存在于全局作用域中的运行时变量,所有模块和脚本都可访问。JavaScript 中的全局变量声明在globalThis对象上(在 Node.js 中通常别名为global,在浏览器中为window)。你可以通过 全局声明(Global Declaration) 让 ESLint 知道你代码中使用了哪些全局变量。这在代码依赖外部环境注入(如 HTML 脚本引入的全局变量)时尤为重要。
七、扩展体系:Plugin、Processor、Shareable Config
Plugin
插件(Plugin)是一个可以包含一组 配置(共享配置)、处理器(Processor) 和/或 规则(Rule) 的包。插件的一个典型用途是为某个框架强制执行最佳实践——例如 Angular 生态的官方插件就包含使用 Angular 框架的最佳实践规则。配置插件的详细说明参见 Configure Plugins。仓库自身的插件开发指南参见 Plugins。
Processor
处理器(Processor)是插件的一部分,负责从其他类型的文件中提取 JavaScript 代码,然后让 ESLint 对这些提取出的代码执行 lint。例如@eslint/markdown就包含一个处理器,能把 Markdown 文件中的代码块文本转换为可被 lint 的代码。配置处理器的说明参见 Plugins > Specify a Processor。处理器服务的底层实现位于 lib/services/processor-service.js,它通过preprocess与postprocess两个阶段完成"提取-合并"循环。
Shareable Config(Configuration)
共享配置(Shareable Config)是提供预定义 配置文件 配置的模块。共享配置可以配置与配置文件完全相同的信息,包括 插件(Plugin) 和 规则(Rule)。共享配置常与插件一同提供——许多插件会提供名为recommended(推荐)的配置,启用它们建议的起始规则集。例如eslint-plugin-solid提供了一个可共享的 recommended 配置:
import { defineConfig } from "eslint/config"; import js from "@eslint/js"; import solid from "eslint-plugin-solid/configs/recommended"; export default defineConfig([js.configs.recommended, solid]);共享配置的编写与发布指南参见 Share Configurations。
八、配置格式演变:Flat Config 与 Legacy Config
Flat Config
扁平配置(Flat Config)是 ESLint 当前的配置文件格式。扁平配置文件命名为eslint.config.(c|m)?(j|t)s形式。之所以称为"扁平",是因为所有嵌套都必须在同一个配置文件中完成;与此相对,Legacy 配置格式 允许配置在项目的子目录间嵌套分布。扁平配置的设计动机在于:消除.eslintrc体系中层叠配置带来的查找歧义与继承复杂性,让配置结果完全由当前目录的单个配置文件决定。
Legacy Config
Legacy 配置(Legacy Config)是 ESLint 之前的配置文件格式,现已被 Flat Config 取代。Legacy 配置命名为.eslintrc.*形式,并允许在项目的子目录中跨文件嵌套。从仓库结构可以观察到这一演进的痕迹:docs/src/use/下既有 migrate-to-9.0.0.md 等迁移指南,lib/config/下同时保留着 config.js、config-loader.js(旧体系)与 flat-config-array.js、flat-config-schema.js(新体系)等实现文件。
九、定位与边界:Linter、Static Analysis、Type Checker
Linter
Linter(代码检查器)是一种 静态分析 工具,可以对一组 规则(Rule) 在源代码上的运行结果进行 报告(Report);每条规则都可能在源代码中报告任意数量的 违规(Violation)。ESLint 是 JavaScript 及其他 Web 技术中最常用的 linter 之一。需要注意的是,linter 与 格式化工具(Formatter) 和 类型检查器(Type Checker) 是相互独立的工具类别。
Static Analysis
静态分析(Static Analysis)是在不构建、不运行源代码的情况下分析源代码的过程。linter(如 ESLint)、格式化工具和类型检查器都属于静态分析工具。静态分析与动态分析相对——动态分析是在代码构建并执行之后评估代码的过程,单元测试、集成测试、端到端测试都是动态分析的常见例子。
Type Checker
类型检查器(Type Checker)是一种构建项目代码结构与数据形状完整理解的 静态分析 工具。类型检查器通常比 linter更慢但更全面:linter 传统上一次只针对单个文件或代码片段的 AST 操作,而类型检查器理解跨文件依赖与类型。TypeScript 是 JavaScript 最常用的类型检查器,typescript-eslint 项目提供了在 lint 规则中使用类型检查器的集成能力。
Logical Rule
逻辑规则(Logical Rule)是检查代码如何运行以发现问题的一类 规则(Rule)。许多逻辑规则致力于发现潜在崩溃(如no-undef)、非预期行为(如no-sparse-arrays)和未使用代码(如no-unused-vars)。ESLint 内置的全部逻辑规则可以在 Rules > Possible Problems 下查看完整列表。
十、术语速查表
为便于快速检索,将本文全部术语按主题归类如下:
| 主题域 | 术语 |
|---|---|
| 语法表示 | Abstract Syntax Tree (AST)、Node、ESTree |
| 配置体系 | Config File、Config Array、Config Object、Flat Config、Legacy Config、Override |
| 规则机制 | Rule、Severity、Violation、Report、Logical Rule、Stylistic Rule、Formatting (Rule) |
| 修复能力 | Fix、Suggestion |
| 查询解析 | Parser、ESQuery、Selector |
| 全局上下文 | Global Declaration、Global Variable |
| 扩展体系 | Plugin、Processor、Shareable Config |
| 配置注释 | Inline Config (Configuration Comment) |
| 输出呈现 | Formatter (Linting)、Formatter (Tool) |
| 分析类别 | Linter、Static Analysis、Type Checker |
十一、从术语到实践:如何继续深入
术语是理解 ESLint 的入口,但真正的掌握来自实践。建议按照以下路径继续深入:
- 动手配置:参照 Configuration Files 创建你自己的
eslint.config.js,体验 Config Object 的files/ignores/rules组合与 Override 语义。 - 观察规则行为:阅读 Rules 下任一规则的文档(如 no-undef、eqeqeq),对照 lib/rules/ 中对应源码,理解"文档术语"如何映射为"实现逻辑"。
- 阅读测试用例:仓库的 tests/lib/rules/ 目录包含全部内置规则的测试,展示了每条规则在各类输入下的违规/修复/建议行为,是理解 Fix 与 Suggestion 区别的最佳教材。
- 编写自定义规则:结合 Custom Rules 指南,使用 ESQuery Selector 编写你自己的规则,实践 AST、Node、Violation 等全部核心概念。
通过本文的术语地图与源码印证,你现在已经拥有阅读 ESLint 官方文档、理解插件源码、排查配置问题的完整知识框架。
【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考