syn_solidity/item/
using.rs

1use crate::{kw, SolPath, Spanned, Type};
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/// A `using` directive: `using { A, B.mul as * } for uint256 global;`.
13///
14/// Solidity reference:
15/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.usingDirective>
16#[derive(Clone)]
17pub struct UsingDirective {
18    pub using_token: kw::using,
19    pub list: UsingList,
20    pub for_token: Token![for],
21    pub ty: UsingType,
22    pub global_token: Option<kw::global>,
23    pub semi_token: Token![;],
24}
25
26impl fmt::Display for UsingDirective {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        write!(
29            f,
30            "using {} for {}{};",
31            self.list,
32            self.ty,
33            if self.global_token.is_some() { " global" } else { "" }
34        )
35    }
36}
37
38impl fmt::Debug for UsingDirective {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        f.debug_struct("UsingDirective")
41            .field("list", &self.list)
42            .field("ty", &self.ty)
43            .field("global", &self.global_token.is_some())
44            .finish()
45    }
46}
47
48impl Parse for UsingDirective {
49    fn parse(input: ParseStream<'_>) -> Result<Self> {
50        Ok(Self {
51            using_token: input.parse()?,
52            list: input.parse()?,
53            for_token: input.parse()?,
54            ty: input.parse()?,
55            global_token: input.parse()?,
56            semi_token: input.parse()?,
57        })
58    }
59}
60
61impl Spanned for UsingDirective {
62    fn span(&self) -> Span {
63        let span = self.using_token.span;
64        span.join(self.semi_token.span).unwrap_or(span)
65    }
66
67    fn set_span(&mut self, span: Span) {
68        self.using_token.span = span;
69        self.semi_token.span = span;
70    }
71}
72
73#[derive(Clone, Debug)]
74pub enum UsingList {
75    Single(SolPath),
76    Multiple(Brace, Punctuated<UsingListItem, Token![,]>),
77}
78
79impl fmt::Display for UsingList {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        match self {
82            Self::Single(path) => path.fmt(f),
83            Self::Multiple(_, list) => {
84                f.write_str("{")?;
85                for (i, item) in list.iter().enumerate() {
86                    if i > 0 {
87                        f.write_str(", ")?;
88                    }
89                    item.fmt(f)?;
90                }
91                f.write_str("}")
92            }
93        }
94    }
95}
96
97impl Parse for UsingList {
98    fn parse(input: ParseStream<'_>) -> Result<Self> {
99        if input.peek(Brace) {
100            let content;
101            Ok(Self::Multiple(
102                braced!(content in input),
103                content.parse_terminated(UsingListItem::parse, Token![,])?,
104            ))
105        } else {
106            input.parse().map(Self::Single)
107        }
108    }
109}
110
111impl Spanned for UsingList {
112    fn span(&self) -> Span {
113        match self {
114            Self::Single(path) => path.span(),
115            Self::Multiple(brace, list) => {
116                let span = brace.span.join();
117                span.join(list.span()).unwrap_or(span)
118            }
119        }
120    }
121
122    fn set_span(&mut self, span: Span) {
123        match self {
124            Self::Single(path) => path.set_span(span),
125            Self::Multiple(brace, list) => {
126                *brace = Brace(span);
127                list.set_span(span);
128            }
129        }
130    }
131}
132
133#[derive(Clone, Debug)]
134pub struct UsingListItem {
135    pub path: SolPath,
136    pub op: Option<(Token![as], UserDefinableOperator)>,
137}
138
139impl fmt::Display for UsingListItem {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        self.path.fmt(f)?;
142        if let Some((_, op)) = &self.op {
143            write!(f, " as {op}")?;
144        }
145        Ok(())
146    }
147}
148
149impl Parse for UsingListItem {
150    fn parse(input: ParseStream<'_>) -> Result<Self> {
151        Ok(Self {
152            path: input.parse()?,
153            op: if input.peek(Token![as]) { Some((input.parse()?, input.parse()?)) } else { None },
154        })
155    }
156}
157
158impl Spanned for UsingListItem {
159    fn span(&self) -> Span {
160        self.path.span()
161    }
162
163    fn set_span(&mut self, span: Span) {
164        self.path.set_span(span);
165    }
166}
167
168#[derive(Clone, Debug)]
169pub enum UsingType {
170    Star(Token![*]),
171    Type(Type),
172}
173
174impl fmt::Display for UsingType {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        match self {
177            Self::Star(_) => f.write_str("*"),
178            Self::Type(ty) => ty.fmt(f),
179        }
180    }
181}
182
183impl Parse for UsingType {
184    fn parse(input: ParseStream<'_>) -> Result<Self> {
185        if input.peek(Token![*]) {
186            input.parse().map(Self::Star)
187        } else {
188            input.parse().map(Self::Type)
189        }
190    }
191}
192
193impl Spanned for UsingType {
194    fn span(&self) -> Span {
195        match self {
196            Self::Star(star) => star.span,
197            Self::Type(ty) => ty.span(),
198        }
199    }
200
201    fn set_span(&mut self, span: Span) {
202        match self {
203            Self::Star(star) => star.span = span,
204            Self::Type(ty) => ty.set_span(span),
205        }
206    }
207}
208
209op_enum! {
210    /// A user-definable operator: `+`, `*`, `|`, etc.
211    ///
212    /// Solidity reference:
213    /// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.userDefinableOperator>
214    pub enum UserDefinableOperator {
215        BitAnd(&),
216        BitNot(~),
217        BitOr(|),
218        BitXor(^),
219        Add(+),
220        Div(/),
221        Rem(%),
222        Mul(*),
223        Sub(-),
224        Eq(==),
225        Ge(>=),
226        Gt(>),
227        Le(<=),
228        Lt(<),
229        Ne(!=),
230    }
231}