Skip to main content

swc_ecma_codegen/
class.rs

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