1use crate::expression::Expression;
4use crate::identifier::Identifier;
5use crate::span::Spanned;
6use crate::statement::Statement;
7
8pub type ModuleItem = Spanned<ModuleItemKind>;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum ModuleItemKind {
15 Statement(Statement),
18 Import(ImportDeclaration),
20 Export(ExportDeclaration),
22}
23
24impl std::fmt::Display for ModuleItemKind {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 Self::Statement(stmt) => write!(f, "{stmt}"),
28 Self::Import(decl) => write!(f, "{decl}"),
29 Self::Export(decl) => write!(f, "{decl}"),
30 }
31 }
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
36pub struct ImportDeclaration {
37 specifiers: Vec<ImportSpecifier>,
38 source: String,
39}
40
41impl ImportDeclaration {
42 #[must_use]
45 pub fn new(specifiers: Vec<ImportSpecifier>, source: impl Into<String>) -> Self {
46 Self {
47 specifiers,
48 source: source.into(),
49 }
50 }
51
52 #[must_use]
54 pub fn specifiers(&self) -> &[ImportSpecifier] {
55 &self.specifiers
56 }
57
58 #[must_use]
60 pub fn source(&self) -> &str {
61 &self.source
62 }
63}
64
65impl std::fmt::Display for ImportDeclaration {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 let specs = self
68 .specifiers
69 .iter()
70 .map(|s| format!("{s}"))
71 .collect::<Vec<_>>()
72 .join(", ");
73 write!(f, "import {specs} from {:?};", self.source)
74 }
75}
76
77#[derive(Debug, Clone, PartialEq, Eq)]
79pub enum ImportSpecifier {
80 Named {
83 imported: Identifier,
85 local: Identifier,
87 },
88 Default {
90 local: Identifier,
92 },
93 Namespace {
95 local: Identifier,
97 },
98}
99
100impl std::fmt::Display for ImportSpecifier {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 match self {
103 Self::Named { imported, local } => {
104 if imported == local {
105 write!(f, "{{ {imported} }}")
106 } else {
107 write!(f, "{{ {imported} as {local} }}")
108 }
109 }
110 Self::Default { local } => write!(f, "{local}"),
111 Self::Namespace { local } => write!(f, "* as {local}"),
112 }
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
118pub enum ExportDeclaration {
119 Named {
121 specifiers: Vec<ExportSpecifier>,
123 source: Option<String>,
125 },
126 Default {
128 declaration: ExportDefault,
130 },
131 Declaration {
133 declaration: Statement,
136 },
137 All {
139 exported: Option<Identifier>,
141 source: String,
143 },
144}
145
146impl std::fmt::Display for ExportDeclaration {
147 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148 match self {
149 Self::Named { specifiers, source } => {
150 write_export_named(f, specifiers, source.as_deref())
151 }
152 Self::Default { declaration } => write!(f, "export default {declaration};"),
153 Self::Declaration { declaration } => write!(f, "export {declaration}"),
154 Self::All { exported, source } => write_export_all(f, exported.as_ref(), source),
155 }
156 }
157}
158
159fn write_export_named(
160 f: &mut std::fmt::Formatter<'_>,
161 specifiers: &[ExportSpecifier],
162 source: Option<&str>,
163) -> std::fmt::Result {
164 let specs = specifiers
165 .iter()
166 .map(|s| format!("{s}"))
167 .collect::<Vec<_>>()
168 .join(", ");
169 match source {
170 Some(src) => write!(f, "export {{ {specs} }} from {src:?};"),
171 None => write!(f, "export {{ {specs} }};"),
172 }
173}
174
175fn write_export_all(
176 f: &mut std::fmt::Formatter<'_>,
177 exported: Option<&Identifier>,
178 source: &str,
179) -> std::fmt::Result {
180 match exported {
181 Some(name) => write!(f, "export * as {name} from {source:?};"),
182 None => write!(f, "export * from {source:?};"),
183 }
184}
185
186#[derive(Debug, Clone, PartialEq, Eq)]
188pub struct ExportSpecifier {
189 local: Identifier,
190 exported: Identifier,
191}
192
193impl ExportSpecifier {
194 #[must_use]
196 pub fn new(local: Identifier, exported: Identifier) -> Self {
197 Self { local, exported }
198 }
199
200 #[must_use]
202 pub fn local(&self) -> &Identifier {
203 &self.local
204 }
205
206 #[must_use]
209 pub fn exported(&self) -> &Identifier {
210 &self.exported
211 }
212}
213
214impl std::fmt::Display for ExportSpecifier {
215 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
216 if self.local == self.exported {
217 write!(f, "{}", self.local)
218 } else {
219 write!(f, "{} as {}", self.local, self.exported)
220 }
221 }
222}
223
224#[derive(Debug, Clone, PartialEq, Eq)]
226pub enum ExportDefault {
227 Expression(Expression),
229 Function(crate::function::Function),
231 Class(crate::class::Class),
233}
234
235impl std::fmt::Display for ExportDefault {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 match self {
238 Self::Expression(expr) => write!(f, "{expr}"),
239 Self::Function(func) => write!(f, "{func}"),
240 Self::Class(class) => write!(f, "{class}"),
241 }
242 }
243}