swc_estree_ast/
class.rs

1use serde::{ser::SerializeMap, Deserialize, Serialize};
2use serde_json::Value;
3use swc_common::ast_serde;
4
5use crate::{
6    common::{
7        Access, BaseNode, Decorator, Identifier, Param, PrivateName, SuperTypeParams,
8        TypeAnnotOrNoop, TypeParamDeclOrNoop,
9    },
10    expr::{ClassExpression, Expression},
11    flavor::Flavor,
12    flow::{ClassImplements, InterfaceExtends},
13    object::ObjectKey,
14    stmt::{BlockStatement, Statement},
15    typescript::{TSDeclareMethod, TSExpressionWithTypeArguments, TSIndexSignature},
16};
17
18#[derive(Debug, Clone, PartialEq)]
19#[ast_serde]
20pub enum Class {
21    #[tag("ClassExpression")]
22    Expr(ClassExpression),
23    #[tag("ClassDeclaration")]
24    Decl(ClassDeclaration),
25}
26
27#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
28#[serde(rename_all = "lowercase")]
29pub enum ClassMethodKind {
30    Get,
31    Set,
32    Method,
33    Constructor,
34}
35
36#[derive(Debug, Clone, PartialEq, Deserialize)]
37pub struct ClassMethod {
38    #[serde(flatten)]
39    pub base: BaseNode,
40    #[serde(default)]
41    pub kind: Option<ClassMethodKind>,
42    pub key: ObjectKey,
43    #[serde(default)]
44    pub params: Vec<Param>,
45    pub body: BlockStatement,
46    #[serde(default)]
47    pub computed: Option<bool>,
48    #[serde(
49        default,
50        rename = "static",
51        skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
52    )]
53    pub is_static: Option<bool>,
54    #[serde(
55        default,
56        skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
57    )]
58    pub generator: Option<bool>,
59    #[serde(
60        default,
61        rename = "async",
62        serialize_with = "crate::ser::serialize_as_bool"
63    )]
64    pub is_async: Option<bool>,
65    #[serde(
66        default,
67        rename = "abstract",
68        skip_serializing_if = "crate::flavor::Flavor::skip_none"
69    )]
70    pub is_abstract: Option<bool>,
71    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
72    pub access: Option<Access>,
73    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
74    pub accessibility: Option<Access>,
75    #[serde(default)]
76    pub decorators: Option<Vec<Decorator>>,
77    #[serde(default)]
78    pub optional: Option<bool>,
79    #[serde(default)]
80    pub return_type: Option<Box<TypeAnnotOrNoop>>,
81    #[serde(default)]
82    pub type_parameters: Option<TypeParamDeclOrNoop>,
83}
84
85#[derive(Serialize)]
86struct BabelClassMethod<'a> {
87    #[serde(rename = "type")]
88    type_: &'a str,
89    #[serde(flatten)]
90    pub base: &'a BaseNode,
91    #[serde(default)]
92    pub kind: Option<ClassMethodKind>,
93    pub key: &'a ObjectKey,
94    #[serde(default)]
95    pub params: &'a [Param],
96    pub body: &'a BlockStatement,
97    #[serde(default)]
98    pub computed: Option<bool>,
99    #[serde(
100        default,
101        rename = "static",
102        skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
103    )]
104    pub is_static: Option<bool>,
105    #[serde(
106        default,
107        skip_serializing_if = "crate::flavor::Flavor::skip_none_and_false"
108    )]
109    pub generator: Option<bool>,
110    #[serde(
111        default,
112        rename = "async",
113        serialize_with = "crate::ser::serialize_as_bool"
114    )]
115    pub is_async: Option<bool>,
116    #[serde(
117        default,
118        rename = "abstract",
119        skip_serializing_if = "crate::flavor::Flavor::skip_none"
120    )]
121    pub is_abstract: Option<bool>,
122    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
123    pub access: Option<&'a Access>,
124    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
125    pub accessibility: Option<&'a Access>,
126    #[serde(default)]
127    pub decorators: Option<&'a [Decorator]>,
128    #[serde(default)]
129    pub optional: Option<bool>,
130    #[serde(default)]
131    pub return_type: Option<&'a TypeAnnotOrNoop>,
132    #[serde(default)]
133    pub type_parameters: Option<&'a TypeParamDeclOrNoop>,
134}
135
136#[derive(Serialize)]
137struct AcornClassMethodValue<'a> {
138    /// `FunctionExpression`
139    #[serde(rename = "type")]
140    type_: &'a str,
141    #[serde(flatten)]
142    base: &'a BaseNode,
143
144    body: &'a BlockStatement,
145
146    params: &'a [Param],
147
148    generator: bool,
149    #[serde(rename = "async")]
150    is_async: bool,
151}
152
153impl Serialize for ClassMethod {
154    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155    where
156        S: serde::Serializer,
157    {
158        match Flavor::current() {
159            Flavor::Babel => {
160                let actual = BabelClassMethod {
161                    type_: "ClassMethod",
162                    base: &self.base,
163                    kind: self.kind,
164                    key: &self.key,
165                    params: &self.params,
166                    body: &self.body,
167                    computed: self.computed,
168                    is_static: self.is_static,
169                    generator: self.generator,
170                    is_async: self.is_async,
171                    is_abstract: self.is_abstract,
172                    access: self.access.as_ref(),
173                    accessibility: self.accessibility.as_ref(),
174                    decorators: self.decorators.as_deref(),
175                    optional: self.optional,
176                    return_type: self.return_type.as_deref(),
177                    type_parameters: self.type_parameters.as_ref(),
178                };
179                actual.serialize(serializer)
180            }
181            Flavor::Acorn { .. } => {
182                let mut s = serializer.serialize_map(None)?;
183
184                {
185                    // TODO(kdy1): This is bad.
186                    self.base
187                        .serialize(crate::flat_map_serializer::FlatMapSerializer(&mut s))?;
188                }
189
190                s.serialize_entry("type", "MethodDefinition")?;
191                s.serialize_entry("computed", &self.computed.unwrap_or(false))?;
192                s.serialize_entry("key", &self.key)?;
193                s.serialize_entry("kind", &self.kind)?;
194                s.serialize_entry("static", &self.is_static.unwrap_or(false))?;
195                s.serialize_entry(
196                    "value",
197                    &AcornClassMethodValue {
198                        type_: "FunctionExpression",
199                        base: &self.body.base,
200                        body: &self.body,
201                        params: &self.params,
202                        generator: self.generator.unwrap_or(false),
203                        is_async: self.is_async.unwrap_or(false),
204                    },
205                )?;
206
207                s.end()
208            }
209        }
210    }
211}
212
213#[derive(Debug, Clone, PartialEq)]
214#[ast_serde("ClassPrivateProperty")]
215pub struct ClassPrivateProperty {
216    #[serde(flatten)]
217    pub base: BaseNode,
218    pub key: PrivateName,
219    #[serde(default)]
220    pub value: Option<Box<Expression>>,
221    #[serde(default)]
222    pub decorators: Option<Vec<Decorator>>,
223    #[serde(default, rename = "static")]
224    pub static_any: Value,
225    #[serde(default)]
226    pub type_annotation: Option<Box<TypeAnnotOrNoop>>,
227}
228
229#[derive(Debug, Clone, PartialEq)]
230#[ast_serde("ClassPrivateMethod")]
231pub struct ClassPrivateMethod {
232    #[serde(flatten)]
233    pub base: BaseNode,
234    #[serde(default)]
235    pub kind: Option<ClassMethodKind>,
236    pub key: PrivateName,
237    #[serde(default)]
238    pub params: Vec<Param>,
239    pub body: BlockStatement,
240    #[serde(default, rename = "static")]
241    pub is_static: Option<bool>,
242    #[serde(default, rename = "abstract")]
243    pub is_abstract: Option<bool>,
244    #[serde(default)]
245    pub access: Option<Access>,
246    #[serde(default)]
247    pub accessibility: Option<Access>,
248    #[serde(default, rename = "async")]
249    pub is_async: Option<bool>,
250    #[serde(default)]
251    pub computed: Option<bool>,
252    #[serde(default)]
253    pub decorators: Option<Vec<Decorator>>,
254    #[serde(default)]
255    pub generator: Option<bool>,
256    #[serde(default)]
257    pub optional: Option<bool>,
258    #[serde(default)]
259    pub return_type: Option<Box<TypeAnnotOrNoop>>,
260    #[serde(default)]
261    pub type_parameters: Option<TypeParamDeclOrNoop>,
262}
263
264#[derive(Debug, Clone, PartialEq, Deserialize)]
265pub struct ClassProperty {
266    #[serde(flatten)]
267    pub base: BaseNode,
268    pub key: ObjectKey,
269    #[serde(default)]
270    pub value: Option<Box<Expression>>,
271    #[serde(default)]
272    pub type_annotation: Option<Box<TypeAnnotOrNoop>>,
273    #[serde(default)]
274    pub decorators: Option<Vec<Decorator>>,
275    #[serde(default)]
276    pub computed: Option<bool>,
277    #[serde(default, rename = "static")]
278    pub is_static: Option<bool>,
279    #[serde(default, rename = "abstract")]
280    pub is_abstract: Option<bool>,
281    #[serde(default)]
282    pub accessibility: Option<Access>,
283    #[serde(default)]
284    pub declare: Option<bool>,
285    #[serde(default)]
286    pub definite: Option<bool>,
287    #[serde(default)]
288    pub optional: Option<bool>,
289    #[serde(default)]
290    pub readonly: Option<bool>,
291}
292#[derive(Serialize)]
293struct BabelClassProperty<'a> {
294    #[serde(rename = "type")]
295    type_: &'static str,
296    #[serde(flatten)]
297    pub base: &'a BaseNode,
298    pub key: &'a ObjectKey,
299    #[serde(default)]
300    pub value: Option<&'a Expression>,
301    #[serde(default)]
302    pub type_annotation: Option<&'a TypeAnnotOrNoop>,
303    #[serde(default)]
304    pub decorators: Option<&'a [Decorator]>,
305    #[serde(default)]
306    pub computed: Option<bool>,
307    #[serde(default, rename = "static")]
308    pub is_static: Option<bool>,
309    #[serde(default, rename = "abstract")]
310    pub is_abstract: Option<bool>,
311    #[serde(default)]
312    pub accessibility: Option<&'a Access>,
313    #[serde(default)]
314    pub declare: Option<bool>,
315    #[serde(default)]
316    pub definite: Option<bool>,
317    #[serde(default)]
318    pub optional: Option<bool>,
319    #[serde(default)]
320    pub readonly: Option<bool>,
321}
322
323impl Serialize for ClassProperty {
324    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
325    where
326        S: serde::Serializer,
327    {
328        match Flavor::current() {
329            Flavor::Babel => {
330                let actual = BabelClassProperty {
331                    type_: "ClassProperty",
332                    base: &self.base,
333                    key: &self.key,
334                    value: self.value.as_deref(),
335                    type_annotation: self.type_annotation.as_deref(),
336                    decorators: self.decorators.as_deref(),
337                    computed: self.computed,
338                    is_static: self.is_static,
339                    is_abstract: self.is_abstract,
340                    accessibility: self.accessibility.as_ref(),
341                    declare: self.declare,
342                    definite: self.definite,
343                    optional: self.optional,
344                    readonly: self.readonly,
345                };
346                actual.serialize(serializer)
347            }
348            Flavor::Acorn { .. } => {
349                let mut s = serializer.serialize_map(None)?;
350
351                {
352                    // TODO(kdy1): This is bad.
353                    self.base
354                        .serialize(crate::flat_map_serializer::FlatMapSerializer(&mut s))?;
355                }
356
357                s.serialize_entry("type", "PropertyDefinition")?;
358                s.serialize_entry("static", &self.is_static)?;
359                s.serialize_entry("key", &self.key)?;
360                s.serialize_entry("value", &self.value)?;
361                s.serialize_entry("computed", &self.computed)?;
362                if let Some(decorators) = &self.decorators {
363                    if !decorators.is_empty() {
364                        s.serialize_entry("decorators", decorators)?;
365                    }
366                }
367                s.serialize_entry("computed", &self.computed)?;
368
369                s.end()
370            }
371        }
372    }
373}
374
375#[derive(Debug, Clone, PartialEq)]
376#[ast_serde("StaticBlock")]
377pub struct StaticBlock {
378    #[serde(flatten)]
379    pub base: BaseNode,
380    #[serde(default)]
381    pub body: Vec<Statement>,
382}
383
384#[derive(Debug, Clone, PartialEq)]
385#[ast_serde]
386pub enum ClassBodyEl {
387    #[tag("ClassMethod")]
388    Method(ClassMethod),
389    #[tag("ClassPrivateMethod")]
390    PrivateMethod(ClassPrivateMethod),
391    #[tag("ClassProperty")]
392    Prop(ClassProperty),
393    #[tag("ClassPrivateProperty")]
394    PrivateProp(ClassPrivateProperty),
395    #[tag("TSDeclareMethod")]
396    TSMethod(TSDeclareMethod),
397    #[tag("TSIndexSignature")]
398    TSIndex(TSIndexSignature),
399    #[tag("StaticBlock")]
400    StaticBlock(StaticBlock),
401}
402
403#[derive(Debug, Clone, PartialEq)]
404#[ast_serde("ClassBody")]
405pub struct ClassBody {
406    #[serde(flatten)]
407    pub base: BaseNode,
408    #[serde(default)]
409    pub body: Vec<ClassBodyEl>,
410}
411
412#[derive(Debug, Clone, PartialEq)]
413#[ast_serde]
414pub enum ClassImpl {
415    #[tag("TSExpressionWithTypeArguments")]
416    TSExpr(TSExpressionWithTypeArguments),
417    #[tag("ClassImplements")]
418    Implements(ClassImplements),
419}
420
421impl From<TSExpressionWithTypeArguments> for ClassImpl {
422    fn from(expr: TSExpressionWithTypeArguments) -> Self {
423        ClassImpl::TSExpr(expr)
424    }
425}
426
427#[derive(Debug, Clone, PartialEq)]
428#[ast_serde("ClassDeclaration")]
429pub struct ClassDeclaration {
430    #[serde(flatten)]
431    pub base: BaseNode,
432    pub id: Identifier,
433    #[serde(default)]
434    pub super_class: Option<Box<Expression>>,
435    pub body: ClassBody,
436    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
437    pub decorators: Option<Vec<Decorator>>,
438    #[serde(
439        default,
440        rename = "abstract",
441        skip_serializing_if = "crate::ser::skip_typescript"
442    )]
443    pub is_abstract: Option<bool>,
444    #[serde(default, skip_serializing_if = "crate::ser::skip_typescript")]
445    pub declare: Option<bool>,
446    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_empty")]
447    pub implements: Option<Vec<ClassImpl>>,
448    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
449    pub mixins: Option<InterfaceExtends>,
450    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
451    pub super_type_parameters: Option<SuperTypeParams>,
452    #[serde(default, skip_serializing_if = "crate::flavor::Flavor::skip_none")]
453    pub type_parameters: Option<TypeParamDeclOrNoop>,
454}
455
456impl From<ClassExpression> for ClassDeclaration {
457    fn from(expr: ClassExpression) -> Self {
458        ClassDeclaration {
459            base: expr.base,
460            id: expr.id.unwrap(),
461            super_class: expr.super_class.map(|s| Box::new(*s)),
462            body: expr.body,
463            decorators: expr.decorators,
464            is_abstract: Default::default(),
465            declare: Default::default(),
466            implements: expr.implements,
467            mixins: expr.mixins,
468            super_type_parameters: expr.super_type_parameters,
469            type_parameters: expr.type_parameters,
470        }
471    }
472}