博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Javascript AST] 0. Introduction: Write a simple BabelJS plugin
阅读量:4965 次
发布时间:2019-06-12

本文共 4353 字,大约阅读时间需要 14 分钟。

To write a simple Babel plugin, we can use  to help us.

The plugin we want to write is:

var foo = 'o'var bar = 'o'foo === barfunction 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 === barfunction 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. 

转载于:https://www.cnblogs.com/Answer1215/p/7588047.html

你可能感兴趣的文章
leetcode【67】-Bulb Switcher
查看>>
JS验证图片格式和大小并预览
查看>>
调节心态的十种做法
查看>>
laravel5.2 移植到新服务器上除了“/”路由 ,其它路由对应的页面显示报404错误(Object not found!)———新装的LAMP没有加载Rewrite模块...
查看>>
乱七八糟
查看>>
潜罪犯
查看>>
python函数
查看>>
编写高质量代码--改善python程序的建议(六)
查看>>
windows xp 中的administrator帐户不在用户登录内怎么解决?
查看>>
[spfa] Jzoj P4722 跳楼机
查看>>
代码审计入门后审计技巧
查看>>
Linux-Rsync服务器/客户端搭建实战
查看>>
接口和抽象类有什么区别
查看>>
简单通过百度api自动获取定位-前端实现
查看>>
180117 我的宠物识别判断语句
查看>>
JavaScript修炼之道pdf
查看>>
自己动手构造编译系统++编译、汇编与链接pdf
查看>>
JAVA 中文件读写函数BufferedReader 和 BufferedWriter 的使用
查看>>
Codeforces Round #206 (Div. 2)
查看>>
iOS11和机器学习CoreML库
查看>>