1use crate::{kw, LitStr, SolIdent, Spanned};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5 braced,
6 parse::{Parse, ParseStream},
7 punctuated::Punctuated,
8 token::Brace,
9 Result, Token,
10};
11
12#[derive(Clone)]
17pub struct ImportDirective {
18 pub import_token: kw::import,
19 pub path: ImportPath,
20 pub semi_token: Token![;],
21}
22
23impl fmt::Display for ImportDirective {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 write!(f, "import {};", self.path)
26 }
27}
28
29impl fmt::Debug for ImportDirective {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("ImportDirective").field("path", &self.path).finish()
32 }
33}
34
35impl Parse for ImportDirective {
36 fn parse(input: ParseStream<'_>) -> Result<Self> {
37 Ok(Self { import_token: input.parse()?, path: input.parse()?, semi_token: input.parse()? })
38 }
39}
40
41impl Spanned for ImportDirective {
42 fn span(&self) -> Span {
43 let span = self.import_token.span;
44 span.join(self.semi_token.span).unwrap_or(span)
45 }
46
47 fn set_span(&mut self, span: Span) {
48 self.import_token.span = span;
49 self.path.set_span(span);
50 self.semi_token.span = span;
51 }
52}
53
54#[derive(Clone, Debug)]
56pub enum ImportPath {
57 Plain(ImportPlain),
59 Aliases(ImportAliases),
61 Glob(ImportGlob),
63}
64
65impl fmt::Display for ImportPath {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 match self {
68 Self::Plain(p) => p.fmt(f),
69 Self::Aliases(p) => p.fmt(f),
70 Self::Glob(p) => p.fmt(f),
71 }
72 }
73}
74
75impl Parse for ImportPath {
76 fn parse(input: ParseStream<'_>) -> Result<Self> {
77 let lookahead = input.lookahead1();
78 if lookahead.peek(Token![*]) {
79 input.parse().map(Self::Glob)
80 } else if lookahead.peek(Brace) {
81 input.parse().map(Self::Aliases)
82 } else {
83 input.parse().map(Self::Plain)
84 }
85 }
86}
87
88impl Spanned for ImportPath {
89 fn span(&self) -> Span {
90 match self {
91 Self::Plain(p) => p.span(),
92 Self::Aliases(p) => p.span(),
93 Self::Glob(p) => p.span(),
94 }
95 }
96
97 fn set_span(&mut self, span: Span) {
98 match self {
99 Self::Plain(p) => p.set_span(span),
100 Self::Aliases(p) => p.set_span(span),
101 Self::Glob(p) => p.set_span(span),
102 }
103 }
104}
105
106impl ImportPath {
107 pub fn path(&self) -> &LitStr {
108 match self {
109 Self::Plain(ImportPlain { path, .. })
110 | Self::Aliases(ImportAliases { path, .. })
111 | Self::Glob(ImportGlob { path, .. }) => path,
112 }
113 }
114
115 pub fn path_mut(&mut self) -> &mut LitStr {
116 match self {
117 Self::Plain(ImportPlain { path, .. })
118 | Self::Aliases(ImportAliases { path, .. })
119 | Self::Glob(ImportGlob { path, .. }) => path,
120 }
121 }
122}
123
124#[derive(Clone)]
126pub struct ImportAlias {
127 pub as_token: Token![as],
128 pub alias: SolIdent,
129}
130
131impl fmt::Display for ImportAlias {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 write!(f, "as {}", self.alias)
134 }
135}
136
137impl fmt::Debug for ImportAlias {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 f.debug_tuple("Alias").field(&self.alias).finish()
140 }
141}
142
143impl Parse for ImportAlias {
144 fn parse(input: ParseStream<'_>) -> Result<Self> {
145 Ok(Self { as_token: input.parse()?, alias: input.parse()? })
146 }
147}
148
149impl Spanned for ImportAlias {
150 fn span(&self) -> Span {
151 let span = self.as_token.span;
152 span.join(self.alias.span()).unwrap_or(span)
153 }
154
155 fn set_span(&mut self, span: Span) {
156 self.as_token.span = span;
157 self.alias.set_span(span);
158 }
159}
160
161impl ImportAlias {
162 pub fn parse_opt(input: ParseStream<'_>) -> Result<Option<Self>> {
163 if input.peek(Token![as]) {
164 input.parse().map(Some)
165 } else {
166 Ok(None)
167 }
168 }
169}
170
171#[derive(Clone)]
173pub struct ImportPlain {
174 pub path: LitStr,
175 pub alias: Option<ImportAlias>,
176}
177
178impl fmt::Display for ImportPlain {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 write!(f, "{}", self.path)?;
181 if let Some(alias) = &self.alias {
182 write!(f, " {alias}")?;
183 }
184 Ok(())
185 }
186}
187
188impl fmt::Debug for ImportPlain {
189 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190 f.debug_struct("Plain").field("path", &self.path).field("alias", &self.alias).finish()
191 }
192}
193
194impl Parse for ImportPlain {
195 fn parse(input: ParseStream<'_>) -> Result<Self> {
196 Ok(Self { path: input.parse()?, alias: input.call(ImportAlias::parse_opt)? })
197 }
198}
199
200impl Spanned for ImportPlain {
201 fn span(&self) -> Span {
202 let span = self.path.span();
203 if let Some(alias) = &self.alias {
204 span.join(alias.span()).unwrap_or(span)
205 } else {
206 span
207 }
208 }
209
210 fn set_span(&mut self, span: Span) {
211 self.path.set_span(span);
212 if let Some(alias) = &mut self.alias {
213 alias.set_span(span);
214 }
215 }
216}
217
218#[derive(Clone)]
220pub struct ImportAliases {
221 pub brace_token: Brace,
222 pub imports: Punctuated<(SolIdent, Option<ImportAlias>), Token![,]>,
223 pub from_token: kw::from,
224 pub path: LitStr,
225}
226
227impl fmt::Display for ImportAliases {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 write!(f, "{{")?;
230 for (i, (ident, alias)) in self.imports.iter().enumerate() {
231 if i > 0 {
232 write!(f, ", ")?;
233 }
234 write!(f, "{ident}")?;
235 if let Some(alias) = alias {
236 write!(f, " {alias}")?;
237 }
238 }
239 write!(f, "}} from {}", self.path)
240 }
241}
242
243impl fmt::Debug for ImportAliases {
244 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245 f.debug_struct("Aliases").field("imports", &self.imports).field("path", &self.path).finish()
246 }
247}
248
249impl Parse for ImportAliases {
250 fn parse(input: ParseStream<'_>) -> Result<Self> {
251 let content;
252 Ok(Self {
253 brace_token: braced!(content in input),
254 imports: content.parse_terminated(
255 |c| Ok((c.parse()?, c.call(ImportAlias::parse_opt)?)),
256 Token![,],
257 )?,
258 from_token: input.parse()?,
259 path: input.parse()?,
260 })
261 }
262}
263
264impl Spanned for ImportAliases {
265 fn span(&self) -> Span {
266 let span = self.brace_token.span.join();
267 span.join(self.path.span()).unwrap_or(span)
268 }
269
270 fn set_span(&mut self, span: Span) {
271 self.brace_token = Brace(span);
272 self.from_token.span = span;
273 self.path.set_span(span);
274 }
275}
276
277#[derive(Clone)]
279pub struct ImportGlob {
280 pub star_token: Token![*],
281 pub alias: Option<ImportAlias>,
282 pub from_token: kw::from,
283 pub path: LitStr,
284}
285
286impl fmt::Display for ImportGlob {
287 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
288 write!(f, "*")?;
289 if let Some(alias) = &self.alias {
290 write!(f, " {alias}")?;
291 }
292 write!(f, " from {}", self.path)
293 }
294}
295
296impl fmt::Debug for ImportGlob {
297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298 f.debug_struct("Glob").field("alias", &self.alias).field("path", &self.path).finish()
299 }
300}
301
302impl Parse for ImportGlob {
303 fn parse(input: ParseStream<'_>) -> Result<Self> {
304 Ok(Self {
305 star_token: input.parse()?,
306 alias: input.call(ImportAlias::parse_opt)?,
307 from_token: input.parse()?,
308 path: input.parse()?,
309 })
310 }
311}
312
313impl Spanned for ImportGlob {
314 fn span(&self) -> Span {
315 let span = self.star_token.span;
316 span.join(self.path.span()).unwrap_or(span)
317 }
318
319 fn set_span(&mut self, span: Span) {
320 self.star_token.span = span;
321 self.alias.set_span(span);
322 self.from_token.span = span;
323 self.path.set_span(span);
324 }
325}