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) }