swc_ecma_codegen/
module_decls.rs

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