1 use crate::ToTokens; 2 use proc_macro2::extra::DelimSpan; 3 use proc_macro2::{Span, TokenStream}; 4 5 // Not public API other than via the syn crate. Use syn::spanned::Spanned. 6 pub trait Spanned: private::Sealed { __span(&self) -> Span7 fn __span(&self) -> Span; 8 } 9 10 impl Spanned for Span { __span(&self) -> Span11 fn __span(&self) -> Span { 12 *self 13 } 14 } 15 16 impl Spanned for DelimSpan { __span(&self) -> Span17 fn __span(&self) -> Span { 18 self.join() 19 } 20 } 21 22 impl<T: ?Sized + ToTokens> Spanned for T { __span(&self) -> Span23 fn __span(&self) -> Span { 24 join_spans(self.into_token_stream()) 25 } 26 } 27 join_spans(tokens: TokenStream) -> Span28fn join_spans(tokens: TokenStream) -> Span { 29 let mut iter = tokens.into_iter().map(|tt| tt.span()); 30 31 let first = match iter.next() { 32 Some(span) => span, 33 None => return Span::call_site(), 34 }; 35 36 iter.fold(None, |_prev, next| Some(next)) 37 .and_then(|last| first.join(last)) 38 .unwrap_or(first) 39 } 40 41 mod private { 42 use crate::ToTokens; 43 use proc_macro2::extra::DelimSpan; 44 use proc_macro2::Span; 45 46 pub trait Sealed {} 47 impl Sealed for Span {} 48 impl Sealed for DelimSpan {} 49 impl<T: ?Sized + ToTokens> Sealed for T {} 50 } 51