swc_ecma_codegen/
module_decls.rs

1use swc_common::Spanned;
2use swc_ecma_ast::*;
3use swc_ecma_codegen_macros::node_impl;
4
5#[cfg(swc_ast_unknown)]
6use crate::unknown_error;
7use crate::{util::StartsWithAlphaNum, ListFormat};
8
9#[node_impl]
10impl MacroNode for ModuleDecl {
11    fn emit(&mut self, emitter: &mut Macro) -> Result {
12        emitter.emit_leading_comments_of_span(self.span(), false)?;
13
14        match self {
15            ModuleDecl::Import(ref d) => emit!(d),
16            ModuleDecl::ExportDecl(ref d) => emit!(d),
17            ModuleDecl::ExportNamed(ref d) => emit!(d),
18            ModuleDecl::ExportDefaultDecl(ref d) => emit!(d),
19            ModuleDecl::ExportDefaultExpr(ref n) => emit!(n),
20            ModuleDecl::ExportAll(ref d) => emit!(d),
21            ModuleDecl::TsExportAssignment(ref n) => emit!(n),
22            ModuleDecl::TsImportEquals(ref n) => emit!(n),
23            ModuleDecl::TsNamespaceExport(ref n) => emit!(n),
24            #[cfg(swc_ast_unknown)]
25            _ => return Err(unknown_error()),
26        }
27
28        emitter.emit_trailing_comments_of_pos(self.span().hi, true, true)?;
29
30        if !emitter.cfg.minify {
31            emitter.wr.write_line()?;
32        }
33
34        Ok(())
35    }
36}
37
38#[node_impl]
39impl MacroNode for ExportDecl {
40    fn emit(&mut self, emitter: &mut Macro) -> Result {
41        srcmap!(emitter, self, true);
42
43        match &self.decl {
44            Decl::Class(decl) => {
45                for dec in &decl.class.decorators {
46                    emit!(dec);
47                }
48
49                keyword!(emitter, "export");
50
51                space!(emitter);
52                emitter.emit_class_decl_inner(decl, true)?;
53            }
54            _ => {
55                keyword!(emitter, "export");
56
57                space!(emitter);
58                emit!(self.decl);
59            }
60        }
61
62        Ok(())
63    }
64}
65
66#[node_impl]
67impl MacroNode for ExportDefaultExpr {
68    fn emit(&mut self, emitter: &mut Macro) -> Result {
69        srcmap!(emitter, self, true);
70
71        keyword!(emitter, "export");
72
73        space!(emitter);
74        keyword!(emitter, "default");
75        {
76            let starts_with_alpha_num = self.expr.starts_with_alpha_num();
77            if starts_with_alpha_num {
78                space!(emitter);
79            } else {
80                formatting_space!(emitter);
81            }
82            emit!(self.expr);
83        }
84        semi!(emitter);
85
86        srcmap!(emitter, self, false);
87
88        Ok(())
89    }
90}
91
92#[node_impl]
93impl MacroNode for ExportDefaultDecl {
94    fn emit(&mut self, emitter: &mut Macro) -> Result {
95        emitter.emit_leading_comments_of_span(self.span(), false)?;
96
97        srcmap!(emitter, self, true);
98
99        keyword!(emitter, "export");
100
101        space!(emitter);
102        keyword!(emitter, "default");
103        space!(emitter);
104        match self.decl {
105            DefaultDecl::Class(ref n) => emit!(n),
106            DefaultDecl::Fn(ref n) => emit!(n),
107            DefaultDecl::TsInterfaceDecl(ref n) => emit!(n),
108            #[cfg(swc_ast_unknown)]
109            _ => return Err(unknown_error()),
110        }
111
112        Ok(())
113    }
114}
115
116#[node_impl]
117impl MacroNode for ImportDecl {
118    fn emit(&mut self, emitter: &mut Macro) -> Result {
119        emitter.emit_leading_comments_of_span(self.span(), false)?;
120
121        srcmap!(emitter, self, true);
122
123        keyword!(emitter, "import");
124
125        if self.type_only {
126            space!(emitter);
127            keyword!(emitter, "type");
128        }
129
130        match self.phase {
131            ImportPhase::Evaluation => {}
132            ImportPhase::Source => {
133                space!(emitter);
134                keyword!(emitter, "source");
135            }
136            ImportPhase::Defer => {
137                space!(emitter);
138                keyword!(emitter, "defer");
139            }
140            #[cfg(swc_ast_unknown)]
141            _ => return Err(unknown_error()),
142        }
143
144        let starts_with_ident = !self.specifiers.is_empty()
145            && match &self.specifiers[0] {
146                ImportSpecifier::Default(_) => true,
147                _ => false,
148            };
149        if starts_with_ident {
150            space!(emitter);
151        } else {
152            formatting_space!(emitter);
153        }
154
155        let mut specifiers = Vec::new();
156        let mut emitted_default = false;
157        let mut emitted_ns = false;
158        for specifier in &self.specifiers {
159            match specifier {
160                ImportSpecifier::Named(ref s) => {
161                    specifiers.push(s);
162                }
163                ImportSpecifier::Default(ref s) => {
164                    emit!(s.local);
165                    emitted_default = true;
166                }
167                ImportSpecifier::Namespace(ref ns) => {
168                    if emitted_default {
169                        punct!(emitter, ",");
170                        formatting_space!(emitter);
171                    }
172
173                    emitted_ns = true;
174
175                    assert!(self.specifiers.len() <= 2);
176                    punct!(emitter, "*");
177                    formatting_space!(emitter);
178                    keyword!(emitter, "as");
179                    space!(emitter);
180                    emit!(ns.local);
181                }
182                #[cfg(swc_ast_unknown)]
183                _ => return Err(unknown_error()),
184            }
185        }
186
187        if specifiers.is_empty() {
188            if emitted_ns || emitted_default {
189                space!(emitter);
190                keyword!(emitter, "from");
191                formatting_space!(emitter);
192            }
193        } else {
194            if emitted_default {
195                punct!(emitter, ",");
196                formatting_space!(emitter);
197            }
198
199            punct!(emitter, "{");
200            emitter.emit_list(
201                self.span(),
202                Some(&specifiers),
203                ListFormat::NamedImportsOrExportsElements,
204            )?;
205            punct!(emitter, "}");
206            formatting_space!(emitter);
207
208            keyword!(emitter, "from");
209            formatting_space!(emitter);
210        }
211
212        emit!(self.src);
213
214        if let Some(with) = &self.with {
215            formatting_space!(emitter);
216            if emitter.cfg.emit_assert_for_import_attributes {
217                keyword!(emitter, "assert");
218            } else {
219                keyword!(emitter, "with")
220            };
221            formatting_space!(emitter);
222            emit!(with);
223        }
224
225        semi!(emitter);
226
227        srcmap!(emitter, self, false);
228
229        Ok(())
230    }
231}
232
233#[node_impl]
234impl MacroNode for ImportNamedSpecifier {
235    fn emit(&mut self, emitter: &mut Macro) -> Result {
236        srcmap!(emitter, self, true);
237
238        if self.is_type_only {
239            keyword!(emitter, "type");
240            space!(emitter);
241        }
242
243        if let Some(ref imported) = self.imported {
244            emit!(imported);
245            space!(emitter);
246            keyword!(emitter, "as");
247            space!(emitter);
248        }
249
250        emit!(self.local);
251
252        srcmap!(emitter, self, false);
253
254        Ok(())
255    }
256}
257
258#[node_impl]
259impl MacroNode for ExportSpecifier {
260    fn emit(&mut self, emitter: &mut Macro) -> Result {
261        match self {
262            ExportSpecifier::Default(..) => {
263                unimplemented!("codegen of `export default from 'foo';`")
264            }
265            ExportSpecifier::Namespace(ref node) => emit!(node),
266            ExportSpecifier::Named(ref node) => emit!(node),
267            #[cfg(swc_ast_unknown)]
268            _ => return Err(unknown_error()),
269        }
270
271        Ok(())
272    }
273}
274
275#[node_impl]
276impl MacroNode for ExportNamespaceSpecifier {
277    fn emit(&mut self, emitter: &mut Macro) -> Result {
278        emitter.emit_leading_comments_of_span(self.span(), false)?;
279
280        srcmap!(emitter, self, true);
281
282        punct!(emitter, "*");
283        formatting_space!(emitter);
284        keyword!(emitter, "as");
285        space!(emitter);
286        emit!(self.name);
287
288        srcmap!(emitter, self, false);
289
290        Ok(())
291    }
292}
293
294#[node_impl]
295impl MacroNode for ExportNamedSpecifier {
296    fn emit(&mut self, emitter: &mut Macro) -> Result {
297        emitter.emit_leading_comments_of_span(self.span(), false)?;
298
299        srcmap!(emitter, self, true);
300
301        if self.is_type_only {
302            keyword!(emitter, "type");
303            space!(emitter);
304        }
305
306        if let Some(exported) = &self.exported {
307            emit!(self.orig);
308            space!(emitter);
309            keyword!(emitter, "as");
310            space!(emitter);
311            emit!(exported);
312        } else {
313            emit!(self.orig);
314        }
315        srcmap!(emitter, self, false);
316
317        Ok(())
318    }
319}
320
321#[node_impl]
322impl MacroNode for NamedExport {
323    fn emit(&mut self, emitter: &mut Macro) -> Result {
324        emitter.emit_leading_comments_of_span(self.span(), false)?;
325
326        srcmap!(emitter, self, true);
327
328        struct Specifiers<'a> {
329            has_namespace_spec: bool,
330            namespace_spec: Option<&'a ExportNamespaceSpecifier>,
331            has_named_specs: bool,
332            named_specs: Vec<&'a ExportSpecifier>,
333        }
334        let Specifiers {
335            has_namespace_spec,
336            namespace_spec,
337            has_named_specs,
338            named_specs,
339        } = self.specifiers.iter().fold(
340            Specifiers {
341                has_namespace_spec: false,
342                namespace_spec: None,
343                has_named_specs: false,
344                named_specs: Vec::new(),
345            },
346            |mut result, s| match s {
347                ExportSpecifier::Namespace(spec) => {
348                    result.has_namespace_spec = true;
349                    // There can only be one namespace export specifier.
350                    if result.namespace_spec.is_none() {
351                        result.namespace_spec = Some(spec)
352                    }
353                    result
354                }
355                spec => {
356                    result.has_named_specs = true;
357                    result.named_specs.push(spec);
358                    result
359                }
360            },
361        );
362
363        keyword!(emitter, "export");
364
365        if self.type_only {
366            space!(emitter);
367            keyword!(emitter, "type");
368        }
369        formatting_space!(emitter);
370
371        if let Some(spec) = namespace_spec {
372            emit!(spec);
373            if has_named_specs {
374                punct!(emitter, ",");
375                formatting_space!(emitter);
376            }
377        }
378        if has_named_specs || !has_namespace_spec {
379            punct!(emitter, "{");
380            emitter.emit_list(
381                self.span,
382                Some(&named_specs),
383                ListFormat::NamedImportsOrExportsElements,
384            )?;
385            punct!(emitter, "}");
386        }
387
388        if let Some(ref src) = self.src {
389            if has_named_specs || !has_namespace_spec {
390                formatting_space!(emitter);
391            } else if has_namespace_spec {
392                space!(emitter);
393            }
394            keyword!(emitter, "from");
395            formatting_space!(emitter);
396            emit!(src);
397
398            if let Some(with) = &self.with {
399                formatting_space!(emitter);
400                if emitter.cfg.emit_assert_for_import_attributes {
401                    keyword!(emitter, "assert");
402                } else {
403                    keyword!(emitter, "with")
404                };
405                formatting_space!(emitter);
406                emit!(with);
407            }
408        }
409        semi!(emitter);
410
411        srcmap!(emitter, self, false);
412
413        Ok(())
414    }
415}
416
417#[node_impl]
418impl MacroNode for ExportAll {
419    fn emit(&mut self, emitter: &mut Macro) -> Result {
420        emitter.emit_leading_comments_of_span(self.span(), false)?;
421
422        srcmap!(emitter, self, true);
423
424        keyword!(emitter, "export");
425
426        if self.type_only {
427            space!(emitter);
428            keyword!(emitter, "type");
429            space!(emitter);
430        } else {
431            formatting_space!(emitter);
432        }
433
434        punct!(emitter, "*");
435        formatting_space!(emitter);
436        keyword!(emitter, "from");
437        formatting_space!(emitter);
438        emit!(self.src);
439
440        if let Some(with) = &self.with {
441            formatting_space!(emitter);
442            if emitter.cfg.emit_assert_for_import_attributes {
443                keyword!(emitter, "assert");
444            } else {
445                keyword!(emitter, "with")
446            };
447            formatting_space!(emitter);
448            emit!(with);
449        }
450
451        semi!(emitter);
452
453        srcmap!(emitter, self, false);
454
455        Ok(())
456    }
457}