你不知道的——AST抽象语法树第二篇(基本使用示例)

581 阅读3分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。

你不知道的——AST抽象语法树第二篇

上一篇 你不知道的——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 又有所不同。

图片