1use std::borrow::Cow;
2
3use is_macro::Is;
4use swc_atoms::Atom;
5use swc_common::{ast_node, util::take::Take, EqIgnoreSpan, Span, DUMMY_SP};
6
7use crate::{
8 decl::Decl,
9 expr::{ClassExpr, Expr, FnExpr},
10 ident::Ident,
11 lit::Str,
12 typescript::{TsExportAssignment, TsImportEqualsDecl, TsInterfaceDecl, TsNamespaceExportDecl},
13 BindingIdent, IdentName, ObjectLit,
14};
15
16#[ast_node]
17#[derive(Eq, Hash, Is, EqIgnoreSpan)]
18#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
19#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
20pub enum ModuleDecl {
21 #[tag("ImportDeclaration")]
22 Import(ImportDecl),
23
24 #[tag("ExportDeclaration")]
25 ExportDecl(ExportDecl),
26
27 #[tag("ExportNamedDeclaration")]
28 ExportNamed(NamedExport),
29
30 #[tag("ExportDefaultDeclaration")]
31 ExportDefaultDecl(ExportDefaultDecl),
32
33 #[tag("ExportDefaultExpression")]
34 ExportDefaultExpr(ExportDefaultExpr),
35
36 #[tag("ExportAllDeclaration")]
37 ExportAll(ExportAll),
38
39 #[tag("TsImportEqualsDeclaration")]
40 TsImportEquals(Box<TsImportEqualsDecl>),
41
42 #[tag("TsExportAssignment")]
43 TsExportAssignment(TsExportAssignment),
44
45 #[tag("TsNamespaceExportDeclaration")]
46 TsNamespaceExport(TsNamespaceExportDecl),
47}
48
49boxed!(ModuleDecl, [TsImportEqualsDecl]);
50
51macro_rules! module_decl {
52 ([$($variant:ty),*]) => {
53 $(
54 bridge_from!(crate::ModuleItem, crate::ModuleDecl, $variant);
55 )*
56 };
57}
58
59module_decl!([
60 ImportDecl,
61 ExportDecl,
62 NamedExport,
63 ExportDefaultDecl,
64 ExportDefaultExpr,
65 ExportAll,
66 TsImportEqualsDecl,
67 TsExportAssignment,
68 TsNamespaceExportDecl
69]);
70
71impl Take for ModuleDecl {
72 fn dummy() -> Self {
73 ImportDecl::dummy().into()
74 }
75}
76
77#[ast_node("ExportDefaultExpression")]
97#[derive(Eq, Hash, EqIgnoreSpan)]
98#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
99#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
100pub struct ExportDefaultExpr {
101 pub span: Span,
102
103 #[cfg_attr(feature = "serde-impl", serde(rename = "expression"))]
104 pub expr: Box<Expr>,
105}
106
107#[ast_node("ExportDeclaration")]
108#[derive(Eq, Hash, EqIgnoreSpan)]
109#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
110#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
111pub struct ExportDecl {
112 pub span: Span,
113
114 #[cfg_attr(feature = "serde-impl", serde(rename = "declaration"))]
115 pub decl: Decl,
116}
117
118#[ast_node("ImportDeclaration")]
119#[derive(Eq, Hash, EqIgnoreSpan)]
120#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
121#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
122pub struct ImportDecl {
123 pub span: Span,
124
125 #[cfg_attr(feature = "serde-impl", serde(default))]
126 pub specifiers: Vec<ImportSpecifier>,
127
128 #[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
129 pub src: Box<Str>,
130
131 #[cfg_attr(feature = "serde-impl", serde(default, rename = "typeOnly"))]
132 pub type_only: bool,
133
134 #[cfg_attr(feature = "serde-impl", serde(default))]
135 #[cfg_attr(
136 feature = "encoding-impl",
137 encoding(with = "cbor4ii::core::types::Maybe")
138 )]
139 pub with: Option<Box<ObjectLit>>,
140
141 #[cfg_attr(feature = "serde-impl", serde(default))]
142 pub phase: ImportPhase,
143}
144
145#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default, EqIgnoreSpan)]
146#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
147#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
148#[cfg_attr(
149 any(feature = "rkyv-impl"),
150 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
151)]
152#[cfg_attr(feature = "rkyv-impl", derive(bytecheck::CheckBytes))]
153#[cfg_attr(feature = "rkyv-impl", repr(u32))]
154#[cfg_attr(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))]
155#[cfg_attr(
156 feature = "encoding-impl",
157 derive(::swc_common::Encode, ::swc_common::Decode)
158)]
159#[cfg_attr(swc_ast_unknown, non_exhaustive)]
160pub enum ImportPhase {
161 #[default]
162 #[cfg_attr(feature = "serde-impl", serde(rename = "evaluation"))]
163 Evaluation,
164 #[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
165 Source,
166 #[cfg_attr(feature = "serde-impl", serde(rename = "defer"))]
167 Defer,
168}
169
170impl Take for ImportDecl {
171 fn dummy() -> Self {
172 ImportDecl {
173 span: DUMMY_SP,
174 specifiers: Take::dummy(),
175 src: Take::dummy(),
176 type_only: Default::default(),
177 with: Take::dummy(),
178 phase: Default::default(),
179 }
180 }
181}
182
183#[ast_node("ExportAllDeclaration")]
185#[derive(Eq, Hash, EqIgnoreSpan)]
186#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
187#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
188pub struct ExportAll {
189 pub span: Span,
190
191 #[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
192 pub src: Box<Str>,
193
194 #[cfg_attr(feature = "serde-impl", serde(rename = "typeOnly"))]
195 pub type_only: bool,
196
197 #[cfg_attr(feature = "serde-impl", serde(default))]
198 #[cfg_attr(
199 feature = "encoding-impl",
200 encoding(with = "cbor4ii::core::types::Maybe")
201 )]
202 pub with: Option<Box<ObjectLit>>,
203}
204
205impl Take for ExportAll {
206 fn dummy() -> Self {
207 Self {
208 span: DUMMY_SP,
209 src: Take::dummy(),
210 type_only: Default::default(),
211 with: Take::dummy(),
212 }
213 }
214}
215
216#[ast_node("ExportNamedDeclaration")]
219#[derive(Eq, Hash, EqIgnoreSpan)]
220#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
221#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
222pub struct NamedExport {
223 pub span: Span,
224
225 pub specifiers: Vec<ExportSpecifier>,
226
227 #[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
228 #[cfg_attr(
229 feature = "encoding-impl",
230 encoding(with = "cbor4ii::core::types::Maybe")
231 )]
232 pub src: Option<Box<Str>>,
233
234 #[cfg_attr(feature = "serde-impl", serde(rename = "typeOnly"))]
235 pub type_only: bool,
236
237 #[cfg_attr(feature = "serde-impl", serde(default))]
238 #[cfg_attr(
239 feature = "encoding-impl",
240 encoding(with = "cbor4ii::core::types::Maybe")
241 )]
242 pub with: Option<Box<ObjectLit>>,
243}
244
245impl Take for NamedExport {
246 fn dummy() -> Self {
247 Self {
248 span: DUMMY_SP,
249 specifiers: Take::dummy(),
250 src: Take::dummy(),
251 type_only: Default::default(),
252 with: Take::dummy(),
253 }
254 }
255}
256
257#[ast_node("ExportDefaultDeclaration")]
258#[derive(Eq, Hash, EqIgnoreSpan)]
259#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
260#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
261pub struct ExportDefaultDecl {
262 pub span: Span,
263
264 pub decl: DefaultDecl,
265}
266
267#[ast_node]
268#[derive(Eq, Hash, Is, EqIgnoreSpan)]
269#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
270#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
271pub enum DefaultDecl {
272 #[tag("ClassExpression")]
273 Class(ClassExpr),
274
275 #[tag("FunctionExpression")]
276 #[is(name = "fn_expr")]
277 Fn(FnExpr),
278
279 #[tag("TsInterfaceDeclaration")]
280 TsInterfaceDecl(Box<TsInterfaceDecl>),
281}
282
283#[ast_node]
284#[derive(Eq, Hash, Is, EqIgnoreSpan)]
285#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
286#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
287pub enum ImportSpecifier {
288 #[tag("ImportSpecifier")]
289 Named(ImportNamedSpecifier),
290 #[tag("ImportDefaultSpecifier")]
291 Default(ImportDefaultSpecifier),
292 #[tag("ImportNamespaceSpecifier")]
293 Namespace(ImportStarAsSpecifier),
294}
295
296impl ImportSpecifier {
297 pub fn is_type_only(&self) -> bool {
298 match self {
299 ImportSpecifier::Named(named) => named.is_type_only,
300 ImportSpecifier::Default(..) | ImportSpecifier::Namespace(..) => false,
301 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
302 _ => swc_common::unknown!(),
303 }
304 }
305
306 pub fn local(&self) -> &Ident {
307 match self {
308 ImportSpecifier::Named(named) => &named.local,
309 ImportSpecifier::Default(default) => &default.local,
310 ImportSpecifier::Namespace(ns) => &ns.local,
311 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
312 _ => swc_common::unknown!(),
313 }
314 }
315
316 pub fn local_mut(&mut self) -> &mut Ident {
317 match self {
318 ImportSpecifier::Named(named) => &mut named.local,
319 ImportSpecifier::Default(default) => &mut default.local,
320 ImportSpecifier::Namespace(ns) => &mut ns.local,
321 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
322 _ => swc_common::unknown!(),
323 }
324 }
325}
326
327#[ast_node("ImportDefaultSpecifier")]
329#[derive(Eq, Hash, EqIgnoreSpan)]
330#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
331#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
332pub struct ImportDefaultSpecifier {
333 pub span: Span,
334
335 pub local: Ident,
336}
337#[ast_node("ImportNamespaceSpecifier")]
339#[derive(Eq, Hash, EqIgnoreSpan)]
340#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
341#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
342pub struct ImportStarAsSpecifier {
343 pub span: Span,
344
345 pub local: Ident,
346}
347#[ast_node("ImportSpecifier")]
351#[derive(Eq, Hash, EqIgnoreSpan)]
352#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
353#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
354pub struct ImportNamedSpecifier {
355 pub span: Span,
356
357 pub local: Ident,
358
359 #[cfg_attr(feature = "serde-impl", serde(default))]
360 #[cfg_attr(
361 feature = "encoding-impl",
362 encoding(with = "cbor4ii::core::types::Maybe")
363 )]
364 pub imported: Option<ModuleExportName>,
365
366 #[cfg_attr(feature = "serde-impl", serde(default))]
367 pub is_type_only: bool,
368}
369
370#[ast_node]
371#[derive(Eq, Hash, Is, EqIgnoreSpan)]
372#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
373#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
374pub enum ExportSpecifier {
375 #[tag("ExportNamespaceSpecifier")]
376 Namespace(ExportNamespaceSpecifier),
377
378 #[tag("ExportDefaultSpecifier")]
379 Default(ExportDefaultSpecifier),
380
381 #[tag("ExportSpecifier")]
382 Named(ExportNamedSpecifier),
383}
384
385#[ast_node("ExportNamespaceSpecifier")]
387#[derive(Eq, Hash, EqIgnoreSpan)]
388#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
389#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
390pub struct ExportNamespaceSpecifier {
391 pub span: Span,
392
393 pub name: ModuleExportName,
394}
395
396#[ast_node("ExportDefaultSpecifier")]
398#[derive(Eq, Hash, EqIgnoreSpan)]
399#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
400#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
401pub struct ExportDefaultSpecifier {
402 #[span]
403 pub exported: Ident,
404}
405
406#[ast_node("ExportSpecifier")]
407#[derive(Eq, Hash, EqIgnoreSpan)]
408#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
409#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
410pub struct ExportNamedSpecifier {
411 pub span: Span,
412 pub orig: ModuleExportName,
414 #[cfg_attr(feature = "serde-impl", serde(default))]
416 #[cfg_attr(
417 feature = "encoding-impl",
418 encoding(with = "cbor4ii::core::types::Maybe")
419 )]
420 pub exported: Option<ModuleExportName>,
421 #[cfg_attr(feature = "serde-impl", serde(default))]
423 pub is_type_only: bool,
424}
425
426#[ast_node]
427#[derive(Eq, Hash, EqIgnoreSpan)]
428#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
429#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
430pub enum ModuleExportName {
432 #[tag("Identifier")]
433 Ident(Ident),
434
435 #[tag("StringLiteral")]
436 Str(Str),
437}
438
439bridge_from!(ModuleExportName, Ident, BindingIdent);
440bridge_from!(ModuleExportName, Ident, IdentName);
441
442impl ModuleExportName {
443 pub fn atom(&self) -> Cow<'_, Atom> {
451 match self {
452 ModuleExportName::Ident(i) => Cow::Borrowed(&i.sym),
453 ModuleExportName::Str(s) => match s.value.clone().try_into_atom() {
454 Ok(atom) => Cow::Owned(atom),
455 Err(original) => Cow::Owned(Atom::from(&*original.to_string_lossy())),
456 },
457 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
458 _ => swc_common::unknown!(),
459 }
460 }
461}