| 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 |  | 
|---|