thiserror_impl/
ast.rs

1use crate::attr::{self, Attrs};
2use crate::generics::ParamsInScope;
3use proc_macro2::Span;
4use syn::{
5    Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result,
6    Type,
7};
8
9pub enum Input<'a> {
10    Struct(Struct<'a>),
11    Enum(Enum<'a>),
12}
13
14pub struct Struct<'a> {
15    pub attrs: Attrs<'a>,
16    pub ident: Ident,
17    pub generics: &'a Generics,
18    pub fields: Vec<Field<'a>>,
19}
20
21pub struct Enum<'a> {
22    pub attrs: Attrs<'a>,
23    pub ident: Ident,
24    pub generics: &'a Generics,
25    pub variants: Vec<Variant<'a>>,
26}
27
28pub struct Variant<'a> {
29    pub original: &'a syn::Variant,
30    pub attrs: Attrs<'a>,
31    pub ident: Ident,
32    pub fields: Vec<Field<'a>>,
33}
34
35pub struct Field<'a> {
36    pub original: &'a syn::Field,
37    pub attrs: Attrs<'a>,
38    pub member: Member,
39    pub ty: &'a Type,
40    pub contains_generic: bool,
41}
42
43impl<'a> Input<'a> {
44    pub fn from_syn(node: &'a DeriveInput) -> Result<Self> {
45        match &node.data {
46            Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct),
47            Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum),
48            Data::Union(_) => Err(Error::new_spanned(
49                node,
50                "union as errors are not supported",
51            )),
52        }
53    }
54}
55
56impl<'a> Struct<'a> {
57    fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> {
58        let mut attrs = attr::get(&node.attrs)?;
59        let scope = ParamsInScope::new(&node.generics);
60        let span = attrs.span().unwrap_or_else(Span::call_site);
61        let fields = Field::multiple_from_syn(&data.fields, &scope, span)?;
62        if let Some(display) = &mut attrs.display {
63            display.expand_shorthand(&fields);
64        }
65        Ok(Struct {
66            attrs,
67            ident: node.ident.clone(),
68            generics: &node.generics,
69            fields,
70        })
71    }
72}
73
74impl<'a> Enum<'a> {
75    fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> {
76        let attrs = attr::get(&node.attrs)?;
77        let scope = ParamsInScope::new(&node.generics);
78        let span = attrs.span().unwrap_or_else(Span::call_site);
79        let variants = data
80            .variants
81            .iter()
82            .map(|node| {
83                let mut variant = Variant::from_syn(node, &scope, span)?;
84                if let display @ None = &mut variant.attrs.display {
85                    display.clone_from(&attrs.display);
86                }
87                if let Some(display) = &mut variant.attrs.display {
88                    display.expand_shorthand(&variant.fields);
89                } else if variant.attrs.transparent.is_none() {
90                    variant.attrs.transparent = attrs.transparent;
91                }
92                Ok(variant)
93            })
94            .collect::<Result<_>>()?;
95        Ok(Enum {
96            attrs,
97            ident: node.ident.clone(),
98            generics: &node.generics,
99            variants,
100        })
101    }
102}
103
104impl<'a> Variant<'a> {
105    fn from_syn(node: &'a syn::Variant, scope: &ParamsInScope<'a>, span: Span) -> Result<Self> {
106        let attrs = attr::get(&node.attrs)?;
107        let span = attrs.span().unwrap_or(span);
108        Ok(Variant {
109            original: node,
110            attrs,
111            ident: node.ident.clone(),
112            fields: Field::multiple_from_syn(&node.fields, scope, span)?,
113        })
114    }
115}
116
117impl<'a> Field<'a> {
118    fn multiple_from_syn(
119        fields: &'a Fields,
120        scope: &ParamsInScope<'a>,
121        span: Span,
122    ) -> Result<Vec<Self>> {
123        fields
124            .iter()
125            .enumerate()
126            .map(|(i, field)| Field::from_syn(i, field, scope, span))
127            .collect()
128    }
129
130    fn from_syn(
131        i: usize,
132        node: &'a syn::Field,
133        scope: &ParamsInScope<'a>,
134        span: Span,
135    ) -> Result<Self> {
136        Ok(Field {
137            original: node,
138            attrs: attr::get(&node.attrs)?,
139            member: node.ident.clone().map(Member::Named).unwrap_or_else(|| {
140                Member::Unnamed(Index {
141                    index: i as u32,
142                    span,
143                })
144            }),
145            ty: &node.ty,
146            contains_generic: scope.intersects(&node.ty),
147        })
148    }
149}
150
151impl Attrs<'_> {
152    pub fn span(&self) -> Option<Span> {
153        if let Some(display) = &self.display {
154            Some(display.fmt.span())
155        } else if let Some(transparent) = &self.transparent {
156            Some(transparent.span)
157        } else {
158            None
159        }
160    }
161}