swc_ecma_compat_common/
macros.rs1#[macro_export]
3macro_rules! impl_visit_mut_fn {
4 () => {
5 fn visit_mut_function(&mut self, f: &mut Function) {
6 if f.body.is_none() {
7 return;
8 }
9
10 f.visit_mut_children_with(self);
11
12 let (params, body) = self.visit_mut_fn_like(&mut f.params, &mut f.body.take().unwrap());
13
14 f.params = params;
15 f.body = Some(body);
16 }
17
18 fn visit_mut_arrow_expr(&mut self, f: &mut ArrowExpr) {
19 use swc_common::Spanned;
20
21 f.visit_mut_children_with(self);
22
23 let was_expr = match *f.body {
24 BlockStmtOrExpr::Expr(..) => true,
25 _ => false,
26 };
27 let (params, mut body) = self.visit_mut_fn_like(
28 &mut f
29 .params
30 .take()
31 .into_iter()
32 .map(|pat| Param {
33 span: DUMMY_SP,
34 decorators: Default::default(),
35 pat,
36 })
37 .collect(),
38 &mut match &mut *f.body {
39 BlockStmtOrExpr::BlockStmt(block) => block.take(),
40 BlockStmtOrExpr::Expr(expr) => BlockStmt {
41 stmts: vec![Stmt::Return(ReturnStmt {
42 span: DUMMY_SP,
43 arg: Some(expr.take()),
44 })],
45 ..Default::default()
46 },
47 _ => panic!("unable to access unknown nodes"),
48 },
49 );
50
51 let body = if was_expr
52 && body.stmts.len() == 1
53 && match body.stmts[0] {
54 Stmt::Return(ReturnStmt { arg: Some(..), .. }) => true,
55 _ => false,
56 } {
57 match body.stmts.pop().unwrap() {
58 Stmt::Return(ReturnStmt { arg: Some(arg), .. }) => {
59 Box::new(BlockStmtOrExpr::Expr(arg))
60 }
61 _ => unreachable!(),
62 }
63 } else {
64 Box::new(BlockStmtOrExpr::BlockStmt(body))
65 };
66
67 f.params = params.into_iter().map(|param| param.pat).collect();
68 f.body = body;
69 }
70
71 fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) {
72 if f.body.is_none() {
73 return;
74 }
75
76 f.visit_mut_children_with(self);
77
78 let (mut params, body) = self.visit_mut_fn_like(
79 &mut vec![Param {
80 span: DUMMY_SP,
81 decorators: Vec::new(),
82 pat: *f.param.take(),
83 }],
84 &mut f.body.take().unwrap(),
85 );
86 debug_assert!(params.len() == 1);
87
88 f.param = Box::new(params.into_iter().next().unwrap().pat);
89 f.body = Some(body);
90 }
91
92 fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
93 if f.body.is_none() {
94 return;
95 }
96
97 f.visit_mut_children_with(self);
98
99 let (params, body) =
100 self.visit_mut_fn_like(&mut Vec::new(), &mut f.body.take().unwrap());
101 debug_assert_eq!(params, Vec::new());
102
103 f.body = Some(body);
104 }
105
106 fn visit_mut_catch_clause(&mut self, f: &mut CatchClause) {
107 f.visit_mut_children_with(self);
108
109 let (mut params, body) = match &mut f.param {
110 Some(pat) => self.visit_mut_fn_like(
111 &mut vec![Param {
112 span: DUMMY_SP,
113 decorators: Vec::new(),
114 pat: pat.take(),
115 }],
116 &mut f.body.take(),
117 ),
118 None => self.visit_mut_fn_like(&mut Vec::new(), &mut f.body.take()),
119 };
120 assert!(
121 params.len() == 0 || params.len() == 1,
122 "fold_fn_like should return 0 ~ 1 parameter while handling catch clause"
123 );
124
125 let param = if params.is_empty() {
126 None
127 } else {
128 Some(params.pop().unwrap())
129 };
130
131 f.param = param.map(|param| param.pat);
132 f.body = body;
133 }
134
135 fn visit_mut_constructor(&mut self, f: &mut Constructor) {
136 if f.body.is_none() {
137 return;
138 }
139
140 tracing::trace!("visit_mut_constructor(parmas.len() = {})", f.params.len());
141
142 f.visit_mut_children_with(self);
143
144 let mut params = f
145 .params
146 .take()
147 .into_iter()
148 .map(|pat| match pat {
149 ParamOrTsParamProp::Param(p) => p,
150 _ => unreachable!(
151 "TsParameterProperty should be removed by typescript::strip pass"
152 ),
153 })
154 .collect();
155
156 let (params, body) = self.visit_mut_fn_like(&mut params, &mut f.body.take().unwrap());
157
158 tracing::trace!(
159 "visit_mut_constructor(parmas.len() = {}, after)",
160 params.len()
161 );
162
163 f.params = params.into_iter().map(ParamOrTsParamProp::Param).collect();
164 f.body = Some(body);
165 }
166 };
167}