]> git.proxmox.com Git - rustc.git/blobdiff - vendor/thiserror-impl/src/ast.rs
Update upstream source from tag 'upstream/1.52.1+dfsg1'
[rustc.git] / vendor / thiserror-impl / src / ast.rs
diff --git a/vendor/thiserror-impl/src/ast.rs b/vendor/thiserror-impl/src/ast.rs
new file mode 100644 (file)
index 0000000..8698ecf
--- /dev/null
@@ -0,0 +1,151 @@
+use crate::attr::{self, Attrs};
+use proc_macro2::Span;
+use syn::{
+    Data, DataEnum, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Index, Member, Result,
+    Type,
+};
+
+pub enum Input<'a> {
+    Struct(Struct<'a>),
+    Enum(Enum<'a>),
+}
+
+pub struct Struct<'a> {
+    pub original: &'a DeriveInput,
+    pub attrs: Attrs<'a>,
+    pub ident: Ident,
+    pub generics: &'a Generics,
+    pub fields: Vec<Field<'a>>,
+}
+
+pub struct Enum<'a> {
+    pub original: &'a DeriveInput,
+    pub attrs: Attrs<'a>,
+    pub ident: Ident,
+    pub generics: &'a Generics,
+    pub variants: Vec<Variant<'a>>,
+}
+
+pub struct Variant<'a> {
+    pub original: &'a syn::Variant,
+    pub attrs: Attrs<'a>,
+    pub ident: Ident,
+    pub fields: Vec<Field<'a>>,
+}
+
+pub struct Field<'a> {
+    pub original: &'a syn::Field,
+    pub attrs: Attrs<'a>,
+    pub member: Member,
+    pub ty: &'a Type,
+}
+
+impl<'a> Input<'a> {
+    pub fn from_syn(node: &'a DeriveInput) -> Result<Self> {
+        match &node.data {
+            Data::Struct(data) => Struct::from_syn(node, data).map(Input::Struct),
+            Data::Enum(data) => Enum::from_syn(node, data).map(Input::Enum),
+            Data::Union(_) => Err(Error::new_spanned(
+                node,
+                "union as errors are not supported",
+            )),
+        }
+    }
+}
+
+impl<'a> Struct<'a> {
+    fn from_syn(node: &'a DeriveInput, data: &'a DataStruct) -> Result<Self> {
+        let mut attrs = attr::get(&node.attrs)?;
+        let span = attrs.span().unwrap_or_else(Span::call_site);
+        let fields = Field::multiple_from_syn(&data.fields, span)?;
+        if let Some(display) = &mut attrs.display {
+            display.expand_shorthand(&fields);
+        }
+        Ok(Struct {
+            original: node,
+            attrs,
+            ident: node.ident.clone(),
+            generics: &node.generics,
+            fields,
+        })
+    }
+}
+
+impl<'a> Enum<'a> {
+    fn from_syn(node: &'a DeriveInput, data: &'a DataEnum) -> Result<Self> {
+        let attrs = attr::get(&node.attrs)?;
+        let span = attrs.span().unwrap_or_else(Span::call_site);
+        let variants = data
+            .variants
+            .iter()
+            .map(|node| {
+                let mut variant = Variant::from_syn(node, span)?;
+                if let display @ None = &mut variant.attrs.display {
+                    *display = attrs.display.clone();
+                }
+                if let Some(display) = &mut variant.attrs.display {
+                    display.expand_shorthand(&variant.fields);
+                } else if variant.attrs.transparent.is_none() {
+                    variant.attrs.transparent = attrs.transparent;
+                }
+                Ok(variant)
+            })
+            .collect::<Result<_>>()?;
+        Ok(Enum {
+            original: node,
+            attrs,
+            ident: node.ident.clone(),
+            generics: &node.generics,
+            variants,
+        })
+    }
+}
+
+impl<'a> Variant<'a> {
+    fn from_syn(node: &'a syn::Variant, span: Span) -> Result<Self> {
+        let attrs = attr::get(&node.attrs)?;
+        let span = attrs.span().unwrap_or(span);
+        Ok(Variant {
+            original: node,
+            attrs,
+            ident: node.ident.clone(),
+            fields: Field::multiple_from_syn(&node.fields, span)?,
+        })
+    }
+}
+
+impl<'a> Field<'a> {
+    fn multiple_from_syn(fields: &'a Fields, span: Span) -> Result<Vec<Self>> {
+        fields
+            .iter()
+            .enumerate()
+            .map(|(i, field)| Field::from_syn(i, field, span))
+            .collect()
+    }
+
+    fn from_syn(i: usize, node: &'a syn::Field, span: Span) -> Result<Self> {
+        Ok(Field {
+            original: node,
+            attrs: attr::get(&node.attrs)?,
+            member: node.ident.clone().map(Member::Named).unwrap_or_else(|| {
+                Member::Unnamed(Index {
+                    index: i as u32,
+                    span,
+                })
+            }),
+            ty: &node.ty,
+        })
+    }
+}
+
+impl Attrs<'_> {
+    pub fn span(&self) -> Option<Span> {
+        if let Some(display) = &self.display {
+            Some(display.fmt.span())
+        } else if let Some(transparent) = &self.transparent {
+            Some(transparent.span)
+        } else {
+            None
+        }
+    }
+}