-
Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathremove-vue-set-and-delete.ts
110 lines (90 loc) · 2.94 KB
/
remove-vue-set-and-delete.ts
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
// To remove:
// Vue.set / Vue.delete
// this.$set / this.$delete
// vm = this; this.$set / this.$delete
import wrap from '../src/wrapAstTransformation'
import type { ASTTransformation } from '../src/wrapAstTransformation'
import type * as N from 'jscodeshift'
export const transformAST: ASTTransformation = (context) => {
const { root, j } = context
const isVue = (node: N.ASTNode) => {
return j.Identifier.check(node) && node.name === 'Vue'
}
const setOrDeleteCalls = root
.find(j.CallExpression, (n: N.CallExpression) => {
if (
!j.MemberExpression.check(n.callee) ||
!j.Identifier.check(n.callee.property)
) {
return false
}
const propName = n.callee.property.name
if (
(propName === 'set' || propName === 'delete') &&
isVue(n.callee.object)
) {
return true
}
if (propName === '$set' || propName === '$delete') {
// we need the path & scope to check if the object is `this`
// so leave it to the filter function
return true
}
return false
})
.filter((path) => {
const prop = (path.node.callee as N.MemberExpression)
.property as N.Identifier
// only the object of `.$set` and `.$delete` is pending for check
if (prop.name !== '$set' && prop.name !== '$delete') {
return true
}
const obj = (path.node.callee as N.MemberExpression).object
if (j.ThisExpression.check(obj)) {
return true
}
if (!j.Identifier.check(obj)) {
return false
}
const decls = j(path).getVariableDeclarators((p) => obj.name)
if (decls && decls.length === 1) {
const declPath = decls.paths()[0]
const declNode = declPath.node
const declStmt = declPath.parent.node
return (
j.VariableDeclarator.check(declNode) &&
(declStmt as N.VariableDeclaration).kind === 'const' &&
j.Identifier.check(declNode.id) &&
j.ThisExpression.check(declNode.init)
)
}
return false
})
setOrDeleteCalls.replaceWith(({ node }) => {
if (node.arguments.some((arg) => j.SpreadElement.check(arg))) {
// TODO: add a comment to inform the user that this kind of usage can't be transformed
return node
}
const prop = (node.callee as N.MemberExpression).property as N.Identifier
if (prop.name === '$set' || prop.name === 'set') {
return j.assignmentExpression(
'=',
// @ts-ignore
j.memberExpression(node.arguments[0], node.arguments[1], true),
// @ts-ignore
node.arguments[2]
)
}
if (prop.name === '$delete' || prop.name === 'delete') {
return j.unaryExpression(
'delete',
// @ts-ignore
j.memberExpression(node.arguments[0], node.arguments[1], true)
)
}
// unreachable branch
return node
})
}
export default wrap(transformAST)
export const parser = 'babylon'