syn_solidity/attribute/
mod.rs

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