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