syn_solidity/attribute/
variable.rs1use crate::{kw, Override, SolPath, Spanned, Visibility};
2use proc_macro2::Span;
3use std::{
4 fmt,
5 hash::{Hash, Hasher},
6 mem,
7};
8use syn::{
9 parse::{Parse, ParseStream},
10 Error, Result, Token,
11};
12
13#[derive(Clone, Debug)]
15pub struct VariableAttributes(pub Vec<VariableAttribute>);
16
17impl fmt::Display for VariableAttributes {
18 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19 for (i, attr) in self.0.iter().enumerate() {
20 if i > 0 {
21 f.write_str(" ")?;
22 }
23 write!(f, "{attr}")?;
24 }
25 Ok(())
26 }
27}
28
29impl Parse for VariableAttributes {
30 fn parse(input: ParseStream<'_>) -> Result<Self> {
31 let mut attributes = Vec::new();
32 while let Ok(attribute) = input.parse::<VariableAttribute>() {
33 let error = |prev: &VariableAttribute| {
34 let mut e = Error::new(attribute.span(), "duplicate attribute");
35 e.combine(Error::new(prev.span(), "previous declaration is here"));
36 e
37 };
38
39 match attribute {
41 VariableAttribute::Constant(_) => {
42 if let Some(prev) =
43 attributes.iter().find(|a| matches!(a, VariableAttribute::Immutable(_)))
44 {
45 return Err(error(prev));
46 }
47 }
48 VariableAttribute::Immutable(_) => {
49 if let Some(prev) =
50 attributes.iter().find(|a| matches!(a, VariableAttribute::Constant(_)))
51 {
52 return Err(error(prev));
53 }
54 }
55 _ => {}
56 }
57
58 if let Some(prev) = attributes.iter().find(|a| **a == attribute) {
59 return Err(error(prev));
60 }
61 attributes.push(attribute);
62 }
63 Ok(Self(attributes))
64 }
65}
66
67impl Spanned for VariableAttributes {
68 fn span(&self) -> Span {
69 self.0.span()
70 }
71
72 fn set_span(&mut self, span: Span) {
73 self.0.set_span(span);
74 }
75}
76
77impl VariableAttributes {
78 pub fn visibility(&self) -> Option<Visibility> {
79 self.0.iter().find_map(VariableAttribute::visibility)
80 }
81
82 pub fn has_external(&self) -> bool {
83 self.0.iter().any(VariableAttribute::is_external)
84 }
85
86 pub fn has_internal(&self) -> bool {
87 self.0.iter().any(VariableAttribute::is_internal)
88 }
89
90 pub fn has_private(&self) -> bool {
91 self.0.iter().any(VariableAttribute::is_private)
92 }
93
94 pub fn has_public(&self) -> bool {
95 self.0.iter().any(VariableAttribute::is_public)
96 }
97
98 pub fn has_constant(&self) -> bool {
99 self.0.iter().any(VariableAttribute::is_constant)
100 }
101
102 pub fn has_immutable(&self) -> bool {
103 self.0.iter().any(VariableAttribute::is_immutable)
104 }
105
106 pub fn has_override(&self, path: Option<&SolPath>) -> bool {
107 self.0.iter().any(|attr| attr.is_override(path))
108 }
109}
110
111#[derive(Clone)]
113pub enum VariableAttribute {
114 Visibility(Visibility),
116 Constant(kw::constant),
118 Immutable(kw::immutable),
120 Override(Override),
122}
123
124impl fmt::Display for VariableAttribute {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 match self {
127 Self::Visibility(v) => v.fmt(f),
128 Self::Constant(_) => f.write_str("constant"),
129 Self::Immutable(_) => f.write_str("immutable"),
130 Self::Override(o) => o.fmt(f),
131 }
132 }
133}
134
135impl fmt::Debug for VariableAttribute {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 match self {
138 Self::Visibility(v) => v.fmt(f),
139 Self::Constant(_) => f.write_str("Constant"),
140 Self::Immutable(_) => f.write_str("Immutable"),
141 Self::Override(o) => o.fmt(f),
142 }
143 }
144}
145
146impl PartialEq for VariableAttribute {
147 fn eq(&self, other: &Self) -> bool {
148 mem::discriminant(self) == mem::discriminant(other)
149 }
150}
151
152impl Eq for VariableAttribute {}
153
154impl Hash for VariableAttribute {
155 fn hash<H: Hasher>(&self, state: &mut H) {
156 mem::discriminant(self).hash(state);
157 }
158}
159
160impl Parse for VariableAttribute {
161 fn parse(input: ParseStream<'_>) -> Result<Self> {
162 let lookahead = input.lookahead1();
163 if Visibility::peek(&lookahead) {
164 input.parse().map(Self::Visibility)
165 } else if lookahead.peek(kw::constant) {
166 input.parse().map(Self::Constant)
167 } else if lookahead.peek(Token![override]) {
168 input.parse().map(Self::Override)
169 } else if lookahead.peek(kw::immutable) {
170 input.parse().map(Self::Immutable)
171 } else {
172 Err(lookahead.error())
173 }
174 }
175}
176
177impl Spanned for VariableAttribute {
178 fn span(&self) -> Span {
179 match self {
180 Self::Visibility(v) => v.span(),
181 Self::Constant(c) => c.span,
182 Self::Override(o) => o.span(),
183 Self::Immutable(i) => i.span,
184 }
185 }
186
187 fn set_span(&mut self, span: Span) {
188 match self {
189 Self::Visibility(v) => v.set_span(span),
190 Self::Constant(c) => c.span = span,
191 Self::Override(o) => o.set_span(span),
192 Self::Immutable(i) => i.span = span,
193 }
194 }
195}
196
197impl VariableAttribute {
198 #[inline]
199 pub const fn visibility(&self) -> Option<Visibility> {
200 match self {
201 Self::Visibility(v) => Some(*v),
202 _ => None,
203 }
204 }
205
206 #[inline]
207 pub const fn r#override(&self) -> Option<&Override> {
208 match self {
209 Self::Override(o) => Some(o),
210 _ => None,
211 }
212 }
213
214 #[inline]
215 pub const fn is_external(&self) -> bool {
216 matches!(self, Self::Visibility(Visibility::External(_)))
217 }
218
219 #[inline]
220 pub const fn is_public(&self) -> bool {
221 matches!(self, Self::Visibility(Visibility::Public(_)))
222 }
223
224 #[inline]
225 pub const fn is_internal(&self) -> bool {
226 matches!(self, Self::Visibility(Visibility::Internal(_)))
227 }
228
229 #[inline]
230 pub const fn is_private(&self) -> bool {
231 matches!(self, Self::Visibility(Visibility::Private(_)))
232 }
233
234 #[inline]
235 pub const fn is_constant(&self) -> bool {
236 matches!(self, Self::Constant(_))
237 }
238
239 #[inline]
240 pub const fn is_immutable(&self) -> bool {
241 matches!(self, Self::Immutable(_))
242 }
243
244 #[inline]
245 pub fn is_override(&self, path: Option<&SolPath>) -> bool {
246 self.r#override().is_some_and(|o| match path {
247 Some(path) => o.paths.iter().any(|p| p == path),
248 None => true,
249 })
250 }
251}