thiserror_impl/
ast.rs

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