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