1use is_macro::Is;
2use swc_atoms::Atom;
3use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
4
5use crate::{
6    expr::{Expr, SpreadElement},
7    ident::Ident,
8    typescript::TsTypeParamInstantiation,
9    IdentName, Str,
10};
11
12#[ast_node]
14#[derive(Eq, Hash, Is, EqIgnoreSpan)]
15#[allow(variant_size_differences)]
16#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
17#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
18pub enum JSXObject {
19    #[tag("JSXMemberExpression")]
20    JSXMemberExpr(Box<JSXMemberExpr>),
21    #[tag("Identifier")]
22    Ident(Ident),
23}
24
25#[ast_node("JSXMemberExpression")]
26#[derive(Eq, Hash, EqIgnoreSpan)]
27#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
28#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
29pub struct JSXMemberExpr {
30    pub span: Span,
31
32    #[cfg_attr(feature = "serde-impl", serde(rename = "object"))]
33    pub obj: JSXObject,
34
35    #[cfg_attr(feature = "serde-impl", serde(rename = "property"))]
36    pub prop: IdentName,
37}
38
39#[ast_node("JSXNamespacedName")]
41#[derive(Eq, Hash, EqIgnoreSpan)]
42#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
43#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
44pub struct JSXNamespacedName {
45    pub span: Span,
46    #[cfg_attr(feature = "serde-impl", serde(rename = "namespace"))]
47    pub ns: IdentName,
48    pub name: IdentName,
49}
50
51#[ast_node("JSXEmptyExpression")]
52#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
53#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
54#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
55pub struct JSXEmptyExpr {
56    pub span: Span,
57}
58
59#[ast_node("JSXExpressionContainer")]
60#[derive(Eq, Hash, EqIgnoreSpan)]
61#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
62#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
63pub struct JSXExprContainer {
64    pub span: Span,
65    #[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
66    pub expr: JSXExpr,
67}
68
69#[ast_node]
70#[derive(Eq, Hash, EqIgnoreSpan)]
71#[allow(variant_size_differences)]
72#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
73#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
74pub enum JSXExpr {
75    #[tag("JSXEmptyExpression")]
76    JSXEmptyExpr(JSXEmptyExpr),
77    #[tag("*")]
78    Expr(Box<Expr>),
79}
80
81#[ast_node("JSXSpreadChild")]
82#[derive(Eq, Hash, EqIgnoreSpan)]
83#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
84#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
85pub struct JSXSpreadChild {
86    pub span: Span,
87    #[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
88    pub expr: Box<Expr>,
89}
90
91#[ast_node]
92#[derive(Eq, Hash, EqIgnoreSpan)]
93#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
94#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
95pub enum JSXElementName {
96    #[tag("Identifier")]
97    Ident(Ident),
98    #[tag("JSXMemberExpression")]
99    JSXMemberExpr(JSXMemberExpr),
100    #[tag("JSXNamespacedName")]
101    JSXNamespacedName(JSXNamespacedName),
102}
103
104impl Take for JSXElementName {
105    fn dummy() -> Self {
106        JSXElementName::Ident(Take::dummy())
107    }
108}
109
110#[ast_node("JSXOpeningElement")]
111#[derive(Eq, Hash, EqIgnoreSpan)]
112#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
113#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
114pub struct JSXOpeningElement {
115    pub name: JSXElementName,
116
117    pub span: Span,
118
119    #[cfg_attr(feature = "serde-impl", serde(default, rename = "attributes"))]
120    pub attrs: Vec<JSXAttrOrSpread>,
121
122    #[cfg_attr(feature = "serde-impl", serde(rename = "selfClosing"))]
123    pub self_closing: bool,
124
125    #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeArguments"))]
128    #[cfg_attr(
129        feature = "encoding-impl",
130        encoding(with = "cbor4ii::core::types::Maybe")
131    )]
132    pub type_args: Option<Box<TsTypeParamInstantiation>>,
133}
134
135impl Take for JSXOpeningElement {
136    fn dummy() -> Self {
137        JSXOpeningElement {
138            name: Take::dummy(),
139            span: DUMMY_SP,
140            attrs: Take::dummy(),
141            self_closing: Default::default(),
142            type_args: Take::dummy(),
143        }
144    }
145}
146
147#[ast_node]
148#[derive(Eq, Hash, EqIgnoreSpan)]
149#[allow(variant_size_differences)]
150#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
151#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
152pub enum JSXAttrOrSpread {
153    #[tag("JSXAttribute")]
154    JSXAttr(JSXAttr),
155    #[tag("SpreadElement")]
156    SpreadElement(SpreadElement),
157}
158
159#[ast_node("JSXClosingElement")]
160#[derive(Eq, Hash, EqIgnoreSpan)]
161#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
162#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
163pub struct JSXClosingElement {
164    pub span: Span,
165    pub name: JSXElementName,
166}
167
168#[ast_node("JSXAttribute")]
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 JSXAttr {
173    pub span: Span,
174    pub name: JSXAttrName,
175    #[cfg_attr(
177        feature = "encoding-impl",
178        encoding(with = "cbor4ii::core::types::Maybe")
179    )]
180    pub value: Option<JSXAttrValue>,
181}
182
183#[ast_node]
184#[derive(Eq, Hash, EqIgnoreSpan)]
185#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
186#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
187pub enum JSXAttrName {
188    #[tag("Identifier")]
189    Ident(IdentName),
190    #[tag("JSXNamespacedName")]
191    JSXNamespacedName(JSXNamespacedName),
192}
193
194#[ast_node]
195#[derive(Eq, Hash, EqIgnoreSpan)]
196#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
197#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
198pub enum JSXAttrValue {
199    #[tag("StringLiteral")]
200    Str(Str),
201
202    #[tag("JSXExpressionContainer")]
203    JSXExprContainer(JSXExprContainer),
204
205    #[tag("JSXElement")]
206    JSXElement(Box<JSXElement>),
207
208    #[tag("JSXFragment")]
209    JSXFragment(JSXFragment),
210}
211
212#[ast_node("JSXText")]
213#[derive(Eq, Hash, EqIgnoreSpan)]
214#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
215pub struct JSXText {
216    pub span: Span,
217    pub value: Atom,
218    pub raw: Atom,
219}
220
221#[cfg(feature = "arbitrary")]
222#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
223impl<'a> arbitrary::Arbitrary<'a> for JSXText {
224    fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
225        let span = u.arbitrary()?;
226        let value = u.arbitrary::<String>()?.into();
227        let raw = u.arbitrary::<String>()?.into();
228
229        Ok(Self { span, value, raw })
230    }
231}
232
233#[ast_node("JSXElement")]
234#[derive(Eq, Hash, EqIgnoreSpan)]
235#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
236#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
237pub struct JSXElement {
238    pub span: Span,
239    pub opening: JSXOpeningElement,
240    pub children: Vec<JSXElementChild>,
241    #[cfg_attr(
242        feature = "encoding-impl",
243        encoding(with = "cbor4ii::core::types::Maybe")
244    )]
245    pub closing: Option<JSXClosingElement>,
246}
247
248impl Take for JSXElement {
249    fn dummy() -> Self {
250        JSXElement {
251            span: DUMMY_SP,
252            opening: Take::dummy(),
253            children: Take::dummy(),
254            closing: Take::dummy(),
255        }
256    }
257}
258
259#[ast_node]
260#[derive(Eq, Hash, EqIgnoreSpan)]
261#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
262#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
263pub enum JSXElementChild {
264    #[tag("JSXText")]
265    JSXText(JSXText),
266
267    #[tag("JSXExpressionContainer")]
268    JSXExprContainer(JSXExprContainer),
269
270    #[tag("JSXSpreadChild")]
271    JSXSpreadChild(JSXSpreadChild),
272
273    #[tag("JSXElement")]
274    JSXElement(Box<JSXElement>),
275
276    #[tag("JSXFragment")]
277    JSXFragment(JSXFragment),
278}
279
280#[ast_node("JSXFragment")]
281#[derive(Eq, Hash, EqIgnoreSpan)]
282#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
283#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
284pub struct JSXFragment {
285    pub span: Span,
286
287    pub opening: JSXOpeningFragment,
288
289    #[cfg_attr(feature = "serde-impl", serde(default))]
290    pub children: Vec<JSXElementChild>,
291
292    pub closing: JSXClosingFragment,
293}
294
295impl Take for JSXFragment {
296    fn dummy() -> Self {
297        JSXFragment {
298            span: DUMMY_SP,
299            opening: Take::dummy(),
300            children: Take::dummy(),
301            closing: Take::dummy(),
302        }
303    }
304}
305
306#[ast_node("JSXOpeningFragment")]
307#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
308#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
309#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
310pub struct JSXOpeningFragment {
311    pub span: Span,
312}
313
314impl Take for JSXOpeningFragment {
315    fn dummy() -> Self {
316        JSXOpeningFragment { span: DUMMY_SP }
317    }
318}
319
320#[ast_node("JSXClosingFragment")]
321#[derive(Eq, Hash, Copy, EqIgnoreSpan)]
322#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
323#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
324pub struct JSXClosingFragment {
325    pub span: Span,
326}
327
328impl Take for JSXClosingFragment {
329    fn dummy() -> Self {
330        JSXClosingFragment { span: DUMMY_SP }
331    }
332}