zhongweinan 2020-02-21
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)
}