版本

自定义解析器

ESLint 自定义解析器允许您扩展 ESLint,以支持检查新的非标准 JavaScript 语言特性或代码中的自定义语法。解析器的职责是将您的代码转换为抽象语法树 (AST),然后 ESLint 可以分析和检查它。

创建自定义解析器

自定义解析器中的方法

自定义解析器是一个 JavaScript 对象,它具有 parse()parseForESLint() 方法。parse 方法仅返回 AST,而 parseForESLint() 还返回其他值,这些值允许解析器进一步自定义 ESLint 的行为。

这两种方法都应该是实例(自身)属性,并将源代码作为第一个参数,并将可选的配置对象作为第二个参数,该配置对象在配置文件中以 parserOptions 的形式提供。

// customParser.js

const espree = require("espree");

// Logs the duration it takes to parse each file.
function parse(code, options) {
    const label = `Parsing file "${options.filePath}"`;
    console.time(label);
    const ast = espree.parse(code, options);
    console.timeEnd(label);
    return ast; // Only the AST is returned.
};

module.exports = { parse };

parse 返回对象

parse 方法应仅返回 AST 对象。

parseForESLint 返回对象

parseForESLint 方法应返回一个对象,该对象包含必需的属性 ast 和可选属性 servicesscopeManagervisitorKeys

  • ast 应包含 AST 对象。
  • services 可以包含任何依赖于解析器的服务(例如节点的类型检查器)。services 属性的值作为 context.sourceCode.parserServices 提供给规则。默认值是一个空对象。
  • scopeManager 可以是一个 ScopeManager 对象。自定义解析器可以为实验性/增强语法使用自定义作用域分析。默认值是由 eslint-scope 创建的 ScopeManager 对象。
    • scopeManager 的支持是在 ESLint v4.14.0 中添加的。支持 scopeManager 的 ESLint 版本将在 parserOptions 中提供 eslintScopeManager: true 属性,该属性可用于功能检测。
  • visitorKeys 可以是一个对象,用于自定义 AST 遍历。对象的键是 AST 节点的类型。每个值都是一个应遍历的属性名称数组。默认值是 eslint-visitor-keys 的 KEYS
    • visitorKeys 的支持是在 ESLint v4.14.0 中添加的。支持 visitorKeys 的 ESLint 版本将在 parserOptions 中提供 eslintVisitorKeys: true 属性,该属性可用于功能检测。

自定义解析器中的元数据

为了更轻松地调试和更有效地缓存自定义解析器,建议在自定义解析器根目录的 meta 对象中提供名称和版本,如下所示

// preferred location of name and version
module.exports = {
    meta: {
        name: "eslint-parser-custom",
        version: "1.2.3"
    }
};

meta.name 属性应与您的自定义解析器的 npm 包名称匹配,meta.version 属性应与您的自定义解析器的 npm 包版本匹配。完成此操作的最简单方法是从您的 package.json 中读取此信息。

AST 规范

自定义解析器应创建的 AST 基于 ESTree。AST 需要一些关于源代码详细信息的附加属性。

所有节点

所有节点都必须具有 range 属性。

  • range (number[]) 是一个包含两个数字的数组。这两个数字都是从 0 开始的索引,表示在源代码字符数组中的位置。第一个是节点的起始位置,第二个是节点的结束位置。code.slice(node.range[0], node.range[1]) 必须是节点的文本。此范围不包括节点周围的空格/括号。
  • loc (SourceLocation) 不得为 nullESTree 将 loc 属性定义为可为空,但 ESLint 要求此属性。SourceLocation#source 属性可以是 undefined。ESLint 不使用 SourceLocation#source 属性。

所有节点的 parent 属性都必须是可重写的。在任何规则访问 AST 之前,ESLint 会在遍历时将每个节点的 parent 属性设置为其父节点。

Program 节点

Program 节点必须具有 tokenscomments 属性。这两个属性都是下面 Token 接口的数组。

interface Token {
    type: string;
    loc: SourceLocation;
    // See the "All Nodes" section for details of the `range` property.
    range: [number, number];
    value: string;
}
  • tokens (Token[]) 是影响程序行为的 token 数组。token 之间可能存在任意空格,因此规则检查 Token#range 以检测 token 之间的空格。这必须按 Token#range[0] 排序。
  • comments (Token[]) 是注释 token 的数组。这必须按 Token#range[0] 排序。

所有 token 和注释的 range 索引不得与其他 token 和注释的 range 重叠。

Literal 节点

Literal 节点必须具有 raw 属性。

  • raw (string) 是此字面量的源代码。这与 code.slice(node.range[0], node.range[1]) 相同。

打包自定义解析器

要将您的自定义解析器发布到 npm,请执行以下操作

  1. 按照上面的 创建自定义解析器 部分创建一个自定义解析器。
  2. 为自定义解析器创建一个 npm 包
  3. 在您的 package.json 文件中,将 main 字段设置为导出您的自定义解析器的文件。
  4. 发布 npm 包。

有关发布 npm 包的更多信息,请参阅 npm 文档

一旦您发布了 npm 包,您可以通过将该包添加到您的项目来使用它。例如

npm

npm install --save-dev eslint-parser-myparser

yarn

yarn add --dev eslint-parser-myparser

pnpm

pnpm add --save-dev eslint-parser-myparser

bun

bun add --dev eslint-parser-myparser

然后将自定义解析器添加到您的 ESLint 配置文件中,使用 languageOptions.parser 属性。例如

// eslint.config.js

const myparser = require("eslint-parser-myparser");

module.exports = [{
    languageOptions: {
        parser: myparser
    },
    // ... rest of configuration
}];

当使用旧版配置时,将 parser 属性指定为字符串

// .eslintrc.js

module.exports = {
    parser: "eslint-parser-myparser",
    // ... rest of configuration
};

要了解有关在您的项目中使用 ESLint 解析器的更多信息,请参阅 配置解析器

示例

有关自定义解析器的复杂示例,请参阅 @typescript-eslint/parser 源代码。

一个简单的自定义解析器,它为规则提供了一个 context.sourceCode.parserServices.foo() 方法。

// awesome-custom-parser.js
var espree = require("espree");
function parseForESLint(code, options) {
    return {
        ast: espree.parse(code, options),
        services: {
            foo: function() {
                console.log("foo");
            }
        },
        scopeManager: null,
        visitorKeys: null
    };
};

module.exports = { parseForESLint };

在 ESLint 配置文件中包含自定义解析器

// eslint.config.js
module.exports = [{
    languageOptions: {
        parser: require("./path/to/awesome-custom-parser")
    }
}];

或者如果使用旧版配置

// .eslintrc.json
{
    "parser": "./path/to/awesome-custom-parser.js"
}
更改语言