[Javascript AST] 0. Introduction: Write a simple BabelJS plugin

來源:互聯網
上載者:User

標籤:function   write   app   elf   node   visitor   net   can   undefined   

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 === 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. 

[Javascript AST] 0. Introduction: Write a simple BabelJS plugin

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.