swc_ecma_ast/
pat.rs

1use is_macro::Is;
2use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
3
4use crate::{
5    expr::Expr,
6    ident::{BindingIdent, Ident},
7    prop::PropName,
8    typescript::TsTypeAnn,
9    Id, IdentName, Invalid,
10};
11
12#[ast_node(no_clone)]
13#[derive(Eq, Hash, Is, EqIgnoreSpan)]
14#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
15#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
16pub enum Pat {
17    #[tag("Identifier")]
18    Ident(BindingIdent),
19
20    #[tag("ArrayPattern")]
21    Array(ArrayPat),
22
23    #[tag("RestElement")]
24    Rest(RestPat),
25
26    #[tag("ObjectPattern")]
27    Object(ObjectPat),
28
29    #[tag("AssignmentPattern")]
30    Assign(AssignPat),
31
32    #[tag("Invalid")]
33    Invalid(Invalid),
34
35    /// Only for for-in / for-of loops. This is *syntactically* valid.
36    #[tag("*")]
37    Expr(Box<Expr>),
38}
39
40// Implement Clone without inline to avoid multiple copies of the
41// implementation.
42impl Clone for Pat {
43    fn clone(&self) -> Self {
44        use Pat::*;
45        match self {
46            Ident(p) => Ident(p.clone()),
47            Array(p) => Array(p.clone()),
48            Rest(p) => Rest(p.clone()),
49            Object(p) => Object(p.clone()),
50            Assign(p) => Assign(p.clone()),
51            Invalid(p) => Invalid(p.clone()),
52            Expr(p) => Expr(p.clone()),
53        }
54    }
55}
56
57impl Default for Pat {
58    fn default() -> Self {
59        Invalid { span: DUMMY_SP }.into()
60    }
61}
62impl Take for Pat {
63    fn dummy() -> Self {
64        Default::default()
65    }
66}
67
68bridge_pat_from!(BindingIdent, Ident);
69bridge_pat_from!(BindingIdent, IdentName);
70bridge_pat_from!(BindingIdent, Id);
71
72macro_rules! pat_to_other {
73    ($T:ty) => {
74        bridge_from!(crate::Param, crate::Pat, $T);
75        bridge_from!(Box<crate::Pat>, crate::Pat, $T);
76    };
77}
78
79pat_to_other!(BindingIdent);
80pat_to_other!(ArrayPat);
81pat_to_other!(ObjectPat);
82pat_to_other!(AssignPat);
83pat_to_other!(RestPat);
84pat_to_other!(Box<Expr>);
85
86#[ast_node("ArrayPattern")]
87#[derive(Eq, Hash, EqIgnoreSpan)]
88#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
89#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
90pub struct ArrayPat {
91    pub span: Span,
92
93    #[cfg_attr(feature = "serde-impl", serde(rename = "elements"))]
94    pub elems: Vec<Option<Pat>>,
95
96    /// Only in an ambient context
97    #[cfg_attr(feature = "serde-impl", serde(rename = "optional"))]
98    pub optional: bool,
99
100    #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
101    pub type_ann: Option<Box<TsTypeAnn>>,
102}
103
104#[ast_node("ObjectPattern")]
105#[derive(Eq, Hash, EqIgnoreSpan)]
106#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
107#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
108pub struct ObjectPat {
109    pub span: Span,
110
111    #[cfg_attr(feature = "serde-impl", serde(rename = "properties"))]
112    pub props: Vec<ObjectPatProp>,
113
114    /// Only in an ambient context
115    #[cfg_attr(feature = "serde-impl", serde(rename = "optional"))]
116    pub optional: bool,
117
118    #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
119    pub type_ann: Option<Box<TsTypeAnn>>,
120}
121
122#[ast_node("AssignmentPattern")]
123#[derive(Eq, Hash, EqIgnoreSpan)]
124#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
125#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
126pub struct AssignPat {
127    pub span: Span,
128
129    pub left: Box<Pat>,
130
131    pub right: Box<Expr>,
132}
133
134/// EsTree `RestElement`
135#[ast_node("RestElement")]
136#[derive(Eq, Hash, EqIgnoreSpan)]
137#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
138#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
139pub struct RestPat {
140    pub span: Span,
141
142    #[cfg_attr(feature = "serde-impl", serde(rename = "rest"))]
143    pub dot3_token: Span,
144
145    #[cfg_attr(feature = "serde-impl", serde(rename = "argument"))]
146    pub arg: Box<Pat>,
147
148    #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeAnnotation"))]
149    pub type_ann: Option<Box<TsTypeAnn>>,
150}
151
152#[ast_node]
153#[derive(Eq, Hash, Is, EqIgnoreSpan)]
154#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
155#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
156pub enum ObjectPatProp {
157    #[tag("KeyValuePatternProperty")]
158    KeyValue(KeyValuePatProp),
159
160    #[tag("AssignmentPatternProperty")]
161    Assign(AssignPatProp),
162
163    #[tag("RestElement")]
164    Rest(RestPat),
165}
166
167/// `{key: value}`
168#[ast_node("KeyValuePatternProperty")]
169#[derive(Eq, Hash, EqIgnoreSpan)]
170#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
171#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
172pub struct KeyValuePatProp {
173    #[span(lo)]
174    pub key: PropName,
175
176    #[span(hi)]
177    pub value: Box<Pat>,
178}
179/// `{key}` or `{key = value}`
180#[ast_node("AssignmentPatternProperty")]
181#[derive(Eq, Hash, EqIgnoreSpan)]
182#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
183#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
184pub struct AssignPatProp {
185    pub span: Span,
186    /// Note: This type is to help implementing visitor and the field `type_ann`
187    /// is always [None].
188    pub key: BindingIdent,
189
190    #[cfg_attr(feature = "serde-impl", serde(default))]
191    pub value: Option<Box<Expr>>,
192}