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 example = function () {
let a;
if (false) {
a = 1;
} else {
if (1) {
a = 2;
}
else {
a = 3;
}
}
return a;
};
`
// 默认为 script,当代码中含有 import 、export 等关键字时会报错,需要指定为 module
const ast = parse.parse(code, {sourceType: "module"})
// 判断条件对应的是 test 节点,if 对应的是 consequent 节点,else 对应的是 alternate 节点
// AST 处理思路以及代码:
//
// 筛选出 BooleanLiteral 和 NumericLiteral 节点,取其对应的值,即 path.node.test.value;
// 判断 value 值为真,则将节点替换成 consequent 节点下的内容,即 path.node.consequent.body;
// 判断 value 值为假,则判断else节点是否存在,存在时替换成 alternate 节点下的内容,即 path.node.alternate.body;
// 有的 if 语句可能没有写 else,也就没有 alternate,所以这种情况下判断 value 值为假,则直接移除该节点,即 path.remove()
function replace_if_else(path) {
const test = path.node.test
// if (t.isBooleanLiteral(test) || t.isNumberLiteral(test)) { //if(当前的筛选节点)
if (t.isBooleanLiteral(test) || t.isNumericLiteral(test)) { //if(当前的筛选节点) 注意:别写错节点名称
if (test.value) { // 如果if括号里面的内容为真,则将if包含的内容节点替换判断节点
path.replaceInline(path.node.consequent.body)
} else {
if (path.node.alternate) { // 如果else节点存在则,则else里面的内容节点替换判断节点
path.replaceInline(path.node.alternate.body)
} else {
path.remove() // 如果else节点不存在,则直接删除if节点,注意:当前path是if节点
}
}
}
}
const visitor = {
enter: [replace_if_else]
}
traverse(ast, visitor)
const result = generator(ast, {jsescOption: {"minimal": true}}).code
console.log(result)
备注:学习K哥AST笔记