syn_solidity/item/
mod.rs

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/// An AST item. A more expanded version of a [Solidity source unit][ref].
42///
43/// [ref]: https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.sourceUnit
44#[derive(Clone)]
45pub enum Item {
46    /// A contract, abstract contract, interface, or library definition:
47    /// `contract Foo is Bar, Baz { ... }`
48    Contract(ItemContract),
49
50    /// An enum definition: `enum Foo { A, B, C }`
51    Enum(ItemEnum),
52
53    /// An error definition: `error Foo(uint256 a, uint256 b);`
54    Error(ItemError),
55
56    /// An event definition: `event Transfer(address indexed from, address
57    /// indexed to, uint256 value);`
58    Event(ItemEvent),
59
60    /// A function, constructor, fallback, receive, or modifier definition:
61    /// `function helloWorld() external pure returns(string memory);`
62    Function(ItemFunction),
63
64    /// An import directive: `import "foo.sol";`
65    Import(ImportDirective),
66
67    /// A pragma directive: `pragma solidity ^0.8.0;`
68    Pragma(PragmaDirective),
69
70    /// A struct definition: `struct Foo { uint256 bar; }`
71    Struct(ItemStruct),
72
73    /// A user-defined value type definition: `type Foo is uint256;`
74    Udt(ItemUdt),
75
76    /// A `using` directive: `using { A, B.mul as * } for uint256 global;`
77    Using(UsingDirective),
78
79    /// A state variable or constant definition: `uint256 constant FOO = 42;`
80    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}