swc_ecma_codegen/
class.rs

1use swc_common::{SourceMapper, Spanned};
2use swc_ecma_ast::*;
3use swc_ecma_codegen_macros::node_impl;
4
5use crate::{
6    text_writer::WriteJs, util::StartsWithAlphaNum, Emitter, ListFormat, Result, SourceMapperExt,
7};
8
9impl<W, S: SourceMapper> Emitter<'_, W, S>
10where
11    W: WriteJs,
12    S: SourceMapperExt,
13{
14    pub fn emit_class_trailing(&mut self, node: &Class) -> Result {
15        if node.super_class.is_some() {
16            space!(self);
17            keyword!(self, "extends");
18
19            {
20                let starts_with_alpha_num =
21                    node.super_class.as_ref().unwrap().starts_with_alpha_num();
22
23                if starts_with_alpha_num {
24                    space!(self);
25                } else {
26                    formatting_space!(self)
27                }
28            }
29            emit!(self, node.super_class);
30            emit!(self, node.super_type_params);
31        }
32
33        if !node.implements.is_empty() {
34            space!(self);
35            keyword!(self, "implements");
36
37            space!(self);
38
39            self.emit_list(
40                node.span,
41                Some(&node.implements),
42                ListFormat::ClassHeritageClauses,
43            )?;
44        }
45
46        formatting_space!(self);
47
48        punct!(self, "{");
49
50        self.emit_list(node.span, Some(&node.body), ListFormat::ClassMembers)?;
51
52        srcmap!(self, node, false, true);
53        punct!(self, "}");
54
55        Ok(())
56    }
57}
58
59#[node_impl]
60impl MacroNode for ClassExpr {
61    fn emit(&mut self, emitter: &mut Macro) -> Result {
62        emitter.emit_leading_comments_of_span(self.span(), false)?;
63
64        srcmap!(emitter, self, true);
65
66        for dec in &self.class.decorators {
67            emit!(dec);
68        }
69
70        if self.class.is_abstract {
71            keyword!(emitter, "abstract");
72            space!(emitter);
73        }
74
75        keyword!(emitter, "class");
76
77        if let Some(ref i) = self.ident {
78            space!(emitter);
79            emit!(i);
80            emit!(self.class.type_params);
81        }
82
83        emitter.emit_class_trailing(&self.class)?;
84
85        Ok(())
86    }
87}
88
89#[node_impl]
90impl MacroNode for Class {
91    fn emit(&mut self, emitter: &mut Macro) -> Result {
92        if self.super_class.is_some() {
93            space!(emitter);
94            keyword!(emitter, "extends");
95
96            {
97                let starts_with_alpha_num =
98                    self.super_class.as_ref().unwrap().starts_with_alpha_num();
99
100                if starts_with_alpha_num {
101                    space!(emitter);
102                } else {
103                    formatting_space!(emitter)
104                }
105            }
106            emit!(self.super_class);
107            emit!(self.super_type_params);
108        }
109
110        if !self.implements.is_empty() {
111            space!(emitter);
112            keyword!(emitter, "implements");
113
114            space!(emitter);
115
116            emitter.emit_list(
117                self.span,
118                Some(&self.implements),
119                ListFormat::ClassHeritageClauses,
120            )?;
121        }
122
123        formatting_space!(emitter);
124
125        punct!(emitter, "{");
126
127        emitter.emit_list(self.span, Some(&self.body), ListFormat::ClassMembers)?;
128
129        srcmap!(emitter, self, false, true);
130        punct!(emitter, "}");
131
132        Ok(())
133    }
134}
135
136#[node_impl]
137impl MacroNode for ClassMember {
138    fn emit(&mut self, emitter: &mut Macro) -> Result {
139        match self {
140            ClassMember::Constructor(ref n) => emit!(n),
141            ClassMember::ClassProp(ref n) => emit!(n),
142            ClassMember::Method(ref n) => emit!(n),
143            ClassMember::PrivateMethod(ref n) => emit!(n),
144            ClassMember::PrivateProp(ref n) => emit!(n),
145            ClassMember::TsIndexSignature(ref n) => emit!(n),
146            ClassMember::Empty(ref n) => emit!(n),
147            ClassMember::StaticBlock(ref n) => emit!(n),
148            ClassMember::AutoAccessor(ref n) => emit!(n),
149        }
150
151        Ok(())
152    }
153}
154
155#[node_impl]
156impl MacroNode for AutoAccessor {
157    fn emit(&mut self, emitter: &mut Macro) -> Result {
158        emitter.emit_list(self.span, Some(&self.decorators), ListFormat::Decorators)?;
159
160        emitter.emit_accessibility(self.accessibility)?;
161
162        if self.is_static {
163            keyword!(emitter, "static");
164            space!(emitter);
165        }
166
167        if self.is_abstract {
168            keyword!(emitter, "abstract");
169            space!(emitter);
170        }
171
172        if self.is_override {
173            keyword!(emitter, "override");
174            space!(emitter);
175        }
176
177        keyword!(emitter, "accessor");
178        space!(emitter);
179
180        emit!(self.key);
181
182        if let Some(type_ann) = &self.type_ann {
183            if self.definite {
184                punct!(emitter, "!");
185            }
186            punct!(emitter, ":");
187            space!(emitter);
188            emit!(type_ann);
189        }
190
191        if let Some(init) = &self.value {
192            formatting_space!(emitter);
193            punct!(emitter, "=");
194            formatting_space!(emitter);
195            emit!(init);
196        }
197
198        semi!(emitter);
199
200        Ok(())
201    }
202}
203
204#[node_impl]
205impl MacroNode for Key {
206    fn emit(&mut self, emitter: &mut Macro) -> Result {
207        match self {
208            Key::Private(n) => emit!(n),
209            Key::Public(n) => emit!(n),
210        }
211
212        Ok(())
213    }
214}
215
216#[node_impl]
217impl MacroNode for PrivateMethod {
218    fn emit(&mut self, emitter: &mut Macro) -> Result {
219        emitter.emit_leading_comments_of_span(self.span(), false)?;
220
221        srcmap!(emitter, self, true);
222
223        if self.is_static {
224            keyword!(emitter, "static");
225            space!(emitter);
226        }
227        match self.kind {
228            MethodKind::Method => {
229                if self.function.is_async {
230                    keyword!(emitter, "async");
231                    space!(emitter);
232                }
233                if self.function.is_generator {
234                    punct!(emitter, "*");
235                }
236
237                emit!(self.key);
238            }
239            MethodKind::Getter => {
240                keyword!(emitter, "get");
241                space!(emitter);
242
243                emit!(self.key);
244            }
245            MethodKind::Setter => {
246                keyword!(emitter, "set");
247                space!(emitter);
248
249                emit!(self.key);
250            }
251        }
252
253        emitter.emit_fn_trailing(&self.function)?;
254
255        Ok(())
256    }
257}
258
259#[node_impl]
260impl MacroNode for ClassMethod {
261    fn emit(&mut self, emitter: &mut Macro) -> Result {
262        emitter.emit_leading_comments_of_span(self.span(), false)?;
263
264        emitter.emit_leading_comments_of_span(self.key.span(), false)?;
265
266        srcmap!(emitter, self, true);
267
268        for d in &self.function.decorators {
269            emit!(d);
270        }
271
272        emitter.emit_accessibility(self.accessibility)?;
273
274        if self.is_static {
275            keyword!(emitter, "static");
276
277            let starts_with_alpha_num = match self.kind {
278                MethodKind::Method => {
279                    if self.function.is_async {
280                        true
281                    } else if self.function.is_generator {
282                        false
283                    } else {
284                        self.key.starts_with_alpha_num()
285                    }
286                }
287                MethodKind::Getter => true,
288                MethodKind::Setter => true,
289            };
290
291            if starts_with_alpha_num {
292                space!(emitter);
293            } else {
294                formatting_space!(emitter);
295            }
296        }
297
298        if self.is_abstract {
299            keyword!(emitter, "abstract");
300            space!(emitter)
301        }
302
303        if self.is_override {
304            keyword!(emitter, "override");
305            space!(emitter)
306        }
307
308        match self.kind {
309            MethodKind::Method => {
310                if self.function.is_async {
311                    keyword!(emitter, "async");
312                    space!(emitter);
313                }
314                if self.function.is_generator {
315                    punct!(emitter, "*");
316                }
317
318                emit!(self.key);
319            }
320            MethodKind::Getter => {
321                keyword!(emitter, "get");
322
323                if self.key.starts_with_alpha_num() {
324                    space!(emitter);
325                } else {
326                    formatting_space!(emitter)
327                }
328
329                emit!(self.key);
330            }
331            MethodKind::Setter => {
332                keyword!(emitter, "set");
333
334                if self.key.starts_with_alpha_num() {
335                    space!(emitter);
336                } else {
337                    formatting_space!(emitter)
338                }
339
340                emit!(self.key);
341            }
342        }
343
344        if self.is_optional {
345            punct!(emitter, "?");
346        }
347
348        if let Some(type_params) = &self.function.type_params {
349            emit!(type_params);
350        }
351
352        punct!(emitter, "(");
353        emitter.emit_list(
354            self.function.span,
355            Some(&self.function.params),
356            ListFormat::CommaListElements,
357        )?;
358
359        punct!(emitter, ")");
360
361        if let Some(ty) = &self.function.return_type {
362            punct!(emitter, ":");
363            formatting_space!(emitter);
364            emit!(ty);
365        }
366
367        if let Some(body) = &self.function.body {
368            formatting_space!(emitter);
369            emit!(body);
370        } else {
371            formatting_semi!(emitter)
372        }
373
374        Ok(())
375    }
376}
377
378#[node_impl]
379impl MacroNode for PrivateProp {
380    fn emit(&mut self, emitter: &mut Macro) -> Result {
381        emitter.emit_leading_comments_of_span(self.span(), false)?;
382
383        srcmap!(emitter, self, true);
384
385        emitter.emit_list(self.span, Some(&self.decorators), ListFormat::Decorators)?;
386
387        emitter.emit_accessibility(self.accessibility)?;
388
389        if self.is_static {
390            keyword!(emitter, "static");
391            space!(emitter);
392        }
393
394        if self.is_override {
395            keyword!(emitter, "override");
396            space!(emitter)
397        }
398
399        if self.readonly {
400            keyword!(emitter, "readonly");
401            space!(emitter);
402        }
403
404        emit!(self.key);
405
406        if self.is_optional {
407            punct!(emitter, "?");
408        }
409
410        if let Some(type_ann) = &self.type_ann {
411            if self.definite {
412                punct!(emitter, "!");
413            }
414            punct!(emitter, ":");
415            space!(emitter);
416            emit!(type_ann);
417        }
418
419        if let Some(value) = &self.value {
420            formatting_space!(emitter);
421            punct!(emitter, "=");
422            formatting_space!(emitter);
423
424            if value.is_seq() {
425                punct!(emitter, "(");
426                emit!(value);
427                punct!(emitter, ")");
428            } else {
429                emit!(value);
430            }
431        }
432
433        semi!(emitter);
434
435        srcmap!(emitter, self, false);
436
437        Ok(())
438    }
439}
440
441#[node_impl]
442impl MacroNode for ClassProp {
443    fn emit(&mut self, emitter: &mut Macro) -> Result {
444        emitter.emit_leading_comments_of_span(self.span(), false)?;
445        srcmap!(emitter, self, true);
446
447        for dec in &self.decorators {
448            emit!(dec)
449        }
450
451        if self.declare {
452            keyword!(emitter, "declare");
453            space!(emitter);
454        }
455
456        emitter.emit_accessibility(self.accessibility)?;
457
458        if self.is_static {
459            keyword!(emitter, "static");
460            space!(emitter);
461        }
462
463        if self.is_abstract {
464            keyword!(emitter, "abstract");
465            space!(emitter)
466        }
467
468        if self.is_override {
469            keyword!(emitter, "override");
470            space!(emitter)
471        }
472
473        if self.readonly {
474            keyword!(emitter, "readonly");
475            space!(emitter)
476        }
477
478        emit!(self.key);
479
480        if self.is_optional {
481            punct!(emitter, "?");
482        }
483
484        if let Some(ty) = &self.type_ann {
485            if self.definite {
486                punct!(emitter, "!");
487            }
488            punct!(emitter, ":");
489            space!(emitter);
490            emit!(ty);
491        }
492
493        if let Some(v) = &self.value {
494            formatting_space!(emitter);
495            punct!(emitter, "=");
496            formatting_space!(emitter);
497
498            if v.is_seq() {
499                punct!(emitter, "(");
500                emit!(v);
501                punct!(emitter, ")");
502            } else {
503                emit!(v);
504            }
505        }
506
507        semi!(emitter);
508
509        srcmap!(emitter, self, false);
510
511        Ok(())
512    }
513}
514
515#[node_impl]
516impl MacroNode for Constructor {
517    fn emit(&mut self, emitter: &mut Macro) -> Result {
518        emitter.emit_leading_comments_of_span(self.span(), false)?;
519
520        srcmap!(emitter, self, true);
521
522        emitter.emit_accessibility(self.accessibility)?;
523
524        keyword!(emitter, "constructor");
525        punct!(emitter, "(");
526        emitter.emit_list(self.span(), Some(&self.params), ListFormat::Parameters)?;
527        punct!(emitter, ")");
528
529        if let Some(body) = &self.body {
530            emit!(body);
531        } else {
532            formatting_semi!(emitter);
533        }
534
535        Ok(())
536    }
537}
538
539#[node_impl]
540impl MacroNode for StaticBlock {
541    fn emit(&mut self, emitter: &mut Macro) -> Result {
542        emitter.emit_leading_comments_of_span(self.span(), false)?;
543
544        srcmap!(emitter, self, true);
545
546        keyword!(emitter, "static");
547        emit!(self.body);
548
549        srcmap!(emitter, self, false);
550
551        Ok(())
552    }
553}
554
555impl<W, S: SourceMapper> Emitter<'_, W, S>
556where
557    W: WriteJs,
558    S: SourceMapperExt,
559{
560    pub fn emit_accessibility(&mut self, n: Option<Accessibility>) -> Result {
561        if let Some(a) = n {
562            match a {
563                Accessibility::Public => keyword!(self, "public"),
564                Accessibility::Protected => keyword!(self, "protected"),
565                Accessibility::Private => keyword!(self, "private"),
566            }
567            space!(self);
568        }
569
570        Ok(())
571    }
572}