[Javascript AST] 0. Introduction: Write a simple BabelJS plugin
Posted Answer1215
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Javascript AST] 0. Introduction: Write a simple BabelJS plugin相关的知识,希望对你有一定的参考价值。
To write a simple Babel plugin, we can use http://astexplorer.net/ to help us.
The plugin we want to write is:
var foo = \'o\' var bar = \'o\' foo === bar function foo(foo, bar) { foo === bar; }
We want to trasnform the code which highlighted in foo() function to:
_foo === _bar
Notice that, we also have \'foo === bar\' which is not inside foo() function. But we don\'t want to touch that.
To get started, we have code below:
export default function(babel) { const { types: t } = babel; return { name: "add_underscore", visitor: { // your code here } }; }
All the code is under \'visitor\' prop.
By hightlight the code we can see, it is a \'BinaryExpression\':
So we focus on \'BinaryExpression\':
export default function(babel) { const { types: t } = babel; return { name: "add_underscore", visitor: { BinaryExpression(path) { } } }; }
\'path\' param contains all the information we need.
If add a console.log() inside BinarayExpression() function, we can see two logs, one is from global scope, another one is from \'foo()\' scope. We only want to get one from foo() function scope:
The way to do is check \'path.scope.block.type\', which is current code\' block scope.
\'foo === bar\' exisits on global belongs to \'Program\':
the one exists in foo() belongs to \'BlockStatement\':
BinaryExpression(path) {
// remove global one if (path.scope.block.type === "Program") { return; } }
And the opreator we want to check is \'===\':
BinaryExpression(path) { if (path.scope.block.type === "Program") { return; } if (path.node.operator !== "===") { return; }
}
Now we have located the one \'foo === bar\' we want, we can start to replace the name:
export default function(babel) { const { types: t } = babel; return { name: "add_underscore", visitor: { BinaryExpression(path) { if (path.scope.block.type === "Program") { return; } if (path.node.operator !== "===") { return; } // locate the \'foo\' and \'bar\' // as left and right Identifier const leftIdentifier = path.node.left; const rightIndentifier = path.node.right; // generate a new identifier const newLeftIdentifier = path.scope.generateUidIdentifier(leftIdentifier.name); const newRightIdentifier = path.scope.generateUidIdentifier( rightIndentifier.name ); // replace the old with new one path.node.left = t.identifier(newLeftIdentifier.name); path.node.right = t.identifier(newRightIdentifier.name); } } }; }
Now the generate code looks like:
var foo = \'o\' var bar = \'o\' foo === bar function foo(foo, bar) { _foo === _bar; }
The code have successfully transform to \'_foo === _bar\'.
But clearly the code won\'t work, because _foo and _bar is undefined.
We need to update the params in the function as well.
// update params in the function const [fooParam, barParam] = path.scope.block.params; fooParam.name = t.identifier(newLeftIdentifier.name).name; barParam.name = t.identifier(newRightIdentifier.name).name;
All Code:
export default function(babel) { const { types: t } = babel; return { name: "add_underscore", visitor: { BinaryExpression(path) { if (path.scope.block.type === "Program") { return; } if (path.node.operator !== "===") { return; } // locate the \'foo\' and \'bar\' // as left and right Identifier const leftIdentifier = path.node.left; const rightIndentifier = path.node.right; // generate a new identifier const newLeftIdentifier = path.scope.generateUidIdentifier(leftIdentifier.name); const newRightIdentifier = path.scope.generateUidIdentifier( rightIndentifier.name ); // replace the old with new one path.node.left = t.identifier(newLeftIdentifier.name); path.node.right = t.identifier(newRightIdentifier.name); // update params in the function const [fooParam, barParam] = path.scope.block.params; fooParam.name = t.identifier(newLeftIdentifier.name).name; barParam.name = t.identifier(newRightIdentifier.name).name; } } }; }
[Notice]: this is a just learning note for myself. The approache might not be optimal.
以上是关于[Javascript AST] 0. Introduction: Write a simple BabelJS plugin的主要内容,如果未能解决你的问题,请参考以下文章