-
Notifications
You must be signed in to change notification settings - Fork 2
/
memo.rs
114 lines (96 loc) · 3.24 KB
/
memo.rs
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
use swc_common::DUMMY_SP;
use swc_core::{
atoms::Atom,
ecma::visit::{noop_visit_mut_type, VisitMut, VisitMutWith},
};
use swc_ecma_ast::{
AssignExpr, AssignOp, AssignTarget, Callee, Class, ClassDecl, ClassExpr, ClassMember, Expr,
MemberExpr, MemberProp, MethodKind, PrivateMethod, PrivateName, PrivateProp, ReturnStmt,
SimpleAssignTarget, ThisExpr,
};
#[derive(Default)]
struct TransformVisitor {
private_props: Vec<Atom>,
current_index: usize,
}
impl TransformVisitor {
fn current_method(&self) -> &Atom {
self.private_props.get(self.current_index).unwrap()
}
fn start_visit_mut_class(&mut self) {
self.private_props = Vec::new();
self.current_index = 0;
}
fn visit_mut_class(&mut self, node: &mut Box<Class>) {
for prop in self.private_props.iter() {
node.body.push(ClassMember::PrivateProp(PrivateProp {
key: PrivateName {
span: DUMMY_SP,
name: prop.as_str().into(),
},
..Default::default()
}));
}
}
}
fn is_memo_getter(node: &mut PrivateMethod) -> bool {
if node.kind != MethodKind::Getter {
return false;
}
node.function.decorators.iter().any(|x| {
if let Some(call_expr) = x.expr.as_call() {
if let Callee::Expr(b) = &call_expr.callee {
if let Some(ident) = b.as_ident() {
return ident.sym.as_str() == "memo";
}
}
}
false
})
}
impl VisitMut for TransformVisitor {
noop_visit_mut_type!();
fn visit_mut_class_decl(&mut self, node: &mut ClassDecl) {
self.start_visit_mut_class();
node.visit_mut_children_with(self);
self.visit_mut_class(&mut node.class);
}
fn visit_mut_class_expr(&mut self, node: &mut ClassExpr) {
self.start_visit_mut_class();
node.visit_mut_children_with(self);
self.visit_mut_class(&mut node.class);
}
fn visit_mut_private_method(&mut self, node: &mut PrivateMethod) {
if is_memo_getter(node) {
self.current_index = self.private_props.len();
self.private_props.push(node.key.name.clone());
node.visit_mut_children_with(self);
node.key = PrivateName {
span: DUMMY_SP,
name: format!("_{}", node.key.name).into(),
}
}
}
fn visit_mut_return_stmt(&mut self, node: &mut ReturnStmt) {
// why? 类表达式会直接走到这里来?
if self.private_props.is_empty() {
return;
}
node.arg = Some(Box::new(Expr::Assign(AssignExpr {
span: DUMMY_SP,
op: AssignOp::Assign,
left: AssignTarget::Simple(SimpleAssignTarget::Member(MemberExpr {
span: DUMMY_SP,
obj: ThisExpr { span: DUMMY_SP }.into(),
prop: MemberProp::PrivateName(PrivateName {
span: DUMMY_SP,
name: self.current_method().clone(),
}),
})),
right: node.arg.clone().unwrap_or(Expr::undefined(DUMMY_SP)),
})));
}
}
pub fn memo_transform() -> impl VisitMut {
TransformVisitor::default()
}