Versions

自定义解析器

ESLint 自定义解析器用于扩展 ESLint,以支持检查代码中新的非标准 JavaScript 语言功能或自定义语法。解析器负责提取代码并将其转换为抽象语法树(AST),ESLint 可对其进行分析和检查。

创建自定义解析器

自定义解析器中的方法

自定义解析器是一个 JavaScript 对象,带有 parseparseForESLint 方法。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 对象。
    • 在 ESLint v4.14.0 中加入了对 scopeManager 的支持。支持 scopeManager 的 ESLint 版本将在 parserOptions 中提供 eslintScopeManager: true 属性,可用于特征检测。
  • visitorKeys 可以是自定义 AST 遍历的对象。该对象的键是 AST 节点的类型。每个值是一个应该被遍历的属性名称的数组。默认为 eslint-visitor-keys 的键
    • 在 ESLint v4.14.0 中加入了对 visitorKeys 的支持。支持 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 属性。

  • rangenumber[])是一个由两个数字组成的数组。这两个数字都是基于 0 的索引,表示源代码字符数组中的位置。第一个是节点的起始位置,第二个是节点的结束位置。code.slice(node.range[0], node.range[1]) 必须是该节点的文本。这个范围不包括节点周围的空格/括号。
  • loc (SourceLocation) 不能是 nullESTreeloc 属性定义为 nullable,但 ESLint 需要这个属性。另一方面 SourceLocation#source 属性也可以是 undefined。ESLint 不使用 SourceLocation#source 属性。

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

Program 节点

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

interface Token {
    type: string;
    loc: SourceLocation;
    range: [number, number];
    // 参见“所有节点”部分,了解 `range` 属性的细节。
    value: string;
}
  • tokensToken[])是影响程序行为的令牌阵列。令牌之间可能存在任意的空间,所以规则会检查 Token#range 以检测令牌之间的空间。这必须按 Token#range[0] 进行排序。
  • commentsToken[])是评论标记的阵列。这必须按 Token#range[0] 排序。

所有标记和评论的范围索引必须不与其他标记和评论的范围重叠。

Literal 节点

Literal 节点必须要有 raw 属性。

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

打包自定义解析器

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

  1. 按照上述创建自定义分析程序部分创建自定义解析器。
  2. 给自定义解析器创建 npm 包
  3. package.json 文件中,将 main 字段设置为导出自定义解析器的文件。
  4. 发布 npm 软件包。

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

发布 npm 软件包后,将软件包添加到项目中即可使用。例如

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

然后使用 parser 属性将自定义分析程序添加到 ESLint 配置文件中。例如:

// .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 配置文件中包括自定义解析器:

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