自定义解析器
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
和可选属性 services
、scopeManager
和 visitorKeys
的对象。
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
的键。- 对
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
) 不能为null
。 ESTree 将loc
属性定义为可空,但 ESLint 需要此属性。SourceLocation#source
属性可以是undefined
。ESLint 不使用SourceLocation#source
属性。
所有节点的 parent
属性必须是可重写的。在任何规则访问 AST 之前,ESLint 在遍历时将每个节点的 parent
属性设置为其父节点。
Program 节点
Program
节点必须具有 tokens
和 comments
属性。这两个属性都是以下 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#range
以检测令牌之间的空格。这必须按Token#range[0]
排序。comments
(Token[]
) 是注释令牌的数组。这必须按Token#range[0]
排序。
所有令牌和注释的范围索引不能与其他令牌和注释的范围重叠。
Literal 节点
Literal
节点必须具有 raw
属性。
raw
(string
) 是此文字的源代码。这与code.slice(node.range[0], node.range[1])
相同。
打包自定义解析器
要将您的自定义解析器发布到 npm,请执行以下操作
- 按照上面 创建自定义解析器 部分创建自定义解析器。
- 为自定义解析器创建一个 npm 包。
- 在您的
package.json
文件中,将main
字段设置为导出自定义解析器的文件。 - 发布 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"
}