-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlodash-get-to-optional-member-expressions.js
116 lines (95 loc) · 2.93 KB
/
lodash-get-to-optional-member-expressions.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
module.exports = function transformer(file, api) {
const j = api.jscodeshift;
const root = j(file.source);
const removeLodashDefaultImports = () =>
root
.find(j.ImportDeclaration)
.filter(path => path.node.source.value === 'lodash.get')
.forEach(path => j(path).remove());
const removeLodashNamedImports = () =>
root
.find(j.ImportDeclaration)
.filter(
path =>
path.node.source.value === 'lodash' ||
path.node.source.value === 'lodash-es'
)
.forEach(path => {
if (path.node.specifiers.some(s => s.imported)) {
const filteredSpecs = path.node.specifiers.filter(
s => s.imported.name !== 'get'
);
let newPath = { node: path.node };
newPath.node.specifiers = filteredSpecs;
j(path).replaceWith(newPath.node);
}
});
let membersVisited = 0;
const memberBuilder = expressions => {
memExs = [];
membersVisited++;
if (membersVisited <= expressions.length) {
const name = expressions[membersVisited - 1];
// Find deeper properties
if (membersVisited !== expressions.length - 1) {
return j.optionalMemberExpression(
memberBuilder(expressions),
j.identifier(name)
);
}
// Last member expression
membersVisited = 0;
return j.optionalMemberExpression(
j.identifier(expressions[expressions.length - 1]),
j.identifier(name)
);
}
return;
};
let memExs = [];
const getAllMemberExpressions = expression => {
if (expression.object) {
memExs.push(expression.property.name);
getAllMemberExpressions(expression.object);
} else {
memExs.push(expression.name);
}
return memExs.reverse();
};
const handleExpression = path => {
const ex = path.value.arguments[0];
let base = {};
if (ex.type === 'MemberExpression') {
base = getAllMemberExpressions(ex);
} else {
base = [path.value.arguments[0].name];
}
const pathParts = path.value.arguments[1].value.split('.');
const defaultValue = path.value.arguments[2] || undefined;
const fullExpressionPath = [...base].concat(pathParts).reverse();
const node = memberBuilder(fullExpressionPath);
let newPath = {};
if (defaultValue !== undefined) {
const operator = '||';
const left = node;
const right = defaultValue;
const logicalExpression = j.logicalExpression(operator, left, right);
newPath = {
...path,
node: logicalExpression,
};
} else {
newPath = { ...path, node };
}
j(path).replaceWith(newPath.node);
};
const transformGetExpressions = () =>
root
.find(j.CallExpression)
.filter(e => e.value.callee.name === 'get')
.forEach(handleExpression);
removeLodashNamedImports();
removeLodashDefaultImports();
transformGetExpressions();
return root.toSource();
};