1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 use crate::ToTokens; 4 use proc_macro2::extra::DelimSpan; 5 use proc_macro2::{Span, TokenStream}; 6 7 // Not public API other than via the syn crate. Use syn::spanned::Spanned. 8 pub trait Spanned: private::Sealed { __span(&self) -> Span9 fn __span(&self) -> Span; 10 } 11 12 impl Spanned for Span { __span(&self) -> Span13 fn __span(&self) -> Span { 14 *self 15 } 16 } 17 18 impl Spanned for DelimSpan { __span(&self) -> Span19 fn __span(&self) -> Span { 20 self.join() 21 } 22 } 23 24 impl<T: ?Sized + ToTokens> Spanned for T { __span(&self) -> Span25 fn __span(&self) -> Span { 26 join_spans(self.into_token_stream()) 27 } 28 } 29 join_spans(tokens: TokenStream) -> Span30fn join_spans(tokens: TokenStream) -> Span { 31 let mut iter = tokens.into_iter().map(|tt| tt.span()); 32 33 let first = match iter.next() { 34 Some(span) => span, 35 None => return Span::call_site(), 36 }; 37 38 iter.fold(None, |_prev, next| Some(next)) 39 .and_then(|last| first.join(last)) 40 .unwrap_or(first) 41 } 42 43 mod private { 44 use crate::ToTokens; 45 use proc_macro2::extra::DelimSpan; 46 use proc_macro2::Span; 47 48 pub trait Sealed {} 49 impl Sealed for Span {} 50 impl Sealed for DelimSpan {} 51 impl<T: ?Sized + ToTokens> Sealed for T {} 52 } 53