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