syn_solidity/item/
udt.rs

1use crate::{kw, SolIdent, Spanned, Type};
2use proc_macro2::Span;
3use std::{
4    fmt,
5    hash::{Hash, Hasher},
6};
7use syn::{
8    parse::{Parse, ParseStream},
9    Attribute, Result, Token,
10};
11
12/// A user-defined value type definition: `type Foo is uint256;`.
13///
14/// Solidity reference:
15/// <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.userDefinedValueTypeDefinition>
16#[derive(Clone)]
17pub struct ItemUdt {
18    pub attrs: Vec<Attribute>,
19    pub type_token: Token![type],
20    pub name: SolIdent,
21    pub is_token: kw::is,
22    pub ty: Type,
23    pub semi_token: Token![;],
24}
25
26impl fmt::Display for ItemUdt {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        write!(f, "type {} is {};", self.name, self.ty)
29    }
30}
31
32impl fmt::Debug for ItemUdt {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        f.debug_struct("ItemUdt")
35            .field("attrs", &self.attrs)
36            .field("name", &self.name)
37            .field("ty", &self.ty)
38            .finish()
39    }
40}
41
42impl PartialEq for ItemUdt {
43    fn eq(&self, other: &Self) -> bool {
44        self.name == other.name && self.ty == other.ty
45    }
46}
47
48impl Eq for ItemUdt {}
49
50impl Hash for ItemUdt {
51    fn hash<H: Hasher>(&self, state: &mut H) {
52        self.name.hash(state);
53        self.ty.hash(state);
54    }
55}
56
57impl Parse for ItemUdt {
58    fn parse(input: ParseStream<'_>) -> Result<Self> {
59        let this = Self {
60            attrs: input.call(Attribute::parse_outer)?,
61            type_token: input.parse()?,
62            name: input.parse()?,
63            is_token: input.parse()?,
64            ty: input.parse()?,
65            semi_token: input.parse()?,
66        };
67
68        // Solidity doesn't allow this, and it would cause ambiguity later on
69        if this.ty.has_custom() {
70            return Err(syn::Error::new(
71                this.ty.span(),
72                "the underlying type for a user-defined value type has to be an elementary value type",
73            ));
74        }
75
76        Ok(this)
77    }
78}
79
80impl Spanned for ItemUdt {
81    fn span(&self) -> Span {
82        self.name.span()
83    }
84
85    fn set_span(&mut self, span: Span) {
86        self.type_token.span = span;
87        self.name.set_span(span);
88        self.is_token.span = span;
89        self.ty.set_span(span);
90        self.semi_token.span = span;
91    }
92}