1use crate::{Expr, SolIdent, Spanned, Storage, Type, VariableAttributes};
2use proc_macro2::Span;
3use std::fmt::{self, Write};
4use syn::{
5 Attribute, Ident, Result, Token,
6 ext::IdentExt,
7 parse::{Parse, ParseStream},
8};
9
10mod list;
11pub use list::{FieldList, ParameterList, Parameters};
12
13#[derive(Clone, Debug, PartialEq, Eq, Hash)]
15pub struct VariableDeclaration {
16 pub attrs: Vec<Attribute>,
18 pub ty: Type,
20 pub storage: Option<Storage>,
22 pub name: Option<SolIdent>,
25}
26
27impl fmt::Display for VariableDeclaration {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 self.ty.fmt(f)?;
30 if let Some(storage) = &self.storage {
31 f.write_char(' ')?;
32 storage.fmt(f)?;
33 }
34 if let Some(name) = &self.name {
35 f.write_char(' ')?;
36 name.fmt(f)?;
37 }
38 Ok(())
39 }
40}
41
42impl Parse for VariableDeclaration {
43 fn parse(input: ParseStream<'_>) -> Result<Self> {
44 Self::_parse(input, false)
45 }
46}
47
48impl Spanned for VariableDeclaration {
49 fn span(&self) -> Span {
50 let span = self.ty.span();
51 match (&self.storage, &self.name) {
52 (Some(storage), None) => span.join(storage.span()),
53 (_, Some(name)) => span.join(name.span()),
54 (None, None) => Some(span),
55 }
56 .unwrap_or(span)
57 }
58
59 fn set_span(&mut self, span: Span) {
60 self.ty.set_span(span);
61 if let Some(storage) = &mut self.storage {
62 storage.set_span(span);
63 }
64 if let Some(name) = &mut self.name {
65 name.set_span(span);
66 }
67 }
68}
69
70impl VariableDeclaration {
71 pub const fn new(ty: Type) -> Self {
72 Self::new_with(ty, None, None)
73 }
74
75 pub const fn new_with(ty: Type, storage: Option<Storage>, name: Option<SolIdent>) -> Self {
76 Self { attrs: Vec::new(), ty, storage, name }
77 }
78
79 pub fn fmt_eip712(&self, f: &mut impl Write) -> fmt::Result {
81 fn fmt_type_eip712(ty: &crate::Type, f: &mut impl Write) -> fmt::Result {
83 match ty {
84 crate::Type::Custom(path) => {
85 write!(f, "{}", path.last())
86 }
87
88 crate::Type::Array(array) => {
89 fmt_type_eip712(&array.ty, f)?;
90 write!(f, "[")?;
91 if let Some(s) = array.size_lit() {
92 write!(f, "{}", s.base10_digits())?;
93 }
94 write!(f, "]")
95 }
96
97 _ => write!(f, "{ty}"),
98 }
99 }
100
101 fmt_type_eip712(&self.ty, f)?;
102 if let Some(name) = &self.name {
103 write!(f, " {name}")?;
104 }
105 Ok(())
106 }
107
108 pub fn parse_with_name(input: ParseStream<'_>) -> Result<Self> {
109 Self::_parse(input, true)
110 }
111
112 fn _parse(input: ParseStream<'_>, require_name: bool) -> Result<Self> {
113 Ok(Self {
114 attrs: input.call(Attribute::parse_outer)?,
115 ty: input.parse()?,
116 storage: input.call(Storage::parse_opt)?,
117 name: if require_name || input.peek(Ident::peek_any) {
118 Some(input.parse()?)
119 } else {
120 None
121 },
122 })
123 }
124}
125
126#[derive(Clone)]
127pub struct VariableDefinition {
128 pub attrs: Vec<Attribute>,
129 pub ty: Type,
130 pub attributes: VariableAttributes,
131 pub name: SolIdent,
132 pub initializer: Option<(Token![=], Expr)>,
133 pub semi_token: Token![;],
134}
135
136impl fmt::Display for VariableDefinition {
137 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
138 write!(f, "{} {} {}", self.ty, self.attributes, self.name)?;
139 if let Some((_, _expr)) = &self.initializer {
140 write!(f, " = <expr>")?;
142 }
143 f.write_str(";")
144 }
145}
146
147impl fmt::Debug for VariableDefinition {
148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149 f.debug_struct("VariableDefinition")
150 .field("ty", &self.ty)
151 .field("attributes", &self.attributes)
152 .field("name", &self.name)
153 .field("initializer", &self.initializer)
154 .finish()
155 }
156}
157
158impl Parse for VariableDefinition {
159 fn parse(input: ParseStream<'_>) -> Result<Self> {
160 Ok(Self {
161 attrs: Attribute::parse_outer(input)?,
162 ty: input.parse()?,
163 attributes: input.parse()?,
164 name: input.parse()?,
165 initializer: if input.peek(Token![=]) {
166 Some((input.parse()?, input.parse()?))
167 } else {
168 None
169 },
170 semi_token: input.parse()?,
171 })
172 }
173}
174
175impl Spanned for VariableDefinition {
176 fn span(&self) -> Span {
177 let span = self.ty.span();
178 span.join(self.semi_token.span).unwrap_or(span)
179 }
180
181 fn set_span(&mut self, span: Span) {
182 self.ty.set_span(span);
183 self.semi_token.span = span;
184 }
185}
186
187impl VariableDefinition {
188 pub fn as_declaration(&self) -> VariableDeclaration {
189 VariableDeclaration {
190 attrs: Vec::new(),
191 ty: self.ty.clone(),
192 storage: None,
193 name: Some(self.name.clone()),
194 }
195 }
196}