Skip to main content

moxy_token/bridge/
proc_macro.rs

1use crate::span::fallback;
2use crate::{Delim, Group, Ident, Keyword, LexError, Lit, Spacing, Span, ToTokens, TokenStream, TokenTree, TryIntoTokenStream};
3
4// --- Span (fallback) ---
5
6impl From<proc_macro::Span> for fallback::Span {
7    fn from(#[allow(unused)] value: proc_macro::Span) -> Self {
8        #[cfg(nightly)]
9        {
10            let r = value.byte_range();
11            Self::new(r.start as u32, r.end as u32)
12        }
13
14        #[cfg(not(nightly))]
15        {
16            Self::default()
17        }
18    }
19}
20
21impl From<fallback::Span> for proc_macro::Span {
22    fn from(_value: fallback::Span) -> Self {
23        Self::call_site()
24    }
25}
26
27// --- Span ---
28
29impl From<proc_macro::Span> for Span {
30    #[inline]
31    fn from(value: proc_macro::Span) -> Self {
32        Self::Compiler(value)
33    }
34}
35
36impl From<Span> for proc_macro::Span {
37    fn from(value: Span) -> Self {
38        match value {
39            Span::Compiler(s) => s,
40            Span::Fallback(_) => Self::call_site(),
41        }
42    }
43}
44
45#[cfg(nightly)]
46impl proc_macro::MultiSpan for Span {
47    fn into_spans(self) -> Vec<proc_macro::Span> {
48        match self {
49            Self::Compiler(s) => vec![s],
50            Self::Fallback(_) => vec![proc_macro::Span::call_site()],
51        }
52    }
53}
54
55// --- Delim ---
56
57impl From<proc_macro::Delimiter> for Delim {
58    #[inline]
59    fn from(value: proc_macro::Delimiter) -> Self {
60        match value {
61            proc_macro::Delimiter::Parenthesis => Self::Paren,
62            proc_macro::Delimiter::Brace => Self::Brace,
63            proc_macro::Delimiter::Bracket => Self::Bracket,
64            proc_macro::Delimiter::None => Self::None,
65        }
66    }
67}
68
69impl From<Delim> for proc_macro::Delimiter {
70    #[inline]
71    fn from(value: Delim) -> Self {
72        match value {
73            Delim::Paren => Self::Parenthesis,
74            Delim::Brace => Self::Brace,
75            Delim::Bracket => Self::Bracket,
76            Delim::None => Self::None,
77        }
78    }
79}
80
81// --- Spacing ---
82
83impl From<proc_macro::Spacing> for Spacing {
84    #[inline]
85    fn from(value: proc_macro::Spacing) -> Self {
86        match value {
87            proc_macro::Spacing::Alone => Self::Alone,
88            proc_macro::Spacing::Joint => Self::Joint,
89        }
90    }
91}
92
93impl From<Spacing> for proc_macro::Spacing {
94    #[inline]
95    fn from(value: Spacing) -> Self {
96        match value {
97            Spacing::Alone => Self::Alone,
98            Spacing::Joint => Self::Joint,
99        }
100    }
101}
102
103// --- Ident ---
104
105impl From<proc_macro::Ident> for Ident {
106    #[inline]
107    fn from(value: proc_macro::Ident) -> Self {
108        Self::new(value.to_string()).with_span(value.span().into())
109    }
110}
111
112impl From<Ident> for proc_macro::Ident {
113    fn from(value: Ident) -> Self {
114        let span: proc_macro::Span = value.span().into();
115
116        if value.is_raw() {
117            Self::new_raw(value.text(), span)
118        } else {
119            Self::new(value.text(), span)
120        }
121    }
122}
123
124// --- Literal ---
125
126impl From<proc_macro::Literal> for Lit {
127    fn from(value: proc_macro::Literal) -> Self {
128        Self::from_repr(&value.to_string(), value.span().into())
129    }
130}
131
132impl From<Lit> for proc_macro::Literal {
133    fn from(value: Lit) -> Self {
134        let repr = value.repr();
135        let mut lit = repr.parse().unwrap_or_else(|_| Self::string(repr));
136
137        lit.set_span(value.span().into());
138        lit
139    }
140}
141
142// --- Group ---
143
144impl From<proc_macro::Group> for Group {
145    #[inline]
146    fn from(value: proc_macro::Group) -> Self {
147        use crate::span::DelimSpan;
148        let mut group = Self::new(value.delimiter().into(), value.stream().into());
149        group.span = DelimSpan::new(value.span_open().into(), value.span_close().into());
150        group
151    }
152}
153
154impl From<Group> for proc_macro::Group {
155    #[inline]
156    fn from(value: Group) -> Self {
157        let span = value.span.span().into();
158        let mut group = Self::new(value.delim.into(), value.tokens.into());
159        group.set_span(span);
160        group
161    }
162}
163
164// --- TokenStream ---
165
166impl ToTokens<TokenStream> for proc_macro::TokenTree {
167    fn to_tokens(&self, tokens: &mut TokenStream) {
168        match self {
169            Self::Ident(v) => {
170                let span = v.span().into();
171                let text = v.to_string();
172                let tt = match text.as_str() {
173                    "true" => TokenTree::Literal(Lit::Bool(crate::LitBool::new(true, span))),
174                    "false" => TokenTree::Literal(Lit::Bool(crate::LitBool::new(false, span))),
175                    _ => match Keyword::from_str(&text, span) {
176                        Some(kw) => TokenTree::Keyword(kw),
177                        None => TokenTree::Ident(v.clone().into()),
178                    },
179                };
180                tokens.extend_one(tt)
181            }
182            Self::Literal(v) => tokens.extend_one(TokenTree::Literal(v.clone().into())),
183            Self::Group(v) => tokens.extend_one(TokenTree::Group(v.clone().into())),
184            Self::Punct(p) => crate::scan_puncts_spanned(&[(p.as_char(), p.span().into(), p.spacing().into())], tokens),
185        }
186    }
187}
188
189impl ToTokens<TokenStream> for proc_macro::TokenStream {
190    fn to_tokens(&self, tokens: &mut TokenStream) {
191        let mut punct_run: Vec<(char, Span, Spacing)> = Vec::new();
192
193        for tt in self.clone() {
194            match tt {
195                proc_macro::TokenTree::Punct(p) => punct_run.push((p.as_char(), p.span().into(), p.spacing().into())),
196                other => {
197                    if !punct_run.is_empty() {
198                        crate::scan_puncts_spanned(&punct_run, tokens);
199                        punct_run.clear();
200                    }
201                    other.to_tokens(tokens);
202                }
203            }
204        }
205
206        if !punct_run.is_empty() {
207            crate::scan_puncts_spanned(&punct_run, tokens);
208        }
209    }
210}
211
212impl ToTokens<proc_macro::TokenStream> for TokenTree {
213    fn to_tokens(&self, out: &mut proc_macro::TokenStream) {
214        match self {
215            Self::Group(g) => out.extend(vec![proc_macro::TokenTree::Group(g.clone().into())]),
216            Self::Ident(v) => out.extend(vec![proc_macro::TokenTree::Ident(v.clone().into())]),
217            Self::Keyword(kw) => {
218                let id = proc_macro::Ident::new(kw.as_str(), kw.span().into());
219                out.extend(vec![proc_macro::TokenTree::Ident(id)])
220            }
221            // `true`/`false` are identifiers to the compiler, not literals.
222            Self::Literal(Lit::Bool(v)) => {
223                let id = proc_macro::Ident::new(v.repr(), v.span().into());
224                out.extend(vec![proc_macro::TokenTree::Ident(id)])
225            }
226            Self::Literal(v) => out.extend(vec![proc_macro::TokenTree::Literal(v.clone().into())]),
227            Self::Punct(op) => {
228                let text = op.as_str();
229                let span: proc_macro::Span = op.span().into();
230                let last = text.chars().count() - 1;
231
232                for (i, ch) in text.chars().enumerate() {
233                    let spacing = if i == last {
234                        op.spacing().into()
235                    } else {
236                        proc_macro::Spacing::Joint
237                    };
238
239                    let mut p = proc_macro::Punct::new(ch, spacing);
240                    p.set_span(span);
241                    out.extend(vec![proc_macro::TokenTree::Punct(p)]);
242                }
243            }
244        }
245    }
246}
247
248impl ToTokens<proc_macro::TokenStream> for TokenStream {
249    fn to_tokens(&self, out: &mut proc_macro::TokenStream) {
250        for t in self.iter() {
251            t.to_tokens(out);
252        }
253    }
254}
255
256impl From<proc_macro::TokenStream> for TokenStream {
257    fn from(value: proc_macro::TokenStream) -> Self {
258        let mut out = Self::new();
259        value.to_tokens(&mut out);
260        out
261    }
262}
263
264impl From<TokenStream> for proc_macro::TokenStream {
265    fn from(value: TokenStream) -> Self {
266        let mut out = Self::new();
267
268        for t in value.iter() {
269            t.to_tokens(&mut out);
270        }
271
272        out
273    }
274}
275
276impl TryIntoTokenStream for proc_macro::TokenStream {
277    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
278        Ok(self.into())
279    }
280}
281
282impl TryIntoTokenStream for &proc_macro::TokenStream {
283    fn try_into_token_stream(self) -> Result<TokenStream, LexError> {
284        Ok(self.clone().into())
285    }
286}