const_format_proc_macros/
respan_to_macro.rs
1use crate::parse_utils::TokenTreeExt;
2
3use proc_macro2::{Delimiter, Span, TokenStream as TokenStream2, TokenTree as TokenTree2};
4
5const MSG: &str = "Expected the macro to be called as `respan_to!((tokens) more tokens)`";
6
7fn parse_paren(tt: TokenTree2) -> TokenStream2 {
8 match tt {
9 TokenTree2::Group(group) if group.delimiter() == Delimiter::Parenthesis => group.stream(),
10 _ => panic!("{}", MSG),
11 }
12}
13
14fn get_span(ts: TokenStream2) -> Span {
15 let mut iter = ts.into_iter();
16
17 match iter.next() {
18 Some(TokenTree2::Group(group)) if group.delimiter() == Delimiter::None => {
19 get_span(group.stream())
20 }
21 Some(first_tt) => {
22 let mut span = first_tt.span();
23
24 for tt in iter {
25 span = span.join(tt.span()).unwrap_or(span);
26 }
27 span
28 }
29 None => Span::mixed_site(),
30 }
31}
32
33pub(crate) fn implementation(ts: TokenStream2) -> TokenStream2 {
34 let mut iter = ts.into_iter();
35
36 let span_to = get_span(parse_paren(iter.next().expect(MSG)));
37
38 iter.map(|tt| tt.set_span_recursive(span_to)).collect()
39}