m90*_*m90 5 javascript babeljs babel-plugin
我正在尝试编写一个简单的 babel 插件,但是我很难用嵌套访问者遍历匹配的节点。我想require在需要某个模块的模块中找到所有调用,然后在同一范围内应用一些转换。
为了用一个人为的例子来说明这一点,我想转换源代码,如:
const f = require('foo-bar');
const result = f() * 2;
Run Code Online (Sandbox Code Playgroud)
变成类似的东西:
const result = 99 * 2; // as i "know" that calling f will always return 99
Run Code Online (Sandbox Code Playgroud)
我试图做到以下几点:
module.exports = ({ types: t }) => ({
visitor: {
CallExpression(path) {
if (path.node.callee.name === 'require'
&& path.node.arguments.length === 1
&& t.isStringLiteral(p.node.arguments[0])
&& path.node.arguments[0].value === 'foo-bar'
) {
const localIdentifier = path.parent.id.name;
// if i print here it will show me that it successfully
// found all require calls
p.scope.traverse({
Identifier(subp) {
// this will never run at all
if (subp.name === localIdentifier) {
console.log('MATCH!');
}
}
});
}
}
}
});
Run Code Online (Sandbox Code Playgroud)
我的方法是否有缺陷,或者我需要从代码角度做一些不同的事情?
我知道这个问题很老了,但是这个答案对于通过谷歌到达这里的人来说可能很有用。您可以在另一个遍历中使用一个遍历node.scope.traverse,例如,如果您CallExpression只想在 的主体内部更改每个遍历try:
module.exports = ({ types: t }) => ({
visitor: {
TryStatement(path) {
const { scope, node } = path
const traversalHandler = {
CallExpression(path) {
path.replaceWith(t.Identifier('foo'))
}
}
scope.traverse(node, traversalHandler, this)
}
}
})
Run Code Online (Sandbox Code Playgroud)
我似乎找不到太多关于path.scope.traverse.
已经快两年了,但我希望这能解决你的问题。
module.exports = ({ types: t }) => ({
visitor: {
CallExpression(path) {
if (path.node.callee.name === 'require'
&& path.node.arguments.length === 1
&& t.isStringLiteral(path.node.arguments[0])
&& path.node.arguments[0].value === 'foo-bar'
) {
this.localIdentifier = path.parent.id.name;
}
if(path.node.callee.name === this.localIdentifier){
path.replaceWith(t.NumericLiteral(99))
}
}
}
});
Run Code Online (Sandbox Code Playgroud)