1use swc_ecma_lexer::common::parser::pat::parse_binding_pat_or_ident;
4
5use super::*;
6use crate::parser::Parser;
7
8impl<I: Tokens> Parser<I> {
9 pub fn parse_pat(&mut self) -> PResult<Pat> {
10 parse_binding_pat_or_ident(self, false)
11 }
12}
13
14#[cfg(test)]
15mod tests {
16 use swc_atoms::atom;
17 use swc_common::DUMMY_SP as span;
18 use swc_ecma_lexer::common::parser::pat::parse_array_binding_pat;
19 use swc_ecma_visit::assert_eq_ignore_span;
20
21 use super::*;
22
23 fn array_pat(s: &'static str) -> Pat {
24 test_parser(s, Syntax::default(), |p| parse_array_binding_pat(p))
25 }
26
27 fn object_pat(s: &'static str) -> Pat {
28 test_parser(s, Syntax::default(), |p| {
29 parse_binding_pat_or_ident(p, false)
30 })
31 }
32
33 fn ident(s: &str) -> Ident {
34 Ident::new_no_ctxt(s.into(), span)
35 }
36
37 fn ident_name(s: &str) -> IdentName {
38 IdentName::new(s.into(), span)
39 }
40
41 fn rest() -> Option<Pat> {
42 Some(
43 RestPat {
44 span,
45 dot3_token: span,
46 type_ann: None,
47 arg: ident("tail").into(),
48 }
49 .into(),
50 )
51 }
52
53 #[test]
54 fn array_pat_simple() {
55 assert_eq_ignore_span!(
56 array_pat("[a, [b], [c]]"),
57 Pat::Array(ArrayPat {
58 span,
59 optional: false,
60 elems: vec![
61 Some(Pat::Ident(ident("a").into())),
62 Some(Pat::Array(ArrayPat {
63 span,
64 optional: false,
65 elems: vec![Some(Pat::Ident(ident("b").into()))],
66 type_ann: None
67 })),
68 Some(Pat::Array(ArrayPat {
69 span,
70 optional: false,
71 elems: vec![Some(Pat::Ident(ident("c").into()))],
72 type_ann: None
73 }))
74 ],
75 type_ann: None
76 })
77 );
78 }
79
80 #[test]
81 fn array_pat_empty_start() {
82 assert_eq_ignore_span!(
83 array_pat("[, a, [b], [c]]"),
84 Pat::Array(ArrayPat {
85 span,
86 optional: false,
87 elems: vec![
88 None,
89 Some(Pat::Ident(ident("a").into())),
90 Some(Pat::Array(ArrayPat {
91 span,
92 optional: false,
93 elems: vec![Some(Pat::Ident(ident("b").into()))],
94 type_ann: None
95 })),
96 Some(Pat::Array(ArrayPat {
97 span,
98 optional: false,
99 elems: vec![Some(Pat::Ident(ident("c").into()))],
100 type_ann: None
101 }))
102 ],
103 type_ann: None
104 })
105 );
106 }
107
108 #[test]
109 fn array_pat_empty() {
110 assert_eq_ignore_span!(
111 array_pat("[a, , [b], [c]]"),
112 Pat::Array(ArrayPat {
113 span,
114 optional: false,
115 elems: vec![
116 Some(Pat::Ident(ident("a").into())),
117 None,
118 Some(Pat::Array(ArrayPat {
119 span,
120 optional: false,
121 elems: vec![Some(Pat::Ident(ident("b").into()))],
122 type_ann: None
123 })),
124 Some(Pat::Array(ArrayPat {
125 span,
126 optional: false,
127 elems: vec![Some(Pat::Ident(ident("c").into()))],
128 type_ann: None
129 }))
130 ],
131 type_ann: None
132 })
133 );
134 }
135
136 #[test]
137 fn array_pat_empty_end() {
138 assert_eq_ignore_span!(
139 array_pat("[a, ,]"),
140 Pat::Array(ArrayPat {
141 span,
142 optional: false,
143 elems: vec![Some(Pat::Ident(ident("a").into())), None,],
144 type_ann: None
145 })
146 );
147 }
148
149 #[test]
150 fn array_binding_pattern_tail() {
151 assert_eq_ignore_span!(
152 array_pat("[...tail]"),
153 Pat::Array(ArrayPat {
154 span,
155 optional: false,
156 elems: vec![rest()],
157 type_ann: None
158 })
159 );
160 }
161
162 #[test]
163 fn array_binding_pattern_assign() {
164 assert_eq_ignore_span!(
165 array_pat("[,a=1,]"),
166 Pat::Array(ArrayPat {
167 span,
168 optional: false,
169 elems: vec![
170 None,
171 Some(Pat::Assign(AssignPat {
172 span,
173 left: Box::new(Pat::Ident(ident("a").into())),
174 right: Box::new(Expr::Lit(Lit::Num(Number {
175 span,
176 value: 1.0,
177 raw: Some(atom!("1"))
178 })))
179 }))
180 ],
181 type_ann: None
182 })
183 );
184 }
185
186 #[test]
187 fn array_binding_pattern_tail_with_elems() {
188 assert_eq_ignore_span!(
189 array_pat("[,,,...tail]"),
190 Pat::Array(ArrayPat {
191 span,
192 optional: false,
193 elems: vec![None, None, None, rest()],
194 type_ann: None
195 })
196 );
197 }
198
199 #[test]
200 fn array_binding_pattern_tail_inside_tail() {
201 assert_eq_ignore_span!(
202 array_pat("[,,,...[...tail]]"),
203 Pat::Array(ArrayPat {
204 span,
205 optional: false,
206 elems: vec![
207 None,
208 None,
209 None,
210 Some(Pat::Rest(RestPat {
211 span,
212 dot3_token: span,
213 type_ann: None,
214 arg: Box::new(Pat::Array(ArrayPat {
215 span,
216 optional: false,
217 elems: vec![rest()],
218 type_ann: None
219 }))
220 }))
221 ],
222 type_ann: None
223 })
224 );
225 }
226
227 #[test]
228 fn object_binding_pattern_tail() {
229 assert_eq_ignore_span!(
230 object_pat("{...obj}"),
231 Pat::Object(ObjectPat {
232 span,
233 type_ann: None,
234 optional: false,
235 props: vec![ObjectPatProp::Rest(RestPat {
236 span,
237 dot3_token: span,
238 type_ann: None,
239 arg: Box::new(Pat::Ident(ident("obj").into()))
240 })]
241 })
242 );
243 }
244
245 #[test]
246 fn object_binding_pattern_with_prop() {
247 assert_eq_ignore_span!(
248 object_pat("{prop = 10 }"),
249 Pat::Object(ObjectPat {
250 span,
251 type_ann: None,
252 optional: false,
253 props: vec![ObjectPatProp::Assign(AssignPatProp {
254 span,
255 key: ident("prop").into(),
256 value: Some(Box::new(Expr::Lit(Lit::Num(Number {
257 span,
258 value: 10.0,
259 raw: Some(atom!("10"))
260 }))))
261 })]
262 })
263 );
264 }
265
266 #[test]
267 fn object_binding_pattern_with_prop_and_label() {
268 fn prop(key: PropName, assign_name: &str, expr: Expr) -> PropOrSpread {
269 PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
270 key,
271 value: AssignExpr {
272 span,
273 op: AssignOp::Assign,
274 left: ident(assign_name).into(),
275 right: Box::new(expr),
276 }
277 .into(),
278 })))
279 }
280
281 assert_eq_ignore_span!(
282 object_pat(
283 "{obj = {$: num = 10, '': sym = '', \" \": quote = \" \", _: under = [...tail],}}"
284 ),
285 Pat::Object(ObjectPat {
286 span,
287 type_ann: None,
288 optional: false,
289 props: vec![ObjectPatProp::Assign(AssignPatProp {
290 span,
291 key: ident("obj").into(),
292 value: Some(Box::new(Expr::Object(ObjectLit {
293 span,
294 props: vec![
295 prop(
296 PropName::Ident(ident_name("$")),
297 "num",
298 Expr::Lit(Lit::Num(Number {
299 span,
300 value: 10.0,
301 raw: Some(atom!("10"))
302 }))
303 ),
304 prop(
305 PropName::Str(Str {
306 span,
307 value: atom!(""),
308 raw: Some(atom!("''")),
309 }),
310 "sym",
311 Expr::Lit(Lit::Str(Str {
312 span,
313 value: atom!(""),
314 raw: Some(atom!("''")),
315 }))
316 ),
317 prop(
318 PropName::Str(Str {
319 span,
320 value: atom!(" "),
321 raw: Some(atom!("\" \"")),
322 }),
323 "quote",
324 Expr::Lit(Lit::Str(Str {
325 span,
326 value: atom!(" "),
327 raw: Some(atom!("\" \"")),
328 }))
329 ),
330 prop(
331 PropName::Ident(ident_name("_")),
332 "under",
333 Expr::Array(ArrayLit {
334 span,
335 elems: vec![Some(ExprOrSpread {
336 spread: Some(span),
337 expr: Box::new(Expr::Ident(ident("tail")))
338 })]
339 })
340 ),
341 ]
342 })))
343 })]
344 })
345 );
346 }
347}