跳到主要内容

替换节点

2024年11月10日
柏拉文
越努力,越幸运

一、认识


二、语法


const replaceWith = (ast, targetNode, newNode) => {
visit(ast, {
[targetNode.type]: (node, parent) => {
if (node === targetNode) {
for (const key in parent) {
if (parent.hasOwnProperty(key)) {
if (Array.isArray(parent[key])) {
parent[key] = parent[key].map((child) =>
child === targetNode ? newNode : child
);
} else if (parent[key] === targetNode) {
parent[key] = newNode;
}
}
}
}
},
});
};

三、场景


3.1 将 var 替换为 let

const swc = require("@swc/core");

const { parseSync, printSync } = swc;

const parse = (sourceCode) => {
try {
const result = parseSync(sourceCode, {
syntax: "ecmascript",
jsx: false,
});
return result;
} catch (error) {
console.error("Error parsing source code:", error);
return null;
}
};

const visit = (ast, visitor) => {
function traverse(node, parent) {
if (!node || typeof node !== "object") return;

if (visitor[node.type]) {
visitor[node.type](node, parent);
}

for (const key in node) {
if (!node.hasOwnProperty(key)) continue;

const child = node[key];
if (Array.isArray(child)) {
child.forEach((c) => traverse(c, node));
} else if (child && typeof child === "object") {
traverse(child, node);
}
}
}

traverse(ast, null);
};

const find = (ast, type) => {
const nodes = [];
visit(ast, {
[type]: (node) => {
nodes.push(node);
},
});
return nodes;
};

const replaceWith = (ast, targetNode, newNode) => {
visit(ast, {
[targetNode.type]: (node, parent) => {
if (node === targetNode) {
for (const key in parent) {
if (parent.hasOwnProperty(key)) {
if (Array.isArray(parent[key])) {
parent[key] = parent[key].map((child) =>
child === targetNode ? newNode : child
);
} else if (parent[key] === targetNode) {
parent[key] = newNode;
}
}
}
}
},
});
};

async function main() {
const sourceCode = `var a = 1; var b = 2; var c = () => { var d = 3; return d; };`;
const ast = parse(sourceCode);

if (!ast) return;

// Find all VariableDeclaration nodes
const variableDeclarations = find(ast, "VariableDeclaration");

// Replace var with const
variableDeclarations.forEach((node) => {
if (node.kind === "var") {
const newNode = { ...node, kind: "let" };
replaceWith(ast, node, newNode);
}
});

// Convert AST back to source code
const newSourceCode = printSync(ast).code;
console.log(newSourceCode);
}

main();