syn_solidity/attribute/
mod.rs

1use crate::{Expr, SolPath, Spanned, kw, utils::DebugPunctuated};
2use proc_macro2::Span;
3use std::{
4    fmt,
5    hash::{Hash, Hasher},
6};
7use syn::{
8    Result, Token, parenthesized,
9    parse::{Parse, ParseStream},
10    punctuated::Punctuated,
11    token::Paren,
12};
13
14mod function;
15pub use function::{FunctionAttribute, FunctionAttributes};
16
17mod variable;
18pub use variable::{VariableAttribute, VariableAttributes};
19
20kw_enum! {
21    /// A storage location.
22    pub enum Storage {
23        Memory(kw::memory),
24        Storage(kw::storage),
25        Calldata(kw::calldata),
26    }
27}
28
29kw_enum! {
30    /// A visibility attribute.
31    pub enum Visibility {
32        External(kw::external),
33        Public(kw::public),
34        Internal(kw::internal),
35        Private(kw::private),
36    }
37}
38
39kw_enum! {
40    /// A mutability attribute.
41    pub enum Mutability {
42        Pure(kw::pure),
43        View(kw::view),
44        Constant(kw::constant),
45        Payable(kw::payable),
46    }
47}
48
49/// The `override` attribute.
50#[derive(Clone, PartialEq, Eq, Hash)]
51pub struct Override {
52    pub override_token: Token![override],
53    pub paren_token: Option<Paren>,
54    pub paths: Punctuated<SolPath, Token![,]>,
55}
56
57impl fmt::Display for Override {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        f.write_str("override")?;
60        if self.paren_token.is_some() {
61            f.write_str("(")?;
62            for (i, path) in self.paths.iter().enumerate() {
63                if i > 0 {
64                    f.write_str(", ")?;
65                }
66                path.fmt(f)?;
67            }
68            f.write_str(")")?;
69        }
70        Ok(())
71    }
72}
73
74impl fmt::Debug for Override {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        f.debug_tuple("Override").field(DebugPunctuated::new(&self.paths)).finish()
77    }
78}
79
80impl Parse for Override {
81    fn parse(input: ParseStream<'_>) -> Result<Self> {
82        let override_token = input.parse()?;
83        let this = if input.peek(Paren) {
84            let content;
85            Self {
86                override_token,
87                paren_token: Some(parenthesized!(content in input)),
88                paths: content.parse_terminated(SolPath::parse, Token![,])?,
89            }
90        } else {
91            Self { override_token, paren_token: None, paths: Default::default() }
92        };
93        Ok(this)
94    }
95}
96
97impl Spanned for Override {
98    fn span(&self) -> Span {
99        let span = self.override_token.span;
100        self.paren_token.and_then(|paren_token| span.join(paren_token.span.join())).unwrap_or(span)
101    }
102
103    fn set_span(&mut self, span: Span) {
104        self.override_token.span = span;
105        if let Some(paren_token) = &mut self.paren_token {
106            *paren_token = Paren(span);
107        }
108    }
109}
110
111/// A modifier invocation, or an inheritance specifier.
112#[derive(Clone)]
113pub struct Modifier {
114    pub name: SolPath,
115    pub paren_token: Option<Paren>,
116    pub arguments: Punctuated<Expr, Token![,]>,
117}
118
119impl PartialEq for Modifier {
120    fn eq(&self, other: &Self) -> bool {
121        self.name == other.name
122    }
123}
124
125impl Eq for Modifier {}
126
127impl Hash for Modifier {
128    fn hash<H: Hasher>(&self, state: &mut H) {
129        self.name.hash(state);
130    }
131}
132
133impl fmt::Display for Modifier {
134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135        self.name.fmt(f)?;
136        if self.paren_token.is_some() {
137            f.write_str("(")?;
138            for (i, _arg) in self.arguments.iter().enumerate() {
139                if i > 0 {
140                    f.write_str(", ")?;
141                }
142                // TODO: impl fmt::Display for Expr
143                f.write_str("<expr>")?;
144            }
145            f.write_str(")")?;
146        }
147        Ok(())
148    }
149}
150
151impl fmt::Debug for Modifier {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153        f.debug_struct("Modifier")
154            .field("name", &self.name)
155            .field("arguments", DebugPunctuated::new(&self.arguments))
156            .finish()
157    }
158}
159
160impl Parse for Modifier {
161    fn parse(input: ParseStream<'_>) -> Result<Self> {
162        let name = input.parse()?;
163        let this = if input.peek(Paren) {
164            let content;
165            let paren_token = parenthesized!(content in input);
166            let arguments = content.parse_terminated(Expr::parse, Token![,])?;
167            Self { name, paren_token: Some(paren_token), arguments }
168        } else {
169            Self { name, paren_token: None, arguments: Punctuated::new() }
170        };
171        Ok(this)
172    }
173}
174
175impl Spanned for Modifier {
176    fn span(&self) -> Span {
177        let span = self.name.span();
178        self.paren_token.and_then(|paren_token| span.join(paren_token.span.join())).unwrap_or(span)
179    }
180
181    fn set_span(&mut self, span: Span) {
182        self.name.set_span(span);
183        if let Some(paren_token) = &mut self.paren_token {
184            *paren_token = Paren(span);
185        }
186    }
187}