1 use proc_macro2::Span; 2 use std::ops::{Deref, DerefMut}; 3 use syn::spanned::Spanned; 4 5 use crate::{ 6 FromDeriveInput, FromField, FromGenericParam, FromGenerics, FromMeta, FromTypeParam, 7 FromVariant, Result, 8 }; 9 10 /// A value and an associated position in source code. The main use case for this is 11 /// to preserve position information to emit warnings from proc macros. You can use 12 /// a `SpannedValue<T>` as a field in any struct that implements or derives any of 13 /// `darling`'s core traits. 14 /// 15 /// To access the underlying value, use the struct's `Deref` implementation. 16 /// 17 /// # Defaulting 18 /// This type is meant to be used in conjunction with attribute-extracted options, 19 /// but the user may not always explicitly set those options in their source code. 20 /// In this case, using `Default::default()` will create an instance which points 21 /// to `Span::call_site()`. 22 #[derive(Debug, Clone, Copy)] 23 pub struct SpannedValue<T> { 24 value: T, 25 span: Span, 26 } 27 28 impl<T> SpannedValue<T> { new(value: T, span: Span) -> Self29 pub fn new(value: T, span: Span) -> Self { 30 SpannedValue { value, span } 31 } 32 33 /// Get the source code location referenced by this struct. span(&self) -> Span34 pub fn span(&self) -> Span { 35 self.span 36 } 37 38 /// Apply a mapping function to a reference to the spanned value. map_ref<U>(&self, map_fn: impl FnOnce(&T) -> U) -> SpannedValue<U>39 pub fn map_ref<U>(&self, map_fn: impl FnOnce(&T) -> U) -> SpannedValue<U> { 40 SpannedValue::new(map_fn(&self.value), self.span) 41 } 42 } 43 44 impl<T: Default> Default for SpannedValue<T> { default() -> Self45 fn default() -> Self { 46 SpannedValue::new(Default::default(), Span::call_site()) 47 } 48 } 49 50 impl<T> Deref for SpannedValue<T> { 51 type Target = T; 52 deref(&self) -> &T53 fn deref(&self) -> &T { 54 &self.value 55 } 56 } 57 58 impl<T> DerefMut for SpannedValue<T> { deref_mut(&mut self) -> &mut T59 fn deref_mut(&mut self) -> &mut T { 60 &mut self.value 61 } 62 } 63 64 impl<T> AsRef<T> for SpannedValue<T> { as_ref(&self) -> &T65 fn as_ref(&self) -> &T { 66 &self.value 67 } 68 } 69 70 macro_rules! spanned { 71 ($trayt:ident, $method:ident, $syn:path) => { 72 impl<T: $trayt> $trayt for SpannedValue<T> { 73 fn $method(value: &$syn) -> Result<Self> { 74 Ok(SpannedValue::new( 75 $trayt::$method(value).map_err(|e| e.with_span(value))?, 76 value.span(), 77 )) 78 } 79 } 80 }; 81 } 82 83 impl<T: FromMeta> FromMeta for SpannedValue<T> { from_meta(item: &syn::Meta) -> Result<Self>84 fn from_meta(item: &syn::Meta) -> Result<Self> { 85 let value = T::from_meta(item).map_err(|e| e.with_span(item))?; 86 let span = match item { 87 // Example: `#[darling(skip)]` as SpannedValue<bool> 88 // should have the span pointing to the word `skip`. 89 syn::Meta::Path(path) => path.span(), 90 // Example: `#[darling(attributes(Value))]` as a SpannedValue<Vec<String>> 91 // should have the span pointing to the list contents. 92 syn::Meta::List(list) => list.tokens.span(), 93 // Example: `#[darling(skip = true)]` as SpannedValue<bool> 94 // should have the span pointing to the word `true`. 95 syn::Meta::NameValue(nv) => nv.value.span(), 96 }; 97 98 Ok(Self::new(value, span)) 99 } 100 } 101 102 spanned!(FromGenericParam, from_generic_param, syn::GenericParam); 103 spanned!(FromGenerics, from_generics, syn::Generics); 104 spanned!(FromTypeParam, from_type_param, syn::TypeParam); 105 spanned!(FromDeriveInput, from_derive_input, syn::DeriveInput); 106 spanned!(FromField, from_field, syn::Field); 107 spanned!(FromVariant, from_variant, syn::Variant); 108 109 impl<T: Spanned> From<T> for SpannedValue<T> { from(value: T) -> Self110 fn from(value: T) -> Self { 111 let span = value.span(); 112 SpannedValue::new(value, span) 113 } 114 } 115 116 #[cfg(test)] 117 mod tests { 118 use super::*; 119 use proc_macro2::Span; 120 121 /// Make sure that `SpannedValue` can be seamlessly used as its underlying type. 122 #[test] deref()123 fn deref() { 124 let test = SpannedValue::new("hello", Span::call_site()); 125 assert_eq!("hello", test.trim()); 126 } 127 } 128