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 #[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 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 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}