syn_solidity/attribute/
function.rs

1use crate::{kw, Modifier, Mutability, Override, SolPath, Spanned, VariableAttribute, Visibility};
2use proc_macro2::Span;
3use std::{
4    fmt,
5    ops::{Deref, DerefMut},
6};
7use syn::{
8    ext::IdentExt,
9    parse::{Parse, ParseStream},
10    token::Brace,
11    Error, Ident, Result, Token,
12};
13
14/// A list of unique function attributes. Used in
15/// [ItemFunction][crate::ItemFunction].
16#[derive(Clone, Default, PartialEq, Eq)]
17pub struct FunctionAttributes(pub Vec<FunctionAttribute>);
18
19impl fmt::Display for FunctionAttributes {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        for (i, attr) in self.0.iter().enumerate() {
22            if i > 0 {
23                f.write_str(" ")?;
24            }
25            write!(f, "{attr}")?;
26        }
27        Ok(())
28    }
29}
30
31impl fmt::Debug for FunctionAttributes {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        self.0.fmt(f)
34    }
35}
36
37impl Deref for FunctionAttributes {
38    type Target = Vec<FunctionAttribute>;
39
40    fn deref(&self) -> &Self::Target {
41        &self.0
42    }
43}
44
45impl DerefMut for FunctionAttributes {
46    fn deref_mut(&mut self) -> &mut Self::Target {
47        &mut self.0
48    }
49}
50
51impl Parse for FunctionAttributes {
52    fn parse(input: ParseStream<'_>) -> Result<Self> {
53        let mut attributes = Vec::<FunctionAttribute>::new();
54        while !input.is_empty() && !input.peek(kw::returns) && input.peek(Ident::peek_any) {
55            let attr: FunctionAttribute = input.parse()?;
56            if matches!(
57                attr,
58                FunctionAttribute::Visibility(_)
59                    | FunctionAttribute::Mutability(_)
60                    | FunctionAttribute::Virtual(_)
61            ) {
62                if let Some(prev) = attributes.iter().find(|a| **a == attr) {
63                    let mut e = Error::new(attr.span(), "duplicate attribute");
64                    e.combine(Error::new(prev.span(), "previous declaration is here"));
65                    return Err(e);
66                }
67            }
68            attributes.push(attr);
69        }
70        Ok(Self(attributes))
71    }
72}
73
74impl Spanned for FunctionAttributes {
75    fn span(&self) -> Span {
76        self.0.span()
77    }
78
79    fn set_span(&mut self, span: Span) {
80        self.0.set_span(span);
81    }
82}
83
84impl FunctionAttributes {
85    #[inline]
86    pub fn new() -> Self {
87        Self(Vec::new())
88    }
89
90    pub fn visibility(&self) -> Option<Visibility> {
91        self.0.iter().find_map(FunctionAttribute::visibility)
92    }
93
94    pub fn mutability(&self) -> Option<Mutability> {
95        self.0.iter().find_map(FunctionAttribute::mutability)
96    }
97
98    pub fn r#override(&self) -> Option<&Override> {
99        self.0.iter().find_map(FunctionAttribute::r#override)
100    }
101
102    pub fn modifier(&self) -> Option<&Modifier> {
103        self.0.iter().find_map(FunctionAttribute::modifier)
104    }
105
106    pub fn has_external(&self) -> bool {
107        self.0.iter().any(FunctionAttribute::is_external)
108    }
109
110    pub fn has_internal(&self) -> bool {
111        self.0.iter().any(FunctionAttribute::is_internal)
112    }
113
114    pub fn has_private(&self) -> bool {
115        self.0.iter().any(FunctionAttribute::is_private)
116    }
117
118    pub fn has_public(&self) -> bool {
119        self.0.iter().any(FunctionAttribute::is_public)
120    }
121
122    pub fn has_virtual(&self) -> bool {
123        self.0.iter().any(FunctionAttribute::is_virtual)
124    }
125
126    pub fn has_override(&self, path: Option<&SolPath>) -> bool {
127        self.0.iter().any(|attr| attr.is_override(path))
128    }
129
130    pub fn has_modifier(&self, path: Option<&SolPath>) -> bool {
131        self.0.iter().any(|attr| attr.is_modifier(path))
132    }
133}
134
135/// A function attribute.
136#[derive(Clone, PartialEq, Eq, Hash)]
137pub enum FunctionAttribute {
138    /// A [Visibility] attribute.
139    Visibility(Visibility),
140    /// A [Mutability] attribute.
141    Mutability(Mutability),
142    /// A [Modifier] attribute.
143    Modifier(Modifier),
144    /// `virtual`
145    Virtual(Token![virtual]),
146    /// An [Override] attribute.
147    Override(Override),
148}
149
150impl fmt::Display for FunctionAttribute {
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        match self {
153            Self::Visibility(visibility) => visibility.fmt(f),
154            Self::Mutability(mutability) => mutability.fmt(f),
155            Self::Virtual(_) => f.write_str("virtual"),
156            Self::Override(o) => o.fmt(f),
157            Self::Modifier(modifier) => modifier.fmt(f),
158        }
159    }
160}
161
162impl fmt::Debug for FunctionAttribute {
163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        match self {
165            Self::Visibility(visibility) => f.debug_tuple("Visibility").field(visibility).finish(),
166            Self::Mutability(mutability) => f.debug_tuple("Mutability").field(mutability).finish(),
167            Self::Virtual(_) => f.write_str("Virtual"),
168            Self::Override(o) => o.fmt(f),
169            Self::Modifier(modifier) => modifier.fmt(f),
170        }
171    }
172}
173
174impl Parse for FunctionAttribute {
175    fn parse(input: ParseStream<'_>) -> Result<Self> {
176        let lookahead = input.lookahead1();
177        if Visibility::peek(&lookahead) {
178            input.parse().map(Self::Visibility)
179        } else if Mutability::peek(&lookahead) {
180            input.parse().map(Self::Mutability)
181        } else if lookahead.peek(Token![virtual]) {
182            input.parse().map(Self::Virtual)
183        } else if lookahead.peek(Token![override]) {
184            input.parse().map(Self::Override)
185        } else if !input.peek(kw::returns) && lookahead.peek(Ident::peek_any) {
186            input.parse().map(Self::Modifier)
187        } else if input.peek(Brace) {
188            // special case for function with implementation
189            Err(input.error("functions cannot have an implementation"))
190        } else {
191            Err(lookahead.error())
192        }
193    }
194}
195
196impl From<VariableAttribute> for FunctionAttribute {
197    /// Converts a variable attribute to its corresponding function attribute.
198    ///
199    /// - `constant` -> `pure`
200    /// - `immutable` -> `view`
201    fn from(value: VariableAttribute) -> Self {
202        match value {
203            VariableAttribute::Visibility(v) => Self::Visibility(v),
204            VariableAttribute::Constant(c) => Self::Mutability(Mutability::new_pure(c.span)),
205            VariableAttribute::Immutable(i) => Self::Mutability(Mutability::new_view(i.span)),
206            VariableAttribute::Override(o) => Self::Override(o),
207        }
208    }
209}
210
211impl Spanned for FunctionAttribute {
212    fn span(&self) -> Span {
213        match self {
214            Self::Visibility(v) => v.span(),
215            Self::Mutability(m) => m.span(),
216            Self::Virtual(v) => v.span,
217            Self::Override(o) => o.span(),
218            Self::Modifier(m) => m.span(),
219        }
220    }
221
222    fn set_span(&mut self, span: Span) {
223        match self {
224            Self::Visibility(v) => v.set_span(span),
225            Self::Mutability(m) => m.set_span(span),
226            Self::Virtual(v) => v.span = span,
227            Self::Override(o) => o.set_span(span),
228            Self::Modifier(m) => m.set_span(span),
229        }
230    }
231}
232
233impl FunctionAttribute {
234    #[inline]
235    pub const fn visibility(&self) -> Option<Visibility> {
236        match self {
237            Self::Visibility(v) => Some(*v),
238            _ => None,
239        }
240    }
241
242    #[inline]
243    pub const fn mutability(&self) -> Option<Mutability> {
244        match self {
245            Self::Mutability(m) => Some(*m),
246            _ => None,
247        }
248    }
249
250    #[inline]
251    pub const fn r#override(&self) -> Option<&Override> {
252        match self {
253            Self::Override(o) => Some(o),
254            _ => None,
255        }
256    }
257
258    #[inline]
259    pub const fn modifier(&self) -> Option<&Modifier> {
260        match self {
261            Self::Modifier(m) => Some(m),
262            _ => None,
263        }
264    }
265
266    #[inline]
267    pub const fn is_external(&self) -> bool {
268        matches!(self, Self::Visibility(Visibility::External(_)))
269    }
270
271    #[inline]
272    pub const fn is_public(&self) -> bool {
273        matches!(self, Self::Visibility(Visibility::Public(_)))
274    }
275
276    #[inline]
277    pub const fn is_internal(&self) -> bool {
278        matches!(self, Self::Visibility(Visibility::Internal(_)))
279    }
280
281    #[inline]
282    pub const fn is_private(&self) -> bool {
283        matches!(self, Self::Visibility(Visibility::Private(_)))
284    }
285
286    #[inline]
287    pub const fn is_virtual(&self) -> bool {
288        matches!(self, Self::Virtual(_))
289    }
290
291    #[inline]
292    pub fn is_override(&self, path: Option<&SolPath>) -> bool {
293        self.r#override().is_some_and(|o| match path {
294            Some(path) => o.paths.iter().any(|p| p == path),
295            None => true,
296        })
297    }
298
299    #[inline]
300    pub fn is_modifier(&self, path: Option<&SolPath>) -> bool {
301        self.modifier().is_some_and(|m| match path {
302            Some(path) => m.name == *path,
303            None => true,
304        })
305    }
306}