跳到主要内容

认识

acorn 可以把代码转化为抽象语法树。解析结果符合The Estree Spec规范。

准备


安装acorn依赖

yarn add acorn -D

开始


acorn.parse()

const acorn = require("acorn");

const source = `import $ from "jquery"`;
const ast = acorn.parse(source, {
location: true,
ranges: true,
sourceType: "module",
ecmaVersion: 8,
});
console.log(ast); // Node { type: 'Program',start:0,end:22,range:[0,22],body:[……]}

acorn 遍历

acorn 不可以借助依赖遍历,这里自己实现了遍历

walk.js 遍历
function walk(ast, { enter, leave }) {
visit(ast, null, enter, leave);
}

function visit(astNode, parent, enter, leave) {
if (enter) {
enter.call(null, astNode, parent);
}
const childKeys = Object.keys(astNode).filter(
(key) => typeof astNode[key] === "object"
);
childKeys.forEach((childKey) => {
let value = astNode[childKey];
if (Array.isArray(value)) {
value.forEach((val) => visit(val, astNode, enter, leave));
} else if (value && value.type) {
visit(value, astNode, enter, leave);
}
});
if (leave) {
leave.call(null, astNode, parent);
}
}

module.exports = walk;
acorn 应用遍历
const acorn = require("acorn");
const walk = require('./walk');

const source = `import $ from "jquery"`;
const ast = acorn.parse(source, {
location: true,
ranges: true,
sourceType: "module",
ecmaVersion: 8,
});
console.log(ast); // Node { type: 'Program',start:0,end:22,range:[0,22],body:[……]}


let ident = 0;
const padding = () => " ".repeat(ident);
ast.body.forEach((statement) => {
walk(statement, {
enter(node) {
if (node.type) {
console.log(padding() + node.type + "进入");
ident += 2;
}
},
leave(node) {
if (node.type) {
ident -= 2;
console.log(padding() + node.type + "离开");
}
},
});
});