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