| 1 | use proc_macro2::{Span, TokenStream}; |
| 2 | use quote::{quote, quote_spanned, ToTokens, TokenStreamExt}; |
| 3 | use syn::{spanned::Spanned, Ident, Path}; |
| 4 | |
| 5 | /// This will be in scope during struct initialization after option parsing. |
| 6 | const DEFAULT_STRUCT_NAME: &str = "__default" ; |
| 7 | |
| 8 | /// The fallback value for a field or container. |
| 9 | #[derive (Debug, Clone)] |
| 10 | pub enum DefaultExpression<'a> { |
| 11 | /// Only valid on fields, `Inherit` indicates that the value should be taken from a pre-constructed |
| 12 | /// fallback object. The value in the variant is the ident of the field. |
| 13 | Inherit(&'a Ident), |
| 14 | Explicit(&'a Path), |
| 15 | Trait { |
| 16 | span: Span, |
| 17 | }, |
| 18 | } |
| 19 | |
| 20 | impl<'a> DefaultExpression<'a> { |
| 21 | pub fn as_declaration(&'a self) -> DefaultDeclaration<'a> { |
| 22 | DefaultDeclaration(self) |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | impl<'a> ToTokens for DefaultExpression<'a> { |
| 27 | fn to_tokens(&self, tokens: &mut TokenStream) { |
| 28 | tokens.append_all(iter:match *self { |
| 29 | DefaultExpression::Inherit(ident: &Ident) => { |
| 30 | let dsn: Ident = Ident::new(DEFAULT_STRUCT_NAME, ::proc_macro2::Span::call_site()); |
| 31 | quote!(#dsn.#ident) |
| 32 | } |
| 33 | DefaultExpression::Explicit(path: &Path) => { |
| 34 | // Use quote_spanned to properly set the span of the parentheses |
| 35 | quote_spanned!(path.span()=>#path()) |
| 36 | } |
| 37 | DefaultExpression::Trait { span: Span } => { |
| 38 | quote_spanned!(span=> ::darling::export::Default::default()) |
| 39 | } |
| 40 | }); |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | /// Used only by containers, this wrapper type generates code to declare the fallback instance. |
| 45 | pub struct DefaultDeclaration<'a>(&'a DefaultExpression<'a>); |
| 46 | |
| 47 | impl<'a> ToTokens for DefaultDeclaration<'a> { |
| 48 | fn to_tokens(&self, tokens: &mut TokenStream) { |
| 49 | let name: Ident = Ident::new(DEFAULT_STRUCT_NAME, ::proc_macro2::Span::call_site()); |
| 50 | let expr: &'a DefaultExpression<'a> = self.0; |
| 51 | tokens.append_all(iter:quote!(let #name: Self = #expr;)); |
| 52 | } |
| 53 | } |
| 54 | |