Skip to main content

moxy_token/bridge/
proc_macro.rs

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