swc_ecma_compat_common/
macros.rs

1/// Not a public API
2#[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}