-
-
Notifications
You must be signed in to change notification settings - Fork 238
/
macro.ts
44 lines (41 loc) 路 1.34 KB
/
macro.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
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { addNamed } from '@babel/helper-module-imports'
import type { NodePath } from '@babel/traverse'
import * as t from '@babel/types'
import { MacroError, createMacro } from 'babel-plugin-macros'
const macro = ({ references }: any) => {
references.useProxy?.forEach((path: NodePath) => {
const hook = addNamed(path, 'useSnapshot', 'valtio')
const proxy = (path.parentPath?.get('arguments.0') as any)?.node
if (!t.isIdentifier(proxy)) throw new MacroError('no proxy object')
const snap = t.identifier(`valtio_macro_snap_${proxy.name}`)
path.parentPath?.parentPath?.replaceWith(
t.variableDeclaration('const', [
t.variableDeclarator(snap, t.callExpression(hook, [proxy])),
])
)
let inFunction = 0
path.parentPath?.getFunctionParent()?.traverse({
Identifier(p) {
if (
inFunction === 0 && // in render
p.node !== proxy &&
p.node.name === proxy.name
) {
p.node.name = snap.name
}
},
Function: {
enter() {
++inFunction
},
exit() {
--inFunction
},
},
})
})
}
export declare function useProxy<T extends object>(proxyObject: T): void
export default createMacro(macro, { configName: 'valtio' })