zoukankan      html  css  js  c++  java
  • [AST Babel Plugin] Hanlde ArrowFunction && FunctionExpression

    Continue with previous post: https://www.cnblogs.com/Answer1215/p/12342540.html

    Now we need to think about functionExpression and ArrowFunction:

    function add(a, b) {
        console.log(a, b)
          return a + b
    }
    
    function subtract(a, b) {
        console.log(a, b)
          return a - b
    }
    
    const multiply = (a, b) => {
        console.log(a, b)
          return a * b;
    }
    
    const divide = function(a, b) {
        console.log(a, b)
          return a / b;
    }
    
    add(1, 2)
    subtract(2, 1)
    multiply(3, 4)
    divide(25, 5)
    console.log('sup dawg')

    Transform code:

    export default function(babel) {
      const { types: t } = babel;
    
      function getFnName(path) {
        const expOrArwFn = path.findParent(t.isVariableDeclaration);
        const parentFn = path.findParent(t.isFunctionDeclaration);
        let faName = "";
        if (parentFn) {
          faName = `${parentFn.node.id.name} `;
        } else if (expOrArwFn) {
          faName = `${expOrArwFn.node.declarations[0].id.name} `;
        } else {
          faName = "";
        }
    
        return faName;
      }
    
      return {
        name: "ast-transform", // not required
        visitor: {
          CallExpression(path) {
            if (
              !looksLike(path.node, {
                callee: {
                  type: "MemberExpression",
                  object: {
                    name: "console"
                  },
                  property: {
                    name: "log"
                  }
                }
              })
            ) {
              return;
            }
    
            // insert string into console.log('instread here', a,b)
            const { line, column } = path.node.loc.start;
            const fnName = getFnName(path);
            const prefix = fnName + `${line}:${column}`;
            path.node.arguments.unshift(t.stringLiteral(prefix));
          }
        }
      };
    }
    
    function looksLike(a, b) {
      return (
        a &&
        b &&
        Object.keys(b).every(bKey => {
          const bVal = b[bKey];
          const aVal = a[bKey];
          if (typeof bVal === "function") {
            return bVal(aVal);
          }
          return isPrimitive(bVal) ? bVal === aVal : looksLike(aVal, bVal);
        })
      );
    }
    
    function isPrimitive(val) {
      return val == null || /^[sbn]/.test(typeof val);
    }

    Output:

    function add(a, b) {
        console.log("add 2:4", a, b)
          return a + b
    }
    
    function subtract(a, b) {
        console.log("subtract 7:4", a, b)
          return a - b
    }
    
    const multiply = (a, b) => {
        console.log("multiply 12:4", a, b)
          return a * b;
    }
    
    const divide = function(a, b) {
        console.log("divide 17:4", a, b)
          return a / b;
    }
    
    add(1, 2)
    subtract(2, 1)
    multiply(3, 4)
    divide()
    console.log("25:0", 'sup dawg')

    Other solutions;

    export default function(babel) {
      const {types: t} = babel
    
      return {
        name: 'captains-log',
        visitor: {
          CallExpression(path) {
            if (
              !looksLike(path, {
                node: {
                  callee: {
                    type: 'MemberExpression',
                    object: {
                      name: 'console',
                    },
                  },
                },
              })
            ) {
              return
            }
            let prefix = ''
            const functionName = getFunctionName(path)
            if (functionName) {
              prefix += functionName
            }
            const start = path.node.loc.start
            prefix += ` ${start.line}:${start.column}`
            path.node.arguments.unshift(t.stringLiteral(prefix.trim()))
          },
        },
      }
    
      function getFunctionName(path) {
        const parentFunction = path.findParent(parent => {
          return (
            t.isFunctionDeclaration(parent) ||
            t.isArrowFunctionExpression(parent) ||
            t.isFunctionExpression(parent)
          )
        })
        if (!parentFunction) {
          return null
        }
        if (looksLike(parentFunction, {node: {id: t.isIdentifier}})) {
          return parentFunction.node.id.name
        } else if (
          t.isVariableDeclarator(parentFunction.parent) ||
          t.isFunctionExpression(parentFunction.parent)
        ) {
          return parentFunction.parent.id.name
        }
        return null
      }
    }
    
    function looksLike(a, b) {
      return (
        a &&
        b &&
        Object.keys(b).every(bKey => {
          const bVal = b[bKey]
          const aVal = a[bKey]
          if (typeof bVal === 'function') {
            return bVal(aVal)
          }
          return isPrimitive(bVal) ? bVal === aVal : looksLike(aVal, bVal)
        })
      )
    }
    
    function isPrimitive(val) {
      return val == null || /^[sbn]/.test(typeof val)
    }
  • 相关阅读:
    Java基础知识回顾
    设计模式简单回顾
    数据结构基础知识
    《More Effective C#》读书笔记
    《Effective C#》读书笔记
    《编程匠艺》读书笔记
    《Scrum实战》读书会作业01
    开始一段新的敏捷学习之旅 —— IT帮读书会第4期《Scrum实战》
    【译】别学框架,学架构
    AngularJS学习笔记(1)
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12342634.html
Copyright © 2011-2022 走看看