const fs = require("fs");//文件读写
const parse = require("@babel/parser"); //解析为ast
const traverse = require('@babel/traverse').default;//遍历节点
const t = require('@babel/types');//类型
const generator = require('@babel/generator').default;//ast解析为代码
const code = `
const a = 1;
const b = a * 2;
const c = 2;
const d = b + 1;
const e = 3;
console.log(d)
`
// 默认为 script,当代码中含有 import 、export 等关键字时会报错,需要指定为 module
const ast = parse.parse(code, {sourceType: "module"})
// 删除多余变量,首先要了解 NodePath 中的 scope,scope 的作用主要是:
// 查找标识符的作用域、获取并修改标识符的所有引用等,删除未使用变量主要用到了 scope.getBinding() 方法,
// 传入的值是当前节点能够引用到的标识符名称,返回的binding对象其关键属性有以下几个:
//
// identifier:标识符的 Node 对象;
// path:标识符的 NodePath 对象;
// constant:标识符是否为常量;
// referenced:标识符是否被引用;
// references:标识符被引用的次数;
// constantViolations:如果标识符被修改,则会存放所有修改该标识符节点的 Path 对象;
// referencePaths:如果标识符被引用,则会存放所有引用该标识符节点的 Path 对象。
// 所以我们可以通过 constantViolations、referenced、references、referencePaths 多个参数来判断变量是否可以被删除
function replace_delete(path) {
const binding = path.scope.getBinding(path.node.id.name);
if (!binding || binding.constantViolations.length > 0) {
return; // 如果表是否被修改过,则不能进行删除
}
if (!binding.referenced) {
path.remove() // 标识符是否被引用,未被引用时可删除
}
// if (binding.references === 0) {
// path.remove(); // 引用次数为0,可以删除节点,注意:remove后面是有括号的
// }
// if (binding.referencePaths.length === 0) {
// path.remove() // 所有引用该标识符节点的Path对象个数为0时,可删除节点
// }
}
const visitor = {
VariableDeclarator: {
enter: [replace_delete]
}
}
traverse(ast, visitor)
const result = generator(ast, {jsescOption: {"minimal": true}}).code
console.log(result)
备注:学习K哥AST笔记