「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
你不知道的——AST抽象语法树第二篇
来自我的公众号文章:你不知道的——AST抽象语法树第二篇(基本使用示例) 在讨论AST的使用示例之前,我们先来大致了解一下 AST 解析之后的各个部分分别代表的是什么?
输入代码:var demo = 123
下方为解析结果:
{ // 当前这一段代码的基本信息
"type": "Program",
"start": 0, // 开始的字符位置
"end": 14, // 结束的字符位置,总长度是包括代码中的空格的
"body": [ // 该代码的具体内容
{
"type": "VariableDeclaration", // 类型为变量声明
"start": 0,
"end": 14,
"declarations": [ // 该变量声明的内容
{
"type": "VariableDeclarator",
"start": 4, // 内容的开始
"end": 13, // 内容的结束
"id": {
"type": "Identifier", // 声明的标识
"start": 4, // 标识开始
"end": 7, // 标识结束
"name": "foo" // 该表示的名称
},
"init": { // 声明的数据类型为 init 类型
"type": "Literal",
"start": 10, // 数据的开始
"end": 13, // 数据的结束
"value": 123, // 数据的 value 值
"raw": "123" // 声明的原始数据
}
}
],
"kind": "var" // 声明的类型,为 var 常量
}
],
"sourceType": "module" // 来源类型
}
如果你仔细看了以上变量声明表达式的解析模块,以及每个模块表达的是什么内容,你应该已经对简单的使用 AST ,及运行、使用原理有个基本的了解。
如果你已经完全看懂以上代码,说明你已经懂得了 ESLint 是怎么检查你的代码是否符合规则的了。
没错,就是根据解析出来这段代码的所有细则,然后检查,这段代码的每一部分,是否与你选择指定的检查规则有冲突。
如果有冲突,则在控制台打印出冲突的严重程度,给出黄色字体的警告或者红色字体的报错
还记得在 ESLint 的文章中给大家提供的 ESLint 的格式化代码吗?
文章传送门十九,公众号:前端学海 ESlint——可组装的JavaScript和JSX检查工具
该代码配合 VsCode 的插件,可以将你的代码不符合 ESLint 检查规则的代码,自动格式为符合代码规则的代码,运行原理,就是查找到错误的代码,通过 AST 解析代码,在语法树中修改错误的部分,然后将修改后的 AST 语法树合并生成新的符合规则的代码。
开始
通过使用 AST 解析和生成函数,来实现代码的自动修改
const demo = 123
将以上代码修改为
var demo = 234
1、安装
npm i recast -S
const recast = require('recast')
// 根据需要修改的部分,使用不同的函数方法
const {
variableDeclaration,
variableDeclarator,
identifier,
literal
} = recast.types.builders
// 解析 const demo = 123
const ast = recast.parse('const demo = 123')
// 需要更改的语法树的数据的位置
// 不同的解析器,存储对象的位置可能不同,
// 切记,根据使用的解析器的解析逻辑去修改语法树
const body = ast.program.body[0]console.log(ast, '解析前的语法树')
// 找到const所在的位置,并将值替换为 var
// 找到值的标记 将内容替换为 ‘234’
// 根据需要修改的部分,合理嵌套使用内部函数,进行修改
ast.program.body[0] = variableDeclaration(
'var',[ // 将const 改为 var
variableDeclarator(
identifier('demo'),
literal(234) // 将值变为 ‘234’
)
])
// 现在的 AST 语法树为已经修改之后语法树,
console.log(ast, '解析后的语法树')
// 将 AST 对象重新转回可以阅读的代码
const newAST = recast.print(ast).code;
// 修改后生成的新代码
console.log(newAST, '修改后生成的新代码')
👇最后执行文件,输入结果如下👇
End 齐活
其实 Babel 的运行原理与我们刚刚的示例非常相像,但 Babel 的使用的 AST 解析器与 ESLint 又有所不同。