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                    _ => 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}