您可以在putout 代码转换器的帮助下跟踪函数调用。Plugin
看起来是这样的:
const {template, types, operator} = require('putout');
const {replaceWith} = operator;
const {BlockStatement} = types;
// create nodes
const buildLog = template(`console.log('TYPE' + ' ' + 'NAME')`);
const buildLogEnter = template(`console.log('enter' + ' ' + 'NAME' + '(' + JSON.stringify(Array.from(arguments)) + ')')`);
const buildLogException = template(`console.log('TYPE' + ' ' + 'NAME' + ': ' + trace$error.message); throw trace$error`);
const buildTryCatch = template(`try {
BLOCK;
} catch(trace$error) {
CATCH;
} finally {
FINALLY;
}
`);
const JSON = 'JSON';
// nodes we are searching for
module.exports.include = () => [
'Function',
];
module.exports.fix = (path) => {
const name = getName(path);
// create 3 types of events
const enterLog = buildLogEnter({
NAME: name,
JSON,
});
const exitLog = buildLogEvent(name, 'exit');
const errorLog = buildLogExceptionEvent(name);
// move function body into try-catch
const bodyPath = path.get('body');
replaceWith(bodyPath, BlockStatement([buildTryCatch({
BLOCK: path.node.body.body,
CATCH: errorLog,
FINALLY: exitLog,
})]));
// add into the beginning of function "console.log" with "enter" event
bodyPath.node.body.unshift(enterLog);
};
// get name of a function
function getName(path) {
if (path.isClassMethod())
return path.node.key.name;
if (path.isFunctionDeclaration())
return path.node.id.name;
const {line} = path.node.loc.start;
return `<anonymous:${line}>`;
}
// build logger
function buildLogEvent(name, type) {
return buildLog({
NAME: name,
TYPE: type,
});
}
// build logger that throws
function buildLogExceptionEvent(name) {
return buildLogException({
NAME: name,
TYPE: 'error',
});
}
假设这是您要跟踪的代码:
const processFile = (a) => a;
process([]);
function process(runners) {
const files = getFiles(runners);
const linted = lintFiles(files);
return linted;
}
function getFiles(runners) {
const files = [];
for (const run of runners) {
files.push(...run());
}
return files;
}
function lintFiles(files) {
const linted = [];
for (const file of files) {
linted.push(processFile(file));
}
return linted;
}
这是一张完整的图片:
如果您将处理后的源代码另存为trace.js
并使用节点运行它,您将拥有:
> node trace.js
enter process([[]])
enter getFiles([[]])
exit getFiles
enter lintFiles([[]])
exit lintFiles
exit process
存在与跟踪功能相关的问题。