1 use proc_macro2::{Ident, Span, TokenStream}; 2 use quote::ToTokens; 3 use std::ops::{Deref, DerefMut}; 4 use syn::LitStr; 5 6 /// An entity with a span attached. 7 #[derive(Debug, Clone)] 8 pub struct Sp<T> { 9 span: Span, 10 val: T, 11 } 12 13 impl<T> Sp<T> { new(val: T, span: Span) -> Self14 pub fn new(val: T, span: Span) -> Self { 15 Sp { val, span } 16 } 17 call_site(val: T) -> Self18 pub fn call_site(val: T) -> Self { 19 Sp { 20 val, 21 span: Span::call_site(), 22 } 23 } 24 span(&self) -> Span25 pub fn span(&self) -> Span { 26 self.span 27 } 28 } 29 30 impl<T> Deref for Sp<T> { 31 type Target = T; 32 deref(&self) -> &T33 fn deref(&self) -> &T { 34 &self.val 35 } 36 } 37 38 impl<T> DerefMut for Sp<T> { deref_mut(&mut self) -> &mut T39 fn deref_mut(&mut self) -> &mut T { 40 &mut self.val 41 } 42 } 43 44 impl From<Ident> for Sp<String> { from(ident: Ident) -> Self45 fn from(ident: Ident) -> Self { 46 Sp { 47 val: ident.to_string(), 48 span: ident.span(), 49 } 50 } 51 } 52 53 impl From<LitStr> for Sp<String> { from(lit: LitStr) -> Self54 fn from(lit: LitStr) -> Self { 55 Sp { 56 val: lit.value(), 57 span: lit.span(), 58 } 59 } 60 } 61 62 impl<'a> From<Sp<&'a str>> for Sp<String> { from(sp: Sp<&'a str>) -> Self63 fn from(sp: Sp<&'a str>) -> Self { 64 Sp::new(sp.val.into(), sp.span) 65 } 66 } 67 68 impl<T: PartialEq> PartialEq<T> for Sp<T> { eq(&self, other: &T) -> bool69 fn eq(&self, other: &T) -> bool { 70 self.val == *other 71 } 72 } 73 74 impl<T: PartialEq> PartialEq for Sp<T> { eq(&self, other: &Sp<T>) -> bool75 fn eq(&self, other: &Sp<T>) -> bool { 76 self.val == **other 77 } 78 } 79 80 impl<T: AsRef<str>> AsRef<str> for Sp<T> { as_ref(&self) -> &str81 fn as_ref(&self) -> &str { 82 self.val.as_ref() 83 } 84 } 85 86 impl<T: ToTokens> ToTokens for Sp<T> { to_tokens(&self, stream: &mut TokenStream)87 fn to_tokens(&self, stream: &mut TokenStream) { 88 // this is the simplest way out of correct ones to change span on 89 // arbitrary token tree I can come up with 90 let tt = self.val.to_token_stream().into_iter().map(|mut tt| { 91 tt.set_span(self.span); 92 tt 93 }); 94 95 stream.extend(tt); 96 } 97 } 98