syn_solidity/item/
using.rs

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