1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::scanner;
use crate::token::Ident;
use crate::token::SingleCharPunct;
use crate::token::Spacing;
use crate::Entry;
use crate::SourceFile;
use crate::Span;
use crate::TokenStream;

use std::rc::Rc;

use proc_macro2::Delimiter;
use proc_macro2::Spacing as Spacing2;
use proc_macro2::TokenStream as TokenStream2;
use proc_macro2::TokenTree as TokenTree2;

#[cfg(feature = "proc-macro")]
mod proc_macro1;

impl From<Spacing2> for Spacing {
    fn from(value: Spacing2) -> Self {
        match value {
            Spacing2::Alone => Spacing::Alone,
            Spacing2::Joint => Spacing::Joint,
        }
    }
}

fn tree_to_trees(token: TokenTree2) -> Vec<Entry> {
    let mut tokens = vec![];
    let span = Span {
        start: 0,
        end: 0,
        source: Rc::new(SourceFile {
            name: String::new(),
            path: None,
            contents: String::new(),
        }),
    };
    match token {
        TokenTree2::Group(group) => {
            let delimiters = match group.delimiter() {
                Delimiter::Parenthesis => Some(('(', ')')),
                Delimiter::Bracket => Some(('[', ']')),
                Delimiter::Brace => Some(('{', '}')),
                Delimiter::None => None,
            };
            if let Some((start, _)) = delimiters {
                tokens.push(Entry::Punct(SingleCharPunct {
                    kind: start.try_into().unwrap(),
                    spacing: Spacing::Alone,
                    span: span.clone(),
                }));
            }
            for token in group.stream() {
                tokens.append(&mut tree_to_trees(token));
            }
            if let Some((_, end)) = delimiters {
                tokens.push(Entry::Punct(SingleCharPunct {
                    kind: end.try_into().unwrap(),
                    spacing: Spacing::Alone,
                    span: span.clone(),
                }));
            }
        }
        TokenTree2::Ident(ident) => {
            let string = ident.to_string();
            tokens.push(Entry::Ident(Ident {
                string,
                span: span.clone(),
            }));
        }
        TokenTree2::Literal(literal) => {
            tokens.extend(
                scanner::scan(Rc::new(SourceFile {
                    name: String::new(),
                    path: None,
                    contents: literal.to_string(),
                }), 0, None)
                .0
                .tokens
                .into_iter()
                .map(|mut token| {
                    token.set_span(span.clone());
                    token
                }),
            );
        }
        TokenTree2::Punct(punct) => {
            let kind = punct.as_char().try_into().unwrap();
            let spacing = punct.spacing().into();
            tokens.push(Entry::Punct(SingleCharPunct {
                kind,
                spacing,
                span: span.clone(),
            }));
        }
    }
    tokens
}

impl From<TokenStream2> for TokenStream {
    fn from(value: TokenStream2) -> Self {
        let mut tokens = vec![];
        let contents = value.to_string();
        let source = Rc::new(SourceFile::new("<TokenStream>".to_string(), contents));
        for token in value {
            tokens.append(&mut tree_to_trees(token));
        }
        let span = Span {
            start: 0,
            end: source.contents.len(),
            source: Rc::clone(&source),
        };
        for token in &mut tokens {
            token.set_span(span.clone());
        }
        TokenStream::new(tokens, source)
    }
}