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