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(feature = "serde-impl", derive(serde::Serialize, serde::Deserialize))]
149#[cfg_attr(
150 feature = "encoding-impl",
151 derive(::swc_common::Encode, ::swc_common::Decode)
152)]
153#[cfg_attr(swc_ast_unknown, non_exhaustive)]
154pub enum ImportPhase {
155 #[default]
156 #[cfg_attr(feature = "serde-impl", serde(rename = "evaluation"))]
157 Evaluation,
158 #[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
159 Source,
160 #[cfg_attr(feature = "serde-impl", serde(rename = "defer"))]
161 Defer,
162}
163
164impl Take for ImportDecl {
165 fn dummy() -> Self {
166 ImportDecl {
167 span: DUMMY_SP,
168 specifiers: Take::dummy(),
169 src: Take::dummy(),
170 type_only: Default::default(),
171 with: Take::dummy(),
172 phase: Default::default(),
173 }
174 }
175}
176
177#[ast_node("ExportAllDeclaration")]
179#[derive(Eq, Hash, EqIgnoreSpan)]
180#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
181#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
182pub struct ExportAll {
183 pub span: Span,
184
185 #[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
186 pub src: Box<Str>,
187
188 #[cfg_attr(feature = "serde-impl", serde(rename = "typeOnly"))]
189 pub type_only: bool,
190
191 #[cfg_attr(feature = "serde-impl", serde(default))]
192 #[cfg_attr(
193 feature = "encoding-impl",
194 encoding(with = "cbor4ii::core::types::Maybe")
195 )]
196 pub with: Option<Box<ObjectLit>>,
197}
198
199impl Take for ExportAll {
200 fn dummy() -> Self {
201 Self {
202 span: DUMMY_SP,
203 src: Take::dummy(),
204 type_only: Default::default(),
205 with: Take::dummy(),
206 }
207 }
208}
209
210#[ast_node("ExportNamedDeclaration")]
213#[derive(Eq, Hash, EqIgnoreSpan)]
214#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
215#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
216pub struct NamedExport {
217 pub span: Span,
218
219 pub specifiers: Vec<ExportSpecifier>,
220
221 #[cfg_attr(feature = "serde-impl", serde(rename = "source"))]
222 #[cfg_attr(
223 feature = "encoding-impl",
224 encoding(with = "cbor4ii::core::types::Maybe")
225 )]
226 pub src: Option<Box<Str>>,
227
228 #[cfg_attr(feature = "serde-impl", serde(rename = "typeOnly"))]
229 pub type_only: bool,
230
231 #[cfg_attr(feature = "serde-impl", serde(default))]
232 #[cfg_attr(
233 feature = "encoding-impl",
234 encoding(with = "cbor4ii::core::types::Maybe")
235 )]
236 pub with: Option<Box<ObjectLit>>,
237}
238
239impl Take for NamedExport {
240 fn dummy() -> Self {
241 Self {
242 span: DUMMY_SP,
243 specifiers: Take::dummy(),
244 src: Take::dummy(),
245 type_only: Default::default(),
246 with: Take::dummy(),
247 }
248 }
249}
250
251#[ast_node("ExportDefaultDeclaration")]
252#[derive(Eq, Hash, EqIgnoreSpan)]
253#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
254#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
255pub struct ExportDefaultDecl {
256 pub span: Span,
257
258 pub decl: DefaultDecl,
259}
260
261#[ast_node]
262#[derive(Eq, Hash, Is, EqIgnoreSpan)]
263#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
264#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
265pub enum DefaultDecl {
266 #[tag("ClassExpression")]
267 Class(ClassExpr),
268
269 #[tag("FunctionExpression")]
270 #[is(name = "fn_expr")]
271 Fn(FnExpr),
272
273 #[tag("TsInterfaceDeclaration")]
274 TsInterfaceDecl(Box<TsInterfaceDecl>),
275}
276
277#[ast_node]
278#[derive(Eq, Hash, Is, EqIgnoreSpan)]
279#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
280#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
281pub enum ImportSpecifier {
282 #[tag("ImportSpecifier")]
283 Named(ImportNamedSpecifier),
284 #[tag("ImportDefaultSpecifier")]
285 Default(ImportDefaultSpecifier),
286 #[tag("ImportNamespaceSpecifier")]
287 Namespace(ImportStarAsSpecifier),
288}
289
290impl ImportSpecifier {
291 pub fn is_type_only(&self) -> bool {
292 match self {
293 ImportSpecifier::Named(named) => named.is_type_only,
294 ImportSpecifier::Default(..) | ImportSpecifier::Namespace(..) => false,
295 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
296 _ => swc_common::unknown!(),
297 }
298 }
299
300 pub fn local(&self) -> &Ident {
301 match self {
302 ImportSpecifier::Named(named) => &named.local,
303 ImportSpecifier::Default(default) => &default.local,
304 ImportSpecifier::Namespace(ns) => &ns.local,
305 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
306 _ => swc_common::unknown!(),
307 }
308 }
309
310 pub fn local_mut(&mut self) -> &mut Ident {
311 match self {
312 ImportSpecifier::Named(named) => &mut named.local,
313 ImportSpecifier::Default(default) => &mut default.local,
314 ImportSpecifier::Namespace(ns) => &mut ns.local,
315 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
316 _ => swc_common::unknown!(),
317 }
318 }
319}
320
321#[ast_node("ImportDefaultSpecifier")]
323#[derive(Eq, Hash, EqIgnoreSpan)]
324#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
325#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
326pub struct ImportDefaultSpecifier {
327 pub span: Span,
328
329 pub local: Ident,
330}
331#[ast_node("ImportNamespaceSpecifier")]
333#[derive(Eq, Hash, EqIgnoreSpan)]
334#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
335#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
336pub struct ImportStarAsSpecifier {
337 pub span: Span,
338
339 pub local: Ident,
340}
341#[ast_node("ImportSpecifier")]
345#[derive(Eq, Hash, EqIgnoreSpan)]
346#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
347#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
348pub struct ImportNamedSpecifier {
349 pub span: Span,
350
351 pub local: Ident,
352
353 #[cfg_attr(feature = "serde-impl", serde(default))]
354 #[cfg_attr(
355 feature = "encoding-impl",
356 encoding(with = "cbor4ii::core::types::Maybe")
357 )]
358 pub imported: Option<ModuleExportName>,
359
360 #[cfg_attr(feature = "serde-impl", serde(default))]
361 pub is_type_only: bool,
362}
363
364#[ast_node]
365#[derive(Eq, Hash, Is, EqIgnoreSpan)]
366#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
367#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
368pub enum ExportSpecifier {
369 #[tag("ExportNamespaceSpecifier")]
370 Namespace(ExportNamespaceSpecifier),
371
372 #[tag("ExportDefaultSpecifier")]
373 Default(ExportDefaultSpecifier),
374
375 #[tag("ExportSpecifier")]
376 Named(ExportNamedSpecifier),
377}
378
379#[ast_node("ExportNamespaceSpecifier")]
381#[derive(Eq, Hash, EqIgnoreSpan)]
382#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
383#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
384pub struct ExportNamespaceSpecifier {
385 pub span: Span,
386
387 pub name: ModuleExportName,
388}
389
390#[ast_node("ExportDefaultSpecifier")]
392#[derive(Eq, Hash, EqIgnoreSpan)]
393#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
394#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
395pub struct ExportDefaultSpecifier {
396 #[span]
397 pub exported: Ident,
398}
399
400#[ast_node("ExportSpecifier")]
401#[derive(Eq, Hash, EqIgnoreSpan)]
402#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
403#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
404pub struct ExportNamedSpecifier {
405 pub span: Span,
406 pub orig: ModuleExportName,
408 #[cfg_attr(feature = "serde-impl", serde(default))]
410 #[cfg_attr(
411 feature = "encoding-impl",
412 encoding(with = "cbor4ii::core::types::Maybe")
413 )]
414 pub exported: Option<ModuleExportName>,
415 #[cfg_attr(feature = "serde-impl", serde(default))]
417 pub is_type_only: bool,
418}
419
420#[ast_node]
421#[derive(Eq, Hash, EqIgnoreSpan)]
422#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
423#[cfg_attr(feature = "shrink-to-fit", derive(shrink_to_fit::ShrinkToFit))]
424pub enum ModuleExportName {
426 #[tag("Identifier")]
427 Ident(Ident),
428
429 #[tag("StringLiteral")]
430 Str(Str),
431}
432
433bridge_from!(ModuleExportName, Ident, BindingIdent);
434bridge_from!(ModuleExportName, Ident, IdentName);
435
436impl ModuleExportName {
437 pub fn atom(&self) -> Cow<'_, Atom> {
445 match self {
446 ModuleExportName::Ident(i) => Cow::Borrowed(&i.sym),
447 ModuleExportName::Str(s) => match s.value.clone().try_into_atom() {
448 Ok(atom) => Cow::Owned(atom),
449 Err(original) => Cow::Owned(Atom::from(&*original.to_string_lossy())),
450 },
451 #[cfg(all(swc_ast_unknown, feature = "encoding-impl"))]
452 _ => swc_common::unknown!(),
453 }
454 }
455}