This repository has been archived by the owner on Jan 9, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
codemod.js
101 lines (86 loc) · 2.84 KB
/
codemod.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
export default function transformer (file, api) {
const j = api.jscodeshift
const yieldToAwait = p => {
const node = p.node
let arg = node.argument
// use Promise.all for array literals, e.g.
// await Promise.all([promise1, promise2, ...])
if (arg.type === 'ArrayExpression') {
arg = j.callExpression(
j.memberExpression(
j.identifier('Promise'),
j.identifier('all')
),
[arg]
)
}
const n = j.awaitExpression(arg)
return n
}
const replaceCoWrap = p => {
const right = p.node.right
const args = right.arguments
if (args.length !== 1) throw new Error('Expected one argument')
const body = args[0]
return j.assignmentExpression(p.node.operator, p.node.left, body)
}
const removeCo = p => {
const node = p.node
const args = node.arguments
if (args.length !== 1) throw new Error('Expected one argument')
return args[0]
}
const generatorToAsync = p => {
const node = p.node
const {id, params, body, expression} = node
const n = j.functionExpression(id, params, body, false, expression)
n.async = true
return n
}
const generatorToAsyncDec = p => {
const node = p.node
const {id, params, body, expression} = node
const n = j.functionDeclaration(id, params, body, false, expression)
n.async = true
return n
}
// log filter
// const log = id => p => { console.log(id, p.node); return true }
const root = j(file.source)
// yield -> await
root.find(j.YieldExpression)
.replaceWith(yieldToAwait)
// a = co.wrap(function * () {}) > a = function * () {}
root.find(j.AssignmentExpression, { right: { callee: { object: { name: 'co' }, property: { name: 'wrap' } } } })
.replaceWith(replaceCoWrap)
// co.wrap(...) -> ...
root.find(j.CallExpression, { callee: { object: { name: 'co' }, property: { name: 'wrap' } } })
.replaceWith(removeCo)
// co(...) -> (async ...)()
root.find(j.CallExpression, { callee: { name: 'co' } })
.replaceWith(removeCo)
.replaceWith(p => j.callExpression(p.node, []))
// a = function * () -> a = async function ()
root.find(j.FunctionDeclaration, { generator: true })
.replaceWith(generatorToAsyncDec)
// function * () -> async function ()
root.find(j.FunctionExpression, { generator: true })
.replaceWith(generatorToAsync)
// remove require co
root
.find(j.VariableDeclaration)
.filter(p => {
const { declarations } = p.node
if (declarations.length !== 1) return false
const declaration = declarations[0]
if (declaration.id.name !== 'co') return false
if (declaration.init.callee.name !== 'require') return false
return true
})
.replaceWith(p => {
return null
})
const replaced = root.toSource()
return replaced
.replace(/async function\(/g, 'async function (')
}