1use crate::{kw, variable::VariableDefinition, SolIdent, Spanned};
2use proc_macro2::Span;
3use std::fmt;
4use syn::{
5 parse::{Parse, ParseStream},
6 Attribute, Result, Token,
7};
8
9mod contract;
10pub use contract::{ContractKind, Inheritance, ItemContract};
11
12mod r#enum;
13pub use r#enum::{ItemEnum, Variant};
14
15mod error;
16pub use error::ItemError;
17
18mod event;
19pub use event::{EventParameter, ItemEvent};
20
21mod function;
22pub use function::{FunctionBody, FunctionKind, ItemFunction, Returns};
23
24mod import;
25pub use import::{
26 ImportAlias, ImportAliases, ImportDirective, ImportGlob, ImportPath, ImportPlain,
27};
28
29mod pragma;
30pub use pragma::{PragmaDirective, PragmaTokens};
31
32mod r#struct;
33pub use r#struct::ItemStruct;
34
35mod udt;
36pub use udt::ItemUdt;
37
38mod using;
39pub use using::{UserDefinableOperator, UsingDirective, UsingList, UsingListItem, UsingType};
40
41#[derive(Clone)]
45pub enum Item {
46 Contract(ItemContract),
49
50 Enum(ItemEnum),
52
53 Error(ItemError),
55
56 Event(ItemEvent),
59
60 Function(ItemFunction),
63
64 Import(ImportDirective),
66
67 Pragma(PragmaDirective),
69
70 Struct(ItemStruct),
72
73 Udt(ItemUdt),
75
76 Using(UsingDirective),
78
79 Variable(VariableDefinition),
81}
82
83impl fmt::Display for Item {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 match self {
86 Self::Contract(item) => item.fmt(f),
87 Self::Enum(item) => item.fmt(f),
88 Self::Error(item) => item.fmt(f),
89 Self::Event(item) => item.fmt(f),
90 Self::Function(item) => item.fmt(f),
91 Self::Import(item) => item.fmt(f),
92 Self::Pragma(item) => item.fmt(f),
93 Self::Struct(item) => item.fmt(f),
94 Self::Udt(item) => item.fmt(f),
95 Self::Using(item) => item.fmt(f),
96 Self::Variable(item) => item.fmt(f),
97 }
98 }
99}
100
101impl fmt::Debug for Item {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 f.write_str("Item::")?;
104 match self {
105 Self::Contract(item) => item.fmt(f),
106 Self::Enum(item) => item.fmt(f),
107 Self::Error(item) => item.fmt(f),
108 Self::Event(item) => item.fmt(f),
109 Self::Function(item) => item.fmt(f),
110 Self::Import(item) => item.fmt(f),
111 Self::Pragma(item) => item.fmt(f),
112 Self::Struct(item) => item.fmt(f),
113 Self::Udt(item) => item.fmt(f),
114 Self::Using(item) => item.fmt(f),
115 Self::Variable(item) => item.fmt(f),
116 }
117 }
118}
119
120impl Parse for Item {
121 fn parse(input: ParseStream<'_>) -> Result<Self> {
122 let mut attrs = input.call(Attribute::parse_outer)?;
123
124 let lookahead = input.lookahead1();
125 let mut item = if FunctionKind::peek(&lookahead) {
126 input.parse().map(Self::Function)
127 } else if lookahead.peek(Token![struct]) {
128 input.parse().map(Self::Struct)
129 } else if lookahead.peek(kw::event) {
130 input.parse().map(Self::Event)
131 } else if lookahead.peek(kw::error) {
132 input.parse().map(Self::Error)
133 } else if ContractKind::peek(&lookahead) {
134 input.parse().map(Self::Contract)
135 } else if lookahead.peek(Token![enum]) {
136 input.parse().map(Self::Enum)
137 } else if lookahead.peek(Token![type]) {
138 input.parse().map(Self::Udt)
139 } else if lookahead.peek(kw::pragma) {
140 input.parse().map(Self::Pragma)
141 } else if lookahead.peek(kw::import) {
142 input.parse().map(Self::Import)
143 } else if lookahead.peek(kw::using) {
144 input.parse().map(Self::Using)
145 } else if crate::Type::peek(&lookahead) {
146 input.parse().map(Self::Variable)
147 } else {
148 Err(lookahead.error())
149 }?;
150
151 attrs.extend(item.replace_attrs(Vec::new()));
152 item.replace_attrs(attrs);
153
154 Ok(item)
155 }
156}
157
158impl Spanned for Item {
159 fn span(&self) -> Span {
160 match self {
161 Self::Contract(contract) => contract.span(),
162 Self::Enum(enumm) => enumm.span(),
163 Self::Error(error) => error.span(),
164 Self::Event(event) => event.span(),
165 Self::Function(function) => function.span(),
166 Self::Import(import) => import.span(),
167 Self::Pragma(pragma) => pragma.span(),
168 Self::Struct(strukt) => strukt.span(),
169 Self::Udt(udt) => udt.span(),
170 Self::Using(using) => using.span(),
171 Self::Variable(variable) => variable.span(),
172 }
173 }
174
175 fn set_span(&mut self, span: Span) {
176 match self {
177 Self::Contract(contract) => contract.set_span(span),
178 Self::Enum(enumm) => enumm.set_span(span),
179 Self::Error(error) => error.set_span(span),
180 Self::Event(event) => event.set_span(span),
181 Self::Function(function) => function.set_span(span),
182 Self::Import(import) => import.set_span(span),
183 Self::Pragma(pragma) => pragma.set_span(span),
184 Self::Struct(strukt) => strukt.set_span(span),
185 Self::Udt(udt) => udt.set_span(span),
186 Self::Using(using) => using.set_span(span),
187 Self::Variable(variable) => variable.set_span(span),
188 }
189 }
190}
191
192impl Item {
193 pub fn name(&self) -> Option<&SolIdent> {
194 match self {
195 Self::Contract(ItemContract { name, .. })
196 | Self::Enum(ItemEnum { name, .. })
197 | Self::Error(ItemError { name, .. })
198 | Self::Event(ItemEvent { name, .. })
199 | Self::Function(ItemFunction { name: Some(name), .. })
200 | Self::Struct(ItemStruct { name, .. })
201 | Self::Udt(ItemUdt { name, .. })
202 | Self::Variable(VariableDefinition { name, .. }) => Some(name),
203 _ => None,
204 }
205 }
206
207 pub fn attrs(&self) -> Option<&Vec<Attribute>> {
208 match self {
209 Self::Contract(ItemContract { attrs, .. })
210 | Self::Function(ItemFunction { attrs, .. })
211 | Self::Enum(ItemEnum { attrs, .. })
212 | Self::Error(ItemError { attrs, .. })
213 | Self::Event(ItemEvent { attrs, .. })
214 | Self::Struct(ItemStruct { attrs, .. })
215 | Self::Udt(ItemUdt { attrs, .. })
216 | Self::Variable(VariableDefinition { attrs, .. }) => Some(attrs),
217 Self::Import(_) | Self::Pragma(_) | Self::Using(_) => None,
218 }
219 }
220
221 pub fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>> {
222 match self {
223 Self::Contract(ItemContract { attrs, .. })
224 | Self::Function(ItemFunction { attrs, .. })
225 | Self::Enum(ItemEnum { attrs, .. })
226 | Self::Error(ItemError { attrs, .. })
227 | Self::Event(ItemEvent { attrs, .. })
228 | Self::Struct(ItemStruct { attrs, .. })
229 | Self::Udt(ItemUdt { attrs, .. })
230 | Self::Variable(VariableDefinition { attrs, .. }) => Some(attrs),
231 Self::Import(_) | Self::Pragma(_) | Self::Using(_) => None,
232 }
233 }
234
235 fn replace_attrs(&mut self, src: Vec<Attribute>) -> Vec<Attribute> {
236 if let Some(attrs) = self.attrs_mut() {
237 std::mem::replace(attrs, src)
238 } else {
239 Vec::new()
240 }
241 }
242}