errore_impl/
ast.rs

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