blob: 507703a53ea73b4105c9f94166a2cd74f05c06c3 [file] [log] [blame]
David Tolnayf790b612017-12-31 18:46:57 -05001use proc_macro2::{Span, TokenStream};
David Tolnay61037c62018-01-05 16:21:03 -08002use quote::{ToTokens, Tokens};
David Tolnayf790b612017-12-31 18:46:57 -05003
4pub trait Spanned {
5 /// Returns a `Span` covering the complete contents of this AST node, or
6 /// `Span::call_site()` if this node is empty.
7 fn span(&self) -> Span;
8}
9
10impl<T> Spanned for T
11where
12 T: ToTokens,
13{
David Tolnay4d942b42018-01-02 22:14:04 -080014 #[cfg(procmacro2_semver_exempt)]
David Tolnayf790b612017-12-31 18:46:57 -050015 fn span(&self) -> Span {
16 let mut tokens = Tokens::new();
17 self.to_tokens(&mut tokens);
18 let token_stream = TokenStream::from(tokens);
19 let mut iter = token_stream.into_iter();
20 let mut span = match iter.next() {
21 Some(tt) => tt.span,
22 None => {
23 return Span::call_site();
24 }
25 };
26 for tt in iter {
27 if let Some(joined) = span.join(tt.span) {
28 span = joined;
29 }
30 }
31 span
32 }
David Tolnay4d942b42018-01-02 22:14:04 -080033
34 #[cfg(not(procmacro2_semver_exempt))]
35 fn span(&self) -> Span {
36 let mut tokens = Tokens::new();
37 self.to_tokens(&mut tokens);
38 let token_stream = TokenStream::from(tokens);
39 let mut iter = token_stream.into_iter();
40
41 // We can't join spans without procmacro2_semver_exempt so just grab the
42 // first one.
43 match iter.next() {
44 Some(tt) => tt.span,
45 None => Span::call_site(),
46 }
47 }
David Tolnayf790b612017-12-31 18:46:57 -050048}