-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathremove-unused.js
87 lines (74 loc) · 2.22 KB
/
remove-unused.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
const babelParser = require('@babel/parser');
const babelTraverse = require('@babel/traverse').default;
const babelGenerator = require('@babel/generator').default;
const t = require('@babel/types');
function removeUnused(fileContent, options) {
const { keepImports, keepVars } = options;
// Parse the JavaScript file to an AST
const ast = babelParser.parse(fileContent, {
sourceType: 'module',
plugins: ['jsx', 'classProperties'],
});
const importWhitelist = new Set(keepImports);
const variableWhitelist = new Set(keepVars);
const classProperties = new Map();
babelTraverse(ast, {
ImportDeclaration: {
exit(path) {
const shouldBeRemoved = path.node.specifiers.every((specifier) => {
const localName = specifier.local.name;
const binding = path.scope.getBinding(localName);
return (
!importWhitelist.has(localName) &&
binding &&
binding.referencePaths.length === 0
);
});
if (shouldBeRemoved) {
path.remove();
}
},
},
VariableDeclarator: {
exit(path) {
const variableName = path.node.id.name;
const binding = path.scope.getBinding(variableName);
if (
!variableWhitelist.has(variableName) &&
binding &&
binding.referencePaths.length === 0
) {
path.remove();
}
},
},
AssignmentExpression: {
exit(path) {
if (t.isMemberExpression(path.node.left) && t.isThisExpression(path.node.left.object)) {
const variableName = path.node.left.property.name;
classProperties.set(variableName, path);
}
},
},
MemberExpression: {
exit(path) {
if (path.node.object.type === 'ThisExpression') {
const variableName = path.node.property.name;
if (classProperties.has(variableName)) {
classProperties.delete(variableName);
}
}
},
},
});
classProperties.forEach((path, variableName) => {
if (!variableWhitelist.has(variableName)) {
path.remove();
}
});
const { code } = babelGenerator(ast, {
retainLines: true,
});
return code;
}
module.exports = removeUnused;