swc_estree_ast/
object.rs

1use serde::{ser::SerializeMap, Deserialize, Serialize};
2use swc_common::ast_serde;
3
4use crate::{
5    common::{
6        BaseNode, Decorator, Identifier, Param, PatternLike, TypeAnnotOrNoop, TypeParamDeclOrNoop,
7    },
8    expr::Expression,
9    flavor::Flavor,
10    flow::{
11        ObjectTypeCallProperty, ObjectTypeIndexer, ObjectTypeInternalSlot, ObjectTypeProperty,
12        ObjectTypeSpreadProperty,
13    },
14    lit::{NumericLiteral, StringLiteral},
15    stmt::BlockStatement,
16};
17
18#[derive(Debug, Clone, PartialEq)]
19#[ast_serde]
20pub enum UserWhitespacable {
21    #[tag("ObjectMethod")]
22    ObjectMethod(ObjectMethod),
23    #[tag("ObjectProperty")]
24    ObjectProperty(ObjectProperty),
25    #[tag("ObjectTypeInternalSlot")]
26    ObjectTypeInternalSlot(ObjectTypeInternalSlot),
27    #[tag("ObjectTypeCallProperty")]
28    ObjectTypeCallProperty(ObjectTypeCallProperty),
29    #[tag("ObjectTypeIndexer")]
30    ObjectTypeIndexer(ObjectTypeIndexer),
31    #[tag("ObjectTypeProperty")]
32    ObjectTypeProperty(ObjectTypeProperty),
33    #[tag("ObjectTypeSpreadProperty")]
34    ObjectTypeSpreadProperty(ObjectTypeSpreadProperty),
35}
36
37#[derive(Debug, Clone, PartialEq)]
38#[ast_serde]
39pub enum ObjectMember {
40    #[tag("ObjectMember")]
41    Method(ObjectMethod),
42    #[tag("ObjectProperty")]
43    Prop(ObjectProperty),
44}
45
46#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
47#[serde(rename_all = "lowercase")]
48pub enum ObjectMethodKind {
49    Method,
50    Get,
51    Set,
52}
53
54#[derive(Debug, Clone, PartialEq)]
55#[ast_serde]
56pub enum ObjectKey {
57    #[tag("Identifier")]
58    Id(Identifier),
59    #[tag("StringLiteral")]
60    String(StringLiteral),
61    #[tag("NumericLiteral")]
62    Numeric(NumericLiteral),
63    #[tag("*")]
64    Expr(Box<Expression>),
65}
66
67#[derive(Debug, Clone, Deserialize, PartialEq)]
68#[serde(rename_all = "camelCase")]
69#[serde(tag = "type")]
70pub struct ObjectMethod {
71    #[serde(flatten)]
72    pub base: BaseNode,
73    pub kind: ObjectMethodKind,
74    pub key: ObjectKey,
75    #[serde(default)]
76    pub params: Vec<Param>,
77    pub body: BlockStatement,
78    #[serde(default)]
79    pub computed: bool,
80    #[serde(default)]
81    pub generator: Option<bool>,
82    #[serde(default, rename = "async")]
83    pub is_async: Option<bool>,
84    #[serde(default)]
85    pub decorator: Option<Vec<Decorator>>,
86    #[serde(default)]
87    pub return_type: Option<Box<TypeAnnotOrNoop>>,
88    #[serde(default)]
89    pub type_parameters: Option<TypeParamDeclOrNoop>,
90}
91
92impl Serialize for ObjectMethod {
93    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
94    where
95        S: serde::Serializer,
96    {
97        match Flavor::current() {
98            Flavor::Babel => {
99                let actual = BabelObjectMethod {
100                    type_: "ObjectMethod",
101                    base: &self.base,
102                    key: &self.key,
103                    kind: self.kind,
104                    params: &self.params,
105                    body: &self.body,
106                    computed: self.computed,
107                    generator: self.generator,
108                    is_async: self.is_async,
109                    decorator: self.decorator.as_deref(),
110                    return_type: self.return_type.as_deref(),
111                    type_parameters: self.type_parameters.as_ref(),
112                };
113                actual.serialize(serializer)
114            }
115            Flavor::Acorn { .. } => {
116                let mut s = serializer.serialize_map(None)?;
117
118                {
119                    // TODO(kdy1): This is bad.
120                    self.base
121                        .serialize(crate::flat_map_serializer::FlatMapSerializer(&mut s))?;
122                }
123
124                s.serialize_entry("type", "Property")?;
125                s.serialize_entry("kind", &self.kind)?;
126                s.serialize_entry("method", &false)?;
127                s.serialize_entry("shorthand", &false)?;
128                s.serialize_entry("key", &self.key)?;
129                s.serialize_entry("computed", &self.computed)?;
130
131                s.serialize_entry(
132                    "value",
133                    &AcornObjectMethodValue {
134                        type_: "FunctionExpression",
135                        base: &self.base,
136                        body: &self.body,
137                        params: &self.params,
138                        generator: self.generator.unwrap_or(false),
139                        is_async: self.is_async.unwrap_or(false),
140                    },
141                )?;
142
143                s.end()
144            }
145        }
146    }
147}
148
149#[derive(Serialize)]
150struct AcornObjectMethodValue<'a> {
151    /// `FunctionExpression`
152    #[serde(rename = "type")]
153    type_: &'static str,
154    #[serde(flatten)]
155    base: &'a BaseNode,
156
157    body: &'a BlockStatement,
158
159    params: &'a [Param],
160
161    generator: bool,
162    #[serde(rename = "async")]
163    is_async: bool,
164}
165
166#[derive(Serialize)]
167#[serde(rename_all = "camelCase")]
168struct BabelObjectMethod<'a> {
169    #[serde(rename = "type")]
170    type_: &'static str,
171    #[serde(flatten)]
172    pub base: &'a BaseNode,
173    pub kind: ObjectMethodKind,
174    pub key: &'a ObjectKey,
175    #[serde(default)]
176    pub params: &'a [Param],
177    pub body: &'a BlockStatement,
178    #[serde(default)]
179    pub computed: bool,
180    #[serde(default)]
181    pub generator: Option<bool>,
182    #[serde(default, rename = "async")]
183    pub is_async: Option<bool>,
184    #[serde(default)]
185    pub decorator: Option<&'a [Decorator]>,
186    #[serde(default)]
187    pub return_type: Option<&'a TypeAnnotOrNoop>,
188    #[serde(default)]
189    pub type_parameters: Option<&'a TypeParamDeclOrNoop>,
190}
191
192#[derive(Debug, Clone, PartialEq)]
193#[ast_serde]
194pub enum ObjectPropVal {
195    #[tag("Identifier")]
196    #[tag("RestElement")]
197    #[tag("AssignmentPattern")]
198    #[tag("ArrayPattern")]
199    #[tag("ObjectPattern")]
200    Pattern(PatternLike),
201    #[tag("*")]
202    Expr(Box<Expression>),
203}
204
205#[derive(Debug, Clone, Deserialize, PartialEq)]
206pub struct ObjectProperty {
207    #[serde(flatten)]
208    pub base: BaseNode,
209    pub key: ObjectKey,
210    pub value: ObjectPropVal,
211    #[serde(default)]
212    pub computed: bool,
213    #[serde(default)]
214    pub shorthand: bool,
215    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
216    pub decorators: Option<Vec<Decorator>>,
217}
218
219#[derive(Serialize)]
220struct BabelObjectProperty<'a> {
221    #[serde(rename = "type")]
222    type_: &'a str,
223    #[serde(flatten)]
224    base: &'a BaseNode,
225    key: &'a ObjectKey,
226    value: &'a ObjectPropVal,
227    method: bool,
228    computed: bool,
229    shorthand: bool,
230    #[serde(skip_serializing_if = "crate::flavor::Flavor::skip_none")]
231    decorators: Option<&'a [Decorator]>,
232}
233
234impl Serialize for ObjectProperty {
235    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
236    where
237        S: serde::Serializer,
238    {
239        match Flavor::current() {
240            Flavor::Babel => {
241                let actual = BabelObjectProperty {
242                    type_: "ObjectProperty",
243                    base: &self.base,
244                    key: &self.key,
245                    value: &self.value,
246                    method: false,
247                    computed: self.computed,
248                    shorthand: self.shorthand,
249                    decorators: self.decorators.as_deref(),
250                };
251                actual.serialize(serializer)
252            }
253            Flavor::Acorn { .. } => {
254                let mut s = serializer.serialize_map(None)?;
255
256                {
257                    // TODO(kdy1): This is bad.
258                    self.base
259                        .serialize(crate::flat_map_serializer::FlatMapSerializer(&mut s))?;
260                }
261
262                s.serialize_entry("type", "Property")?;
263                s.serialize_entry("kind", "init")?;
264                s.serialize_entry("method", &false)?;
265                s.serialize_entry("shorthand", &self.shorthand)?;
266                s.serialize_entry("key", &self.key)?;
267                s.serialize_entry("value", &self.value)?;
268                s.serialize_entry("computed", &self.computed)?;
269                if let Some(decorators) = &self.decorators {
270                    if !decorators.is_empty() {
271                        s.serialize_entry("decorators", decorators)?;
272                    }
273                }
274
275                s.end()
276            }
277        }
278    }
279}