diff options
Diffstat (limited to 'crates/proc_macro_srv/src/rustc_server.rs')
-rw-r--r-- | crates/proc_macro_srv/src/rustc_server.rs | 704 |
1 files changed, 704 insertions, 0 deletions
diff --git a/crates/proc_macro_srv/src/rustc_server.rs b/crates/proc_macro_srv/src/rustc_server.rs new file mode 100644 index 000000000..7d1695c86 --- /dev/null +++ b/crates/proc_macro_srv/src/rustc_server.rs | |||
@@ -0,0 +1,704 @@ | |||
1 | //! Rustc proc-macro server implementation with tt | ||
2 | //! | ||
3 | //! Based on idea from https://github.com/fedochet/rust-proc-macro-expander | ||
4 | //! The lib-proc-macro server backend is `TokenStream`-agnostic, such that | ||
5 | //! we could provide any TokenStream implementation. | ||
6 | //! The original idea from fedochet is using proc-macro2 as backend, | ||
7 | //! we use tt instead for better intergation with RA. | ||
8 | //! | ||
9 | //! FIXME: No span and source file information is implemented yet | ||
10 | |||
11 | use crate::proc_macro::bridge::{self, server}; | ||
12 | |||
13 | use std::collections::{Bound, HashMap}; | ||
14 | use std::hash::Hash; | ||
15 | use std::iter::FromIterator; | ||
16 | use std::str::FromStr; | ||
17 | use std::{ascii, vec::IntoIter}; | ||
18 | |||
19 | type Group = tt::Subtree; | ||
20 | type TokenTree = tt::TokenTree; | ||
21 | type Punct = tt::Punct; | ||
22 | type Spacing = tt::Spacing; | ||
23 | type Literal = tt::Literal; | ||
24 | type Span = tt::TokenId; | ||
25 | |||
26 | #[derive(Debug, Clone)] | ||
27 | pub struct TokenStream { | ||
28 | pub subtree: tt::Subtree, | ||
29 | } | ||
30 | |||
31 | impl TokenStream { | ||
32 | pub fn new() -> Self { | ||
33 | TokenStream { subtree: Default::default() } | ||
34 | } | ||
35 | |||
36 | pub fn with_subtree(subtree: tt::Subtree) -> Self { | ||
37 | TokenStream { subtree } | ||
38 | } | ||
39 | |||
40 | pub fn is_empty(&self) -> bool { | ||
41 | self.subtree.token_trees.is_empty() | ||
42 | } | ||
43 | } | ||
44 | |||
45 | /// Creates a token stream containing a single token tree. | ||
46 | impl From<TokenTree> for TokenStream { | ||
47 | fn from(tree: TokenTree) -> TokenStream { | ||
48 | TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } } | ||
49 | } | ||
50 | } | ||
51 | |||
52 | /// Collects a number of token trees into a single stream. | ||
53 | impl FromIterator<TokenTree> for TokenStream { | ||
54 | fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { | ||
55 | trees.into_iter().map(TokenStream::from).collect() | ||
56 | } | ||
57 | } | ||
58 | |||
59 | /// A "flattening" operation on token streams, collects token trees | ||
60 | /// from multiple token streams into a single stream. | ||
61 | impl FromIterator<TokenStream> for TokenStream { | ||
62 | fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { | ||
63 | let mut builder = TokenStreamBuilder::new(); | ||
64 | streams.into_iter().for_each(|stream| builder.push(stream)); | ||
65 | builder.build() | ||
66 | } | ||
67 | } | ||
68 | |||
69 | impl Extend<TokenTree> for TokenStream { | ||
70 | fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) { | ||
71 | self.extend(trees.into_iter().map(TokenStream::from)); | ||
72 | } | ||
73 | } | ||
74 | |||
75 | impl Extend<TokenStream> for TokenStream { | ||
76 | fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { | ||
77 | for item in streams { | ||
78 | for tkn in item { | ||
79 | match tkn { | ||
80 | tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => { | ||
81 | self.subtree.token_trees.extend(subtree.token_trees); | ||
82 | } | ||
83 | _ => { | ||
84 | self.subtree.token_trees.push(tkn); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | type Level = crate::proc_macro::Level; | ||
93 | type LineColumn = crate::proc_macro::LineColumn; | ||
94 | type SourceFile = crate::proc_macro::SourceFile; | ||
95 | |||
96 | /// A structure representing a diagnostic message and associated children | ||
97 | /// messages. | ||
98 | #[derive(Clone, Debug)] | ||
99 | pub struct Diagnostic { | ||
100 | level: Level, | ||
101 | message: String, | ||
102 | spans: Vec<Span>, | ||
103 | children: Vec<Diagnostic>, | ||
104 | } | ||
105 | |||
106 | impl Diagnostic { | ||
107 | /// Creates a new diagnostic with the given `level` and `message`. | ||
108 | pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic { | ||
109 | Diagnostic { level, message: message.into(), spans: vec![], children: vec![] } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | // Rustc Server Ident has to be `Copyable` | ||
114 | // We use a stub here for bypassing | ||
115 | #[derive(Hash, Eq, PartialEq, Copy, Clone)] | ||
116 | pub struct IdentId(u32); | ||
117 | |||
118 | #[derive(Clone, Hash, Eq, PartialEq)] | ||
119 | struct IdentData(tt::Ident); | ||
120 | |||
121 | #[derive(Default)] | ||
122 | struct IdentInterner { | ||
123 | idents: HashMap<IdentData, u32>, | ||
124 | ident_data: Vec<IdentData>, | ||
125 | } | ||
126 | |||
127 | impl IdentInterner { | ||
128 | fn intern(&mut self, data: &IdentData) -> u32 { | ||
129 | if let Some(index) = self.idents.get(data) { | ||
130 | return *index; | ||
131 | } | ||
132 | |||
133 | let index = self.idents.len() as u32; | ||
134 | self.ident_data.push(data.clone()); | ||
135 | self.idents.insert(data.clone(), index); | ||
136 | index | ||
137 | } | ||
138 | |||
139 | fn get(&self, index: u32) -> &IdentData { | ||
140 | &self.ident_data[index as usize] | ||
141 | } | ||
142 | |||
143 | #[allow(unused)] | ||
144 | fn get_mut(&mut self, index: u32) -> &mut IdentData { | ||
145 | self.ident_data.get_mut(index as usize).expect("Should be consistent") | ||
146 | } | ||
147 | } | ||
148 | |||
149 | pub struct TokenStreamBuilder { | ||
150 | acc: TokenStream, | ||
151 | } | ||
152 | |||
153 | /// Public implementation details for the `TokenStream` type, such as iterators. | ||
154 | pub mod token_stream { | ||
155 | use std::str::FromStr; | ||
156 | |||
157 | use super::{TokenStream, TokenTree}; | ||
158 | |||
159 | /// An iterator over `TokenStream`'s `TokenTree`s. | ||
160 | /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups, | ||
161 | /// and returns whole groups as token trees. | ||
162 | impl IntoIterator for TokenStream { | ||
163 | type Item = TokenTree; | ||
164 | type IntoIter = super::IntoIter<TokenTree>; | ||
165 | |||
166 | fn into_iter(self) -> Self::IntoIter { | ||
167 | self.subtree.token_trees.into_iter() | ||
168 | } | ||
169 | } | ||
170 | |||
171 | type LexError = String; | ||
172 | |||
173 | /// Attempts to break the string into tokens and parse those tokens into a token stream. | ||
174 | /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters | ||
175 | /// or characters not existing in the language. | ||
176 | /// All tokens in the parsed stream get `Span::call_site()` spans. | ||
177 | /// | ||
178 | /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to | ||
179 | /// change these errors into `LexError`s later. | ||
180 | impl FromStr for TokenStream { | ||
181 | type Err = LexError; | ||
182 | |||
183 | fn from_str(src: &str) -> Result<TokenStream, LexError> { | ||
184 | let (subtree, _token_map) = | ||
185 | mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?; | ||
186 | |||
187 | let tt: tt::TokenTree = subtree.into(); | ||
188 | Ok(tt.into()) | ||
189 | } | ||
190 | } | ||
191 | |||
192 | impl ToString for TokenStream { | ||
193 | fn to_string(&self) -> String { | ||
194 | let tt = self.subtree.clone().into(); | ||
195 | to_text(&tt) | ||
196 | } | ||
197 | } | ||
198 | |||
199 | fn to_text(tkn: &tt::TokenTree) -> String { | ||
200 | match tkn { | ||
201 | tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(), | ||
202 | tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(), | ||
203 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char), | ||
204 | tt::TokenTree::Subtree(subtree) => { | ||
205 | let content = subtree | ||
206 | .token_trees | ||
207 | .iter() | ||
208 | .map(|tkn| { | ||
209 | let s = to_text(tkn); | ||
210 | if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn { | ||
211 | if punct.spacing == tt::Spacing::Alone { | ||
212 | return s + " "; | ||
213 | } | ||
214 | } | ||
215 | s | ||
216 | }) | ||
217 | .collect::<Vec<_>>() | ||
218 | .concat(); | ||
219 | let (open, close) = match subtree.delimiter.map(|it| it.kind) { | ||
220 | None => ("", ""), | ||
221 | Some(tt::DelimiterKind::Brace) => ("{", "}"), | ||
222 | Some(tt::DelimiterKind::Parenthesis) => ("(", ")"), | ||
223 | Some(tt::DelimiterKind::Bracket) => ("[", "]"), | ||
224 | }; | ||
225 | format!("{}{}{}", open, content, close) | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | |||
231 | impl TokenStreamBuilder { | ||
232 | fn new() -> TokenStreamBuilder { | ||
233 | TokenStreamBuilder { acc: TokenStream::new() } | ||
234 | } | ||
235 | |||
236 | fn push(&mut self, stream: TokenStream) { | ||
237 | self.acc.extend(stream.into_iter()) | ||
238 | } | ||
239 | |||
240 | fn build(self) -> TokenStream { | ||
241 | self.acc | ||
242 | } | ||
243 | } | ||
244 | |||
245 | #[derive(Clone)] | ||
246 | pub struct TokenStreamIter { | ||
247 | trees: IntoIter<TokenTree>, | ||
248 | } | ||
249 | |||
250 | #[derive(Default)] | ||
251 | pub struct Rustc { | ||
252 | ident_interner: IdentInterner, | ||
253 | // FIXME: store span information here. | ||
254 | } | ||
255 | |||
256 | impl server::Types for Rustc { | ||
257 | type TokenStream = TokenStream; | ||
258 | type TokenStreamBuilder = TokenStreamBuilder; | ||
259 | type TokenStreamIter = TokenStreamIter; | ||
260 | type Group = Group; | ||
261 | type Punct = Punct; | ||
262 | type Ident = IdentId; | ||
263 | type Literal = Literal; | ||
264 | type SourceFile = SourceFile; | ||
265 | type Diagnostic = Diagnostic; | ||
266 | type Span = Span; | ||
267 | type MultiSpan = Vec<Span>; | ||
268 | } | ||
269 | |||
270 | impl server::TokenStream for Rustc { | ||
271 | fn new(&mut self) -> Self::TokenStream { | ||
272 | Self::TokenStream::new() | ||
273 | } | ||
274 | |||
275 | fn is_empty(&mut self, stream: &Self::TokenStream) -> bool { | ||
276 | stream.is_empty() | ||
277 | } | ||
278 | fn from_str(&mut self, src: &str) -> Self::TokenStream { | ||
279 | Self::TokenStream::from_str(src).expect("cannot parse string") | ||
280 | } | ||
281 | fn to_string(&mut self, stream: &Self::TokenStream) -> String { | ||
282 | stream.to_string() | ||
283 | } | ||
284 | fn from_token_tree( | ||
285 | &mut self, | ||
286 | tree: bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>, | ||
287 | ) -> Self::TokenStream { | ||
288 | match tree { | ||
289 | bridge::TokenTree::Group(group) => { | ||
290 | let tree = TokenTree::from(group); | ||
291 | Self::TokenStream::from_iter(vec![tree]) | ||
292 | } | ||
293 | |||
294 | bridge::TokenTree::Ident(IdentId(index)) => { | ||
295 | let IdentData(ident) = self.ident_interner.get(index).clone(); | ||
296 | let ident: tt::Ident = ident; | ||
297 | let leaf = tt::Leaf::from(ident); | ||
298 | let tree = TokenTree::from(leaf); | ||
299 | Self::TokenStream::from_iter(vec![tree]) | ||
300 | } | ||
301 | |||
302 | bridge::TokenTree::Literal(literal) => { | ||
303 | let leaf = tt::Leaf::from(literal); | ||
304 | let tree = TokenTree::from(leaf); | ||
305 | Self::TokenStream::from_iter(vec![tree]) | ||
306 | } | ||
307 | |||
308 | bridge::TokenTree::Punct(p) => { | ||
309 | let leaf = tt::Leaf::from(p); | ||
310 | let tree = TokenTree::from(leaf); | ||
311 | Self::TokenStream::from_iter(vec![tree]) | ||
312 | } | ||
313 | } | ||
314 | } | ||
315 | |||
316 | fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter { | ||
317 | let trees: Vec<TokenTree> = stream.into_iter().collect(); | ||
318 | TokenStreamIter { trees: trees.into_iter() } | ||
319 | } | ||
320 | } | ||
321 | |||
322 | impl server::TokenStreamBuilder for Rustc { | ||
323 | fn new(&mut self) -> Self::TokenStreamBuilder { | ||
324 | Self::TokenStreamBuilder::new() | ||
325 | } | ||
326 | fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) { | ||
327 | builder.push(stream) | ||
328 | } | ||
329 | fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream { | ||
330 | builder.build() | ||
331 | } | ||
332 | } | ||
333 | |||
334 | impl server::TokenStreamIter for Rustc { | ||
335 | fn next( | ||
336 | &mut self, | ||
337 | iter: &mut Self::TokenStreamIter, | ||
338 | ) -> Option<bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> { | ||
339 | iter.trees.next().map(|tree| match tree { | ||
340 | TokenTree::Subtree(group) => bridge::TokenTree::Group(group), | ||
341 | TokenTree::Leaf(tt::Leaf::Ident(ident)) => { | ||
342 | bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident)))) | ||
343 | } | ||
344 | TokenTree::Leaf(tt::Leaf::Literal(literal)) => bridge::TokenTree::Literal(literal), | ||
345 | TokenTree::Leaf(tt::Leaf::Punct(punct)) => bridge::TokenTree::Punct(punct), | ||
346 | }) | ||
347 | } | ||
348 | } | ||
349 | |||
350 | fn delim_to_internal(d: bridge::Delimiter) -> Option<tt::Delimiter> { | ||
351 | let kind = match d { | ||
352 | bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis, | ||
353 | bridge::Delimiter::Brace => tt::DelimiterKind::Brace, | ||
354 | bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket, | ||
355 | bridge::Delimiter::None => return None, | ||
356 | }; | ||
357 | Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind }) | ||
358 | } | ||
359 | |||
360 | fn delim_to_external(d: Option<tt::Delimiter>) -> bridge::Delimiter { | ||
361 | match d.map(|it| it.kind) { | ||
362 | Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis, | ||
363 | Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace, | ||
364 | Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket, | ||
365 | None => bridge::Delimiter::None, | ||
366 | } | ||
367 | } | ||
368 | |||
369 | fn spacing_to_internal(spacing: bridge::Spacing) -> Spacing { | ||
370 | match spacing { | ||
371 | bridge::Spacing::Alone => Spacing::Alone, | ||
372 | bridge::Spacing::Joint => Spacing::Joint, | ||
373 | } | ||
374 | } | ||
375 | |||
376 | fn spacing_to_external(spacing: Spacing) -> bridge::Spacing { | ||
377 | match spacing { | ||
378 | Spacing::Alone => bridge::Spacing::Alone, | ||
379 | Spacing::Joint => bridge::Spacing::Joint, | ||
380 | } | ||
381 | } | ||
382 | |||
383 | impl server::Group for Rustc { | ||
384 | fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group { | ||
385 | Self::Group { | ||
386 | delimiter: delim_to_internal(delimiter), | ||
387 | token_trees: stream.subtree.token_trees, | ||
388 | } | ||
389 | } | ||
390 | fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter { | ||
391 | delim_to_external(group.delimiter) | ||
392 | } | ||
393 | |||
394 | // NOTE: Return value of do not include delimiter | ||
395 | fn stream(&mut self, group: &Self::Group) -> Self::TokenStream { | ||
396 | TokenStream { | ||
397 | subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() }, | ||
398 | } | ||
399 | } | ||
400 | |||
401 | fn span(&mut self, group: &Self::Group) -> Self::Span { | ||
402 | group.delimiter.map(|it| it.id).unwrap_or_else(|| tt::TokenId::unspecified()) | ||
403 | } | ||
404 | |||
405 | fn set_span(&mut self, _group: &mut Self::Group, _span: Self::Span) { | ||
406 | // FIXME handle span | ||
407 | } | ||
408 | |||
409 | fn span_open(&mut self, _group: &Self::Group) -> Self::Span { | ||
410 | // FIXME handle span | ||
411 | // MySpan(self.span_interner.intern(&MySpanData(group.span_open()))) | ||
412 | tt::TokenId::unspecified() | ||
413 | } | ||
414 | |||
415 | fn span_close(&mut self, _group: &Self::Group) -> Self::Span { | ||
416 | // FIXME handle span | ||
417 | tt::TokenId::unspecified() | ||
418 | } | ||
419 | } | ||
420 | |||
421 | impl server::Punct for Rustc { | ||
422 | fn new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct { | ||
423 | tt::Punct { | ||
424 | char: ch, | ||
425 | spacing: spacing_to_internal(spacing), | ||
426 | id: tt::TokenId::unspecified(), | ||
427 | } | ||
428 | } | ||
429 | fn as_char(&mut self, punct: Self::Punct) -> char { | ||
430 | punct.char | ||
431 | } | ||
432 | fn spacing(&mut self, punct: Self::Punct) -> bridge::Spacing { | ||
433 | spacing_to_external(punct.spacing) | ||
434 | } | ||
435 | fn span(&mut self, _punct: Self::Punct) -> Self::Span { | ||
436 | // FIXME handle span | ||
437 | tt::TokenId::unspecified() | ||
438 | } | ||
439 | fn with_span(&mut self, punct: Self::Punct, _span: Self::Span) -> Self::Punct { | ||
440 | // FIXME handle span | ||
441 | punct | ||
442 | } | ||
443 | } | ||
444 | |||
445 | impl server::Ident for Rustc { | ||
446 | fn new(&mut self, string: &str, _span: Self::Span, _is_raw: bool) -> Self::Ident { | ||
447 | IdentId( | ||
448 | self.ident_interner.intern(&IdentData(tt::Ident { | ||
449 | text: string.into(), | ||
450 | id: tt::TokenId::unspecified(), | ||
451 | })), | ||
452 | ) | ||
453 | } | ||
454 | |||
455 | fn span(&mut self, _ident: Self::Ident) -> Self::Span { | ||
456 | // FIXME handle span | ||
457 | tt::TokenId::unspecified() | ||
458 | } | ||
459 | fn with_span(&mut self, ident: Self::Ident, _span: Self::Span) -> Self::Ident { | ||
460 | // FIXME handle span | ||
461 | ident | ||
462 | } | ||
463 | } | ||
464 | |||
465 | impl server::Literal for Rustc { | ||
466 | fn debug_kind(&mut self, _literal: &Self::Literal) -> String { | ||
467 | // r-a: debug_kind and suffix are unsupported; corresponding client code has been changed to not call these. | ||
468 | // They must still be present to be ABI-compatible and work with upstream proc_macro. | ||
469 | "".to_owned() | ||
470 | } | ||
471 | fn symbol(&mut self, literal: &Self::Literal) -> String { | ||
472 | literal.text.to_string() | ||
473 | } | ||
474 | fn suffix(&mut self, _literal: &Self::Literal) -> Option<String> { | ||
475 | None | ||
476 | } | ||
477 | |||
478 | fn integer(&mut self, n: &str) -> Self::Literal { | ||
479 | let n: i128 = n.parse().unwrap(); | ||
480 | Literal { text: n.to_string().into(), id: tt::TokenId::unspecified() } | ||
481 | } | ||
482 | |||
483 | fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal { | ||
484 | macro_rules! def_suffixed_integer { | ||
485 | ($kind:ident, $($ty:ty),*) => { | ||
486 | match $kind { | ||
487 | $( | ||
488 | stringify!($ty) => { | ||
489 | let n: $ty = n.parse().unwrap(); | ||
490 | format!(concat!("{}", stringify!($ty)), n) | ||
491 | } | ||
492 | )* | ||
493 | _ => unimplemented!("unknown args for typed_integer: n {}, kind {}", n, $kind), | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | |||
498 | let text = | ||
499 | def_suffixed_integer! {kind, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128}; | ||
500 | |||
501 | Literal { text: text.into(), id: tt::TokenId::unspecified() } | ||
502 | } | ||
503 | |||
504 | fn float(&mut self, n: &str) -> Self::Literal { | ||
505 | let n: f64 = n.parse().unwrap(); | ||
506 | let mut text = f64::to_string(&n); | ||
507 | if !text.contains('.') { | ||
508 | text += ".0" | ||
509 | } | ||
510 | Literal { text: text.into(), id: tt::TokenId::unspecified() } | ||
511 | } | ||
512 | |||
513 | fn f32(&mut self, n: &str) -> Self::Literal { | ||
514 | let n: f32 = n.parse().unwrap(); | ||
515 | let text = format!("{}f32", n); | ||
516 | Literal { text: text.into(), id: tt::TokenId::unspecified() } | ||
517 | } | ||
518 | |||
519 | fn f64(&mut self, n: &str) -> Self::Literal { | ||
520 | let n: f64 = n.parse().unwrap(); | ||
521 | let text = format!("{}f64", n); | ||
522 | Literal { text: text.into(), id: tt::TokenId::unspecified() } | ||
523 | } | ||
524 | |||
525 | fn string(&mut self, string: &str) -> Self::Literal { | ||
526 | let mut escaped = String::new(); | ||
527 | for ch in string.chars() { | ||
528 | escaped.extend(ch.escape_debug()); | ||
529 | } | ||
530 | Literal { text: format!("\"{}\"", escaped).into(), id: tt::TokenId::unspecified() } | ||
531 | } | ||
532 | |||
533 | fn character(&mut self, ch: char) -> Self::Literal { | ||
534 | Literal { text: format!("'{}'", ch).into(), id: tt::TokenId::unspecified() } | ||
535 | } | ||
536 | |||
537 | fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal { | ||
538 | let string = bytes | ||
539 | .iter() | ||
540 | .cloned() | ||
541 | .flat_map(ascii::escape_default) | ||
542 | .map(Into::<char>::into) | ||
543 | .collect::<String>(); | ||
544 | |||
545 | Literal { text: format!("b\"{}\"", string).into(), id: tt::TokenId::unspecified() } | ||
546 | } | ||
547 | |||
548 | fn span(&mut self, literal: &Self::Literal) -> Self::Span { | ||
549 | literal.id | ||
550 | } | ||
551 | |||
552 | fn set_span(&mut self, _literal: &mut Self::Literal, _span: Self::Span) { | ||
553 | // FIXME handle span | ||
554 | } | ||
555 | |||
556 | fn subspan( | ||
557 | &mut self, | ||
558 | _literal: &Self::Literal, | ||
559 | _start: Bound<usize>, | ||
560 | _end: Bound<usize>, | ||
561 | ) -> Option<Self::Span> { | ||
562 | // FIXME handle span | ||
563 | None | ||
564 | } | ||
565 | } | ||
566 | |||
567 | impl server::SourceFile for Rustc { | ||
568 | fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool { | ||
569 | file1.eq(file2) | ||
570 | } | ||
571 | fn path(&mut self, file: &Self::SourceFile) -> String { | ||
572 | String::from( | ||
573 | file.path().to_str().expect("non-UTF8 file path in `proc_macro::SourceFile::path`"), | ||
574 | ) | ||
575 | } | ||
576 | fn is_real(&mut self, file: &Self::SourceFile) -> bool { | ||
577 | file.is_real() | ||
578 | } | ||
579 | } | ||
580 | |||
581 | impl server::Diagnostic for Rustc { | ||
582 | fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic { | ||
583 | let mut diag = Diagnostic::new(level, msg); | ||
584 | diag.spans = spans; | ||
585 | diag | ||
586 | } | ||
587 | |||
588 | fn sub( | ||
589 | &mut self, | ||
590 | _diag: &mut Self::Diagnostic, | ||
591 | _level: Level, | ||
592 | _msg: &str, | ||
593 | _spans: Self::MultiSpan, | ||
594 | ) { | ||
595 | // FIXME handle diagnostic | ||
596 | // | ||
597 | } | ||
598 | |||
599 | fn emit(&mut self, _diag: Self::Diagnostic) { | ||
600 | // FIXME handle diagnostic | ||
601 | // diag.emit() | ||
602 | } | ||
603 | } | ||
604 | |||
605 | impl server::Span for Rustc { | ||
606 | fn debug(&mut self, span: Self::Span) -> String { | ||
607 | format!("{:?}", span.0) | ||
608 | } | ||
609 | fn def_site(&mut self) -> Self::Span { | ||
610 | // MySpan(self.span_interner.intern(&MySpanData(Span::def_site()))) | ||
611 | // FIXME handle span | ||
612 | tt::TokenId::unspecified() | ||
613 | } | ||
614 | fn call_site(&mut self) -> Self::Span { | ||
615 | // MySpan(self.span_interner.intern(&MySpanData(Span::call_site()))) | ||
616 | // FIXME handle span | ||
617 | tt::TokenId::unspecified() | ||
618 | } | ||
619 | fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile { | ||
620 | // let MySpanData(span) = self.span_interner.get(span.0); | ||
621 | unimplemented!() | ||
622 | } | ||
623 | |||
624 | /// Recent feature, not yet in the proc_macro | ||
625 | /// | ||
626 | /// See PR: | ||
627 | /// https://github.com/rust-lang/rust/pull/55780 | ||
628 | fn source_text(&mut self, _span: Self::Span) -> Option<String> { | ||
629 | None | ||
630 | } | ||
631 | |||
632 | fn parent(&mut self, _span: Self::Span) -> Option<Self::Span> { | ||
633 | // FIXME handle span | ||
634 | None | ||
635 | } | ||
636 | fn source(&mut self, span: Self::Span) -> Self::Span { | ||
637 | // FIXME handle span | ||
638 | span | ||
639 | } | ||
640 | fn start(&mut self, _span: Self::Span) -> LineColumn { | ||
641 | // FIXME handle span | ||
642 | LineColumn { line: 0, column: 0 } | ||
643 | } | ||
644 | fn end(&mut self, _span: Self::Span) -> LineColumn { | ||
645 | // FIXME handle span | ||
646 | LineColumn { line: 0, column: 0 } | ||
647 | } | ||
648 | fn join(&mut self, _first: Self::Span, _second: Self::Span) -> Option<Self::Span> { | ||
649 | None | ||
650 | } | ||
651 | fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span { | ||
652 | // FIXME handle span | ||
653 | tt::TokenId::unspecified() | ||
654 | } | ||
655 | |||
656 | fn mixed_site(&mut self) -> Self::Span { | ||
657 | // FIXME handle span | ||
658 | tt::TokenId::unspecified() | ||
659 | } | ||
660 | } | ||
661 | |||
662 | impl server::MultiSpan for Rustc { | ||
663 | fn new(&mut self) -> Self::MultiSpan { | ||
664 | // FIXME handle span | ||
665 | vec![] | ||
666 | } | ||
667 | |||
668 | fn push(&mut self, other: &mut Self::MultiSpan, span: Self::Span) { | ||
669 | //TODP | ||
670 | other.push(span) | ||
671 | } | ||
672 | } | ||
673 | |||
674 | #[cfg(test)] | ||
675 | mod tests { | ||
676 | use super::*; | ||
677 | use crate::proc_macro::bridge::server::Literal; | ||
678 | |||
679 | #[test] | ||
680 | fn test_rustc_server_literals() { | ||
681 | let mut srv = Rustc { ident_interner: IdentInterner::default() }; | ||
682 | assert_eq!(srv.integer("1234").text, "1234"); | ||
683 | |||
684 | assert_eq!(srv.typed_integer("12", "u8").text, "12u8"); | ||
685 | assert_eq!(srv.typed_integer("255", "u16").text, "255u16"); | ||
686 | assert_eq!(srv.typed_integer("1234", "u32").text, "1234u32"); | ||
687 | assert_eq!(srv.typed_integer("15846685", "u64").text, "15846685u64"); | ||
688 | assert_eq!(srv.typed_integer("15846685258", "u128").text, "15846685258u128"); | ||
689 | assert_eq!(srv.typed_integer("156788984", "usize").text, "156788984usize"); | ||
690 | assert_eq!(srv.typed_integer("127", "i8").text, "127i8"); | ||
691 | assert_eq!(srv.typed_integer("255", "i16").text, "255i16"); | ||
692 | assert_eq!(srv.typed_integer("1234", "i32").text, "1234i32"); | ||
693 | assert_eq!(srv.typed_integer("15846685", "i64").text, "15846685i64"); | ||
694 | assert_eq!(srv.typed_integer("15846685258", "i128").text, "15846685258i128"); | ||
695 | assert_eq!(srv.float("0").text, "0.0"); | ||
696 | assert_eq!(srv.float("15684.5867").text, "15684.5867"); | ||
697 | assert_eq!(srv.f32("15684.58").text, "15684.58f32"); | ||
698 | assert_eq!(srv.f64("15684.58").text, "15684.58f64"); | ||
699 | |||
700 | assert_eq!(srv.string("hello_world").text, "\"hello_world\""); | ||
701 | assert_eq!(srv.character('c').text, "'c'"); | ||
702 | assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\""); | ||
703 | } | ||
704 | } | ||