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 },
48 );
49
50 let body = if was_expr
51 && body.stmts.len() == 1
52 && match body.stmts[0] {
53 Stmt::Return(ReturnStmt { arg: Some(..), .. }) => true,
54 _ => false,
55 } {
56 match body.stmts.pop().unwrap() {
57 Stmt::Return(ReturnStmt { arg: Some(arg), .. }) => {
58 Box::new(BlockStmtOrExpr::Expr(arg))
59 }
60 _ => unreachable!(),
61 }
62 } else {
63 Box::new(BlockStmtOrExpr::BlockStmt(body))
64 };
65
66 f.params = params.into_iter().map(|param| param.pat).collect();
67 f.body = body;
68 }
69
70 fn visit_mut_setter_prop(&mut self, f: &mut SetterProp) {
71 if f.body.is_none() {
72 return;
73 }
74
75 f.visit_mut_children_with(self);
76
77 let (mut params, body) = self.visit_mut_fn_like(
78 &mut vec![Param {
79 span: DUMMY_SP,
80 decorators: Vec::new(),
81 pat: *f.param.take(),
82 }],
83 &mut f.body.take().unwrap(),
84 );
85 debug_assert!(params.len() == 1);
86
87 f.param = Box::new(params.into_iter().next().unwrap().pat);
88 f.body = Some(body);
89 }
90
91 fn visit_mut_getter_prop(&mut self, f: &mut GetterProp) {
92 if f.body.is_none() {
93 return;
94 }
95
96 f.visit_mut_children_with(self);
97
98 let (params, body) =
99 self.visit_mut_fn_like(&mut Vec::new(), &mut f.body.take().unwrap());
100 debug_assert_eq!(params, Vec::new());
101
102 f.body = Some(body);
103 }
104
105 fn visit_mut_catch_clause(&mut self, f: &mut CatchClause) {
106 f.visit_mut_children_with(self);
107
108 let (mut params, body) = match &mut f.param {
109 Some(pat) => self.visit_mut_fn_like(
110 &mut vec![Param {
111 span: DUMMY_SP,
112 decorators: Vec::new(),
113 pat: pat.take(),
114 }],
115 &mut f.body.take(),
116 ),
117 None => self.visit_mut_fn_like(&mut Vec::new(), &mut f.body.take()),
118 };
119 assert!(
120 params.len() == 0 || params.len() == 1,
121 "fold_fn_like should return 0 ~ 1 parameter while handling catch clause"
122 );
123
124 let param = if params.is_empty() {
125 None
126 } else {
127 Some(params.pop().unwrap())
128 };
129
130 f.param = param.map(|param| param.pat);
131 f.body = body;
132 }
133
134 fn visit_mut_constructor(&mut self, f: &mut Constructor) {
135 if f.body.is_none() {
136 return;
137 }
138
139 tracing::trace!("visit_mut_constructor(parmas.len() = {})", f.params.len());
140
141 f.visit_mut_children_with(self);
142
143 let mut params = f
144 .params
145 .take()
146 .into_iter()
147 .map(|pat| match pat {
148 ParamOrTsParamProp::Param(p) => p,
149 _ => unreachable!(
150 "TsParameterProperty should be removed by typescript::strip pass"
151 ),
152 })
153 .collect();
154
155 let (params, body) = self.visit_mut_fn_like(&mut params, &mut f.body.take().unwrap());
156
157 tracing::trace!(
158 "visit_mut_constructor(parmas.len() = {}, after)",
159 params.len()
160 );
161
162 f.params = params.into_iter().map(ParamOrTsParamProp::Param).collect();
163 f.body = Some(body);
164 }
165 };
166}