Babylon-AST初探-代碼更新&刪除(Update & Remove)

  經過前兩篇文章的介紹,你們已經瞭解了CreateRetrieve,咱們接着介紹UpdateRemove操做。Update操做一般配合Create來完成。咱們這篇文章主要介紹幾個經常使用的NodePath`APIreplaceinsertremove`。具體也能夠看babel-handbook中的Manipulation章節vue

replaceWith 使用新的節點進行替換

將加法運算替換成乘法

const code = `const c = a + b`
const ast = babylon.parse(code)

traverse(ast, {
  BinaryExpression(path) {
    // 注意這裏要有判斷,不然會無限進入`BinaryExpression`
    // https://stackoverflow.com/questions/37539432/babel-maximum-call-stack-size-exceeded-while-using-path-replacewith
    if (path.node.operator === '+') {
      path.replaceWith(t.binaryExpression('*', path.node.left, path.node.right))
    }
  }
})

console.log(generate(ast, {}, code).code) // const c = a * b;

this.count替換爲this.data.count

  轉換先後的AST展現以下圖:node

圖片描述

  咱們須要作的是,找到符合this.countThisExpression,而後把它替換爲this.datagit

const code = `this.count`
const ast = babylon.parse(code)

traverse(ast, {
  MemberExpression(path) {
    if (
      t.isThisExpression(path.node.object) &&
      t.isIdentifier(path.node.property, {
        name: 'count'
      })
    ) {
      path
        .get('object')    // 獲取`ThisExpresssion`
        .replaceWith(
          t.memberExpression(t.thisExpression(), t.identifier('data'))
        )
    }
  }
})
console.log(generate(ast, {}, code).code) // this.data.count;

replaceWithSourceString 直接使用代碼替換

  上個例子中將this.count替換爲this.data.count的部分,經過t.memberExpression能夠構造node。更簡單的操做能夠直接使用replaceWithSourceString,我的以爲這個API很好用。github

path.get('object').replaceWithSourceString('this.data')

插入操做

  插入是樹操做的一種常見操做。子節點是個Array,前、中、後各類位置均可以插入新節點。下面來介紹下pushContainerunshiftContainerinsertBeforeinsertAfter操做。小程序

  這裏以給obj對象新增一個屬性myprop: 'hello my property'爲例:數組

const code = `
const obj = {
  count: 0,
  message: 'hello world'
}
`
const ast = babylon.parse(code)

const property = t.objectProperty(
  t.identifier('myprop'),
  t.stringLiteral('hello my property')
)

pushContainer 父節點的操做

  父節點爲子節點Array插入一個nodebabel

traverse(ast, {
  ObjectExpression(path) {
    path.pushContainer('properties', property)
  }
})

insertAfter 兄弟節點的操做

  insertAfter也能夠完成上述操做,須要找到message屬性,而後在後面插入node就搞定啦ide

traverse(ast, {
  ObjectProperty(path) {
    if (
      t.isIdentifier(path.node.key, {
        name: 'message'
      })
    ) {
      path.insertAfter(property)
    }
  }
})

  unshiftContainerinsertBefore與上面兩個相對應,這裏再也不舉例了,你們能夠本身試一試。ui

  由於properties是個數組,所以,咱們能夠直接使用數組操做this

traverse(ast, {
  ObjectExpression(path) {
    // path.pushContainer('properties', property)
    path.node.properties.push(property)
  }
})

Remove 自我毀滅

  Remove方法極爲簡單,找到要刪除的NodePath,執行Remove就結束了。如上述代碼,咱們要刪除message屬性,代碼以下:

traverse(ast, {
  ObjectProperty(path) {
    if (
      t.isIdentifier(path.node.key, {
        name: 'message'
      })
    ) {
      path.remove()
    }
  }
})

到目前爲止,AST的CURD咱們都介紹完了,下面一篇文章以vue小程序爲例,咱們來實戰一波。

相關文章
相關標籤/搜索