1 | use proc_macro2::Span; |
2 | use syn::{parse_quote, spanned::Spanned}; |
3 | |
4 | use crate::ast::NestedMeta; |
5 | use crate::error::Accumulator; |
6 | use crate::{Error, FromMeta, Result}; |
7 | |
8 | mod core; |
9 | mod forward_attrs; |
10 | mod forwarded_field; |
11 | mod from_attributes; |
12 | mod from_derive; |
13 | mod from_field; |
14 | mod from_meta; |
15 | mod from_type_param; |
16 | mod from_variant; |
17 | mod input_field; |
18 | mod input_variant; |
19 | mod outer_from; |
20 | mod shape; |
21 | |
22 | pub use self::core::Core; |
23 | pub use self::forward_attrs::ForwardAttrsFilter; |
24 | pub use self::forwarded_field::ForwardedField; |
25 | pub use self::from_attributes::FromAttributesOptions; |
26 | pub use self::from_derive::FdiOptions; |
27 | pub use self::from_field::FromFieldOptions; |
28 | pub use self::from_meta::FromMetaOptions; |
29 | pub use self::from_type_param::FromTypeParamOptions; |
30 | pub use self::from_variant::FromVariantOptions; |
31 | pub use self::input_field::InputField; |
32 | pub use self::input_variant::InputVariant; |
33 | pub use self::outer_from::OuterFrom; |
34 | pub use self::shape::{DataShape, DeriveInputShapeSet}; |
35 | |
36 | /// A default/fallback expression encountered in attributes during parsing. |
37 | #[derive (Debug, Clone)] |
38 | pub enum DefaultExpression { |
39 | /// The value should be taken from the `default` instance of the containing struct. |
40 | /// This is not valid in container options. |
41 | Inherit, |
42 | Explicit(syn::Path), |
43 | Trait { |
44 | /// The input span that is responsible for the use of `Default::default`. |
45 | span: Span, |
46 | }, |
47 | } |
48 | |
49 | #[doc (hidden)] |
50 | impl FromMeta for DefaultExpression { |
51 | // Note: This cannot use `from_word` as it needs to capture the span |
52 | // in the `Meta::Path` case. |
53 | fn from_meta(item: &syn::Meta) -> Result<Self> { |
54 | match item { |
55 | syn::Meta::Path(_) => Ok(DefaultExpression::Trait { span: item.span() }), |
56 | syn::Meta::List(nm: &MetaList) => Err(Error::unsupported_format("list" ).with_span(node:nm)), |
57 | syn::Meta::NameValue(nv: &MetaNameValue) => Self::from_expr(&nv.value), |
58 | } |
59 | } |
60 | |
61 | fn from_expr(expr: &syn::Expr) -> Result<Self> { |
62 | syn::Path::from_expr(expr).map(op:DefaultExpression::Explicit) |
63 | } |
64 | |
65 | fn from_value(value: &syn::Lit) -> Result<Self> { |
66 | syn::Path::from_value(value).map(op:DefaultExpression::Explicit) |
67 | } |
68 | } |
69 | |
70 | /// Middleware for extracting attribute values. Implementers are expected to override |
71 | /// `parse_nested` so they can apply individual items to themselves, while `parse_attributes` |
72 | /// is responsible for looping through distinct outer attributes and collecting errors. |
73 | pub trait ParseAttribute: Sized { |
74 | fn parse_attributes(mut self, attrs: &[syn::Attribute]) -> Result<Self> { |
75 | let mut errors: Accumulator = Error::accumulator(); |
76 | for attr: &Attribute in attrs { |
77 | if attr.meta.path() == &parse_quote!(darling) { |
78 | errors.handle(result:parse_attr(attr, &mut self)); |
79 | } |
80 | } |
81 | |
82 | errors.finish_with(self) |
83 | } |
84 | |
85 | /// Read a meta-item, and apply its values to the current instance. |
86 | fn parse_nested(&mut self, mi: &syn::Meta) -> Result<()>; |
87 | } |
88 | |
89 | fn parse_attr<T: ParseAttribute>(attr: &syn::Attribute, target: &mut T) -> Result<()> { |
90 | let mut errors: Accumulator = Error::accumulator(); |
91 | match &attr.meta { |
92 | syn::Meta::List(data: &MetaList) => { |
93 | for item: NestedMeta in NestedMeta::parse_meta_list(data.tokens.clone())? { |
94 | if let NestedMeta::Meta(ref mi: &Meta) = item { |
95 | errors.handle(result:target.parse_nested(mi)); |
96 | } else { |
97 | panic!("Wasn't able to parse: ` {:?}`" , item); |
98 | } |
99 | } |
100 | |
101 | errors.finish() |
102 | } |
103 | item: &Meta => panic!("Wasn't able to parse: ` {:?}`" , item), |
104 | } |
105 | } |
106 | |
107 | /// Middleware for extracting values from the body of the derive input. Implementers are |
108 | /// expected to override `parse_field` or `parse_variant` as appropriate for their use-case, |
109 | /// while `parse_body` dispatches to the appropriate methods and handles error collection. |
110 | pub trait ParseData: Sized { |
111 | fn parse_body(mut self, body: &syn::Data) -> Result<Self> { |
112 | use syn::{Data, Fields}; |
113 | |
114 | let mut errors = Error::accumulator(); |
115 | |
116 | match *body { |
117 | Data::Struct(ref data) => match data.fields { |
118 | Fields::Unit => {} |
119 | Fields::Named(ref fields) => { |
120 | for field in &fields.named { |
121 | errors.handle(self.parse_field(field)); |
122 | } |
123 | } |
124 | Fields::Unnamed(ref fields) => { |
125 | for field in &fields.unnamed { |
126 | errors.handle(self.parse_field(field)); |
127 | } |
128 | } |
129 | }, |
130 | Data::Enum(ref data) => { |
131 | for variant in &data.variants { |
132 | errors.handle(self.parse_variant(variant)); |
133 | } |
134 | } |
135 | Data::Union(_) => unreachable!(), |
136 | }; |
137 | |
138 | self.validate_body(&mut errors); |
139 | |
140 | errors.finish_with(self) |
141 | } |
142 | |
143 | /// Apply the next found variant to the object, returning an error |
144 | /// if parsing goes wrong. |
145 | fn parse_variant(&mut self, variant: &syn::Variant) -> Result<()> { |
146 | Err(Error::unsupported_format("enum variant" ).with_span(variant)) |
147 | } |
148 | |
149 | /// Apply the next found struct field to the object, returning an error |
150 | /// if parsing goes wrong. |
151 | fn parse_field(&mut self, field: &syn::Field) -> Result<()> { |
152 | Err(Error::unsupported_format("struct field" ).with_span(field)) |
153 | } |
154 | |
155 | /// Perform validation checks that require data from more than one field or variant. |
156 | /// The default implementation does no validations. |
157 | /// Implementors can override this method as appropriate for their use-case. |
158 | #[allow (unused_variables)] |
159 | fn validate_body(&self, errors: &mut Accumulator) {} |
160 | } |
161 | |