/
index.js
122 lines (103 loc) · 3.05 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
function getFilePathArgument(path, t, state) {
return t.stringLiteral(
`${state.file.opts.filename}:${path.node.loc.start.line}:${
path.node.loc.start.column
}`
);
}
/**
*
*/
function handleFactoryFunction(variableName, path, t, state) {
const paths = path.scope.getBinding(variableName).referencePaths;
if (!paths.length) {
return;
}
// We only care about function invocations
// Statements like `if (debug)` can be left untouched
const variables = paths.filter(path => path.findParent(t.isCallExpression));
variables.forEach(path => {
// `debug('foo')('bar')`
const epxressionStatement = path.findParent(t.isExpressionStatement);
if (epxressionStatement) {
return epxressionStatement
.get('expression')
.node.arguments.push(getFilePathArgument(path, t, state));
}
// const log = debug('foo');
// log('bar')
return handleIdentifier(path.findParent(t.isVariableDeclarator), t, state);
});
}
function handleIdentifier(path, t, state) {
const variableName = path.node.id.name;
const paths = path.scope.getBinding(variableName).referencePaths;
if (!paths.length) {
return;
}
paths.forEach(path => {
if (!t.isCallExpression(path.parent)) {
return;
}
path.parent.arguments.push(getFilePathArgument(path, t, state));
});
}
function shouldRun(state) {
return typeof state.opts.showSource !== 'undefined'
? state.opts.showSource
: true;
}
module.exports = function(babel) {
const { types: t } = babel;
return {
visitor: {
ImportDefaultSpecifier(path, state) {
if (!shouldRun(state)) {
return;
}
if (path.parentPath.get('source').node.value !== 'debug') {
return;
}
return handleFactoryFunction(
path.get('local').node.name,
path,
t,
state
);
},
CallExpression(path, state) {
if (!shouldRun(state)) {
return;
}
if (path.node.callee.name !== 'require') {
return;
}
if (path.node.arguments[0].value !== 'debug') {
return;
}
// immediate invocation `require('debug')('something')`
if (t.isCallExpression(path.parentPath.get('callee'))) {
const identifier = path.findParent(t.isVariableDeclarator);
if (!identifier) {
return;
}
return handleIdentifier(identifier, t, state);
}
// require with later usage
// `const debug = require('debug');`
// const log = debug('foo');
// log('bar')
// or debug('foo')('bar')
// get whatever var was used to require `debug` to
const variableDeclaration = path.findParent(t.isVariableDeclarator);
// `require('debug')` without any variable assignment
if (!variableDeclaration) {
return;
}
const variableName = path.findParent(t.isVariableDeclarator).node.id
.name;
return handleFactoryFunction(variableName, path, t, state);
}
}
};
};