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 integration with RA.
8 //!
9 //! FIXME: No span and source file information is implemented yet
10
11 use super::proc_macro::bridge::{self, server};
12
13 use std::collections::HashMap;
14 use std::hash::Hash;
15 use std::iter::FromIterator;
16 use std::ops::Bound;
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 token_trees: Vec<TokenTree>,
29 }
30
31 impl TokenStream {
new() -> Self32 pub fn new() -> Self {
33 TokenStream { token_trees: Default::default() }
34 }
35
with_subtree(subtree: tt::Subtree) -> Self36 pub fn with_subtree(subtree: tt::Subtree) -> Self {
37 if subtree.delimiter.is_some() {
38 TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
39 } else {
40 TokenStream { token_trees: subtree.token_trees }
41 }
42 }
43
into_subtree(self) -> tt::Subtree44 pub fn into_subtree(self) -> tt::Subtree {
45 tt::Subtree { delimiter: None, token_trees: self.token_trees }
46 }
47
is_empty(&self) -> bool48 pub fn is_empty(&self) -> bool {
49 self.token_trees.is_empty()
50 }
51 }
52
53 /// Creates a token stream containing a single token tree.
54 impl From<TokenTree> for TokenStream {
from(tree: TokenTree) -> TokenStream55 fn from(tree: TokenTree) -> TokenStream {
56 TokenStream { token_trees: vec![tree] }
57 }
58 }
59
60 /// Collects a number of token trees into a single stream.
61 impl FromIterator<TokenTree> for TokenStream {
from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self62 fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
63 trees.into_iter().map(TokenStream::from).collect()
64 }
65 }
66
67 /// A "flattening" operation on token streams, collects token trees
68 /// from multiple token streams into a single stream.
69 impl FromIterator<TokenStream> for TokenStream {
from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self70 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
71 let mut builder = TokenStreamBuilder::new();
72 streams.into_iter().for_each(|stream| builder.push(stream));
73 builder.build()
74 }
75 }
76
77 impl Extend<TokenTree> for TokenStream {
extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I)78 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
79 self.extend(trees.into_iter().map(TokenStream::from));
80 }
81 }
82
83 impl Extend<TokenStream> for TokenStream {
extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I)84 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
85 for item in streams {
86 for tkn in item {
87 match tkn {
88 tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
89 self.token_trees.extend(subtree.token_trees);
90 }
91 _ => {
92 self.token_trees.push(tkn);
93 }
94 }
95 }
96 }
97 }
98 }
99
100 type Level = super::proc_macro::Level;
101 type LineColumn = super::proc_macro::LineColumn;
102 type SourceFile = super::proc_macro::SourceFile;
103
104 /// A structure representing a diagnostic message and associated children
105 /// messages.
106 #[derive(Clone, Debug)]
107 pub struct Diagnostic {
108 level: Level,
109 message: String,
110 spans: Vec<Span>,
111 children: Vec<Diagnostic>,
112 }
113
114 impl Diagnostic {
115 /// Creates a new diagnostic with the given `level` and `message`.
new<T: Into<String>>(level: Level, message: T) -> Diagnostic116 pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
117 Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
118 }
119 }
120
121 // Rustc Server Ident has to be `Copyable`
122 // We use a stub here for bypassing
123 #[derive(Hash, Eq, PartialEq, Copy, Clone)]
124 pub struct IdentId(u32);
125
126 #[derive(Clone, Hash, Eq, PartialEq)]
127 struct IdentData(tt::Ident);
128
129 #[derive(Default)]
130 struct IdentInterner {
131 idents: HashMap<IdentData, u32>,
132 ident_data: Vec<IdentData>,
133 }
134
135 impl IdentInterner {
intern(&mut self, data: &IdentData) -> u32136 fn intern(&mut self, data: &IdentData) -> u32 {
137 if let Some(index) = self.idents.get(data) {
138 return *index;
139 }
140
141 let index = self.idents.len() as u32;
142 self.ident_data.push(data.clone());
143 self.idents.insert(data.clone(), index);
144 index
145 }
146
get(&self, index: u32) -> &IdentData147 fn get(&self, index: u32) -> &IdentData {
148 &self.ident_data[index as usize]
149 }
150
151 #[allow(unused)]
get_mut(&mut self, index: u32) -> &mut IdentData152 fn get_mut(&mut self, index: u32) -> &mut IdentData {
153 self.ident_data.get_mut(index as usize).expect("Should be consistent")
154 }
155 }
156
157 pub struct TokenStreamBuilder {
158 acc: TokenStream,
159 }
160
161 /// Public implementation details for the `TokenStream` type, such as iterators.
162 pub mod token_stream {
163 use std::str::FromStr;
164
165 use super::{TokenStream, TokenTree};
166
167 /// An iterator over `TokenStream`'s `TokenTree`s.
168 /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
169 /// and returns whole groups as token trees.
170 impl IntoIterator for TokenStream {
171 type Item = TokenTree;
172 type IntoIter = super::IntoIter<TokenTree>;
173
into_iter(self) -> Self::IntoIter174 fn into_iter(self) -> Self::IntoIter {
175 self.token_trees.into_iter()
176 }
177 }
178
179 type LexError = String;
180
181 /// Attempts to break the string into tokens and parse those tokens into a token stream.
182 /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
183 /// or characters not existing in the language.
184 /// All tokens in the parsed stream get `Span::call_site()` spans.
185 ///
186 /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
187 /// change these errors into `LexError`s later.
188 impl FromStr for TokenStream {
189 type Err = LexError;
190
from_str(src: &str) -> Result<TokenStream, LexError>191 fn from_str(src: &str) -> Result<TokenStream, LexError> {
192 let (subtree, _token_map) =
193 mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?;
194
195 let subtree = subtree_replace_token_ids_with_unspecified(subtree);
196 Ok(TokenStream::with_subtree(subtree))
197 }
198 }
199
200 impl ToString for TokenStream {
to_string(&self) -> String201 fn to_string(&self) -> String {
202 tt::pretty(&self.token_trees)
203 }
204 }
205
subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree206 fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree {
207 tt::Subtree {
208 delimiter: subtree
209 .delimiter
210 .map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }),
211 token_trees: subtree
212 .token_trees
213 .into_iter()
214 .map(token_tree_replace_token_ids_with_unspecified)
215 .collect(),
216 }
217 }
218
token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree219 fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree {
220 match tt {
221 tt::TokenTree::Leaf(leaf) => {
222 tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf))
223 }
224 tt::TokenTree::Subtree(subtree) => {
225 tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree))
226 }
227 }
228 }
229
leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf230 fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf {
231 match leaf {
232 tt::Leaf::Literal(lit) => {
233 tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit })
234 }
235 tt::Leaf::Punct(punct) => {
236 tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct })
237 }
238 tt::Leaf::Ident(ident) => {
239 tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident })
240 }
241 }
242 }
243 }
244
245 impl TokenStreamBuilder {
new() -> TokenStreamBuilder246 fn new() -> TokenStreamBuilder {
247 TokenStreamBuilder { acc: TokenStream::new() }
248 }
249
push(&mut self, stream: TokenStream)250 fn push(&mut self, stream: TokenStream) {
251 self.acc.extend(stream.into_iter())
252 }
253
build(self) -> TokenStream254 fn build(self) -> TokenStream {
255 self.acc
256 }
257 }
258
259 pub struct FreeFunctions;
260
261 #[derive(Clone)]
262 pub struct TokenStreamIter {
263 trees: IntoIter<TokenTree>,
264 }
265
266 #[derive(Default)]
267 pub struct Rustc {
268 ident_interner: IdentInterner,
269 // FIXME: store span information here.
270 }
271
272 impl server::Types for Rustc {
273 type FreeFunctions = FreeFunctions;
274 type TokenStream = TokenStream;
275 type TokenStreamBuilder = TokenStreamBuilder;
276 type TokenStreamIter = TokenStreamIter;
277 type Group = Group;
278 type Punct = Punct;
279 type Ident = IdentId;
280 type Literal = Literal;
281 type SourceFile = SourceFile;
282 type Diagnostic = Diagnostic;
283 type Span = Span;
284 type MultiSpan = Vec<Span>;
285 }
286
287 impl server::FreeFunctions for Rustc {
track_env_var(&mut self, _var: &str, _value: Option<&str>)288 fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {
289 // FIXME: track env var accesses
290 // https://github.com/rust-lang/rust/pull/71858
291 }
track_path(&mut self, _path: &str)292 fn track_path(&mut self, _path: &str) {}
293 }
294
295 impl server::TokenStream for Rustc {
new(&mut self) -> Self::TokenStream296 fn new(&mut self) -> Self::TokenStream {
297 Self::TokenStream::new()
298 }
299
is_empty(&mut self, stream: &Self::TokenStream) -> bool300 fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
301 stream.is_empty()
302 }
from_str(&mut self, src: &str) -> Self::TokenStream303 fn from_str(&mut self, src: &str) -> Self::TokenStream {
304 use std::str::FromStr;
305
306 Self::TokenStream::from_str(src).expect("cannot parse string")
307 }
to_string(&mut self, stream: &Self::TokenStream) -> String308 fn to_string(&mut self, stream: &Self::TokenStream) -> String {
309 stream.to_string()
310 }
from_token_tree( &mut self, tree: bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>, ) -> Self::TokenStream311 fn from_token_tree(
312 &mut self,
313 tree: bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
314 ) -> Self::TokenStream {
315 match tree {
316 bridge::TokenTree::Group(group) => {
317 let tree = TokenTree::from(group);
318 Self::TokenStream::from_iter(vec![tree])
319 }
320
321 bridge::TokenTree::Ident(IdentId(index)) => {
322 let IdentData(ident) = self.ident_interner.get(index).clone();
323 let ident: tt::Ident = ident;
324 let leaf = tt::Leaf::from(ident);
325 let tree = TokenTree::from(leaf);
326 Self::TokenStream::from_iter(vec![tree])
327 }
328
329 bridge::TokenTree::Literal(literal) => {
330 let leaf = tt::Leaf::from(literal);
331 let tree = TokenTree::from(leaf);
332 Self::TokenStream::from_iter(vec![tree])
333 }
334
335 bridge::TokenTree::Punct(p) => {
336 let leaf = tt::Leaf::from(p);
337 let tree = TokenTree::from(leaf);
338 Self::TokenStream::from_iter(vec![tree])
339 }
340 }
341 }
342
into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter343 fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
344 let trees: Vec<TokenTree> = stream.into_iter().collect();
345 TokenStreamIter { trees: trees.into_iter() }
346 }
347 }
348
349 impl server::TokenStreamBuilder for Rustc {
new(&mut self) -> Self::TokenStreamBuilder350 fn new(&mut self) -> Self::TokenStreamBuilder {
351 Self::TokenStreamBuilder::new()
352 }
push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream)353 fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) {
354 builder.push(stream)
355 }
build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream356 fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
357 builder.build()
358 }
359 }
360
361 impl server::TokenStreamIter for Rustc {
next( &mut self, iter: &mut Self::TokenStreamIter, ) -> Option<bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>>362 fn next(
363 &mut self,
364 iter: &mut Self::TokenStreamIter,
365 ) -> Option<bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
366 iter.trees.next().map(|tree| match tree {
367 TokenTree::Subtree(group) => bridge::TokenTree::Group(group),
368 TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
369 bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident))))
370 }
371 TokenTree::Leaf(tt::Leaf::Literal(literal)) => bridge::TokenTree::Literal(literal),
372 TokenTree::Leaf(tt::Leaf::Punct(punct)) => bridge::TokenTree::Punct(punct),
373 })
374 }
375 }
376
delim_to_internal(d: bridge::Delimiter) -> Option<tt::Delimiter>377 fn delim_to_internal(d: bridge::Delimiter) -> Option<tt::Delimiter> {
378 let kind = match d {
379 bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
380 bridge::Delimiter::Brace => tt::DelimiterKind::Brace,
381 bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket,
382 bridge::Delimiter::None => return None,
383 };
384 Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind })
385 }
386
delim_to_external(d: Option<tt::Delimiter>) -> bridge::Delimiter387 fn delim_to_external(d: Option<tt::Delimiter>) -> bridge::Delimiter {
388 match d.map(|it| it.kind) {
389 Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis,
390 Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace,
391 Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket,
392 None => bridge::Delimiter::None,
393 }
394 }
395
spacing_to_internal(spacing: bridge::Spacing) -> Spacing396 fn spacing_to_internal(spacing: bridge::Spacing) -> Spacing {
397 match spacing {
398 bridge::Spacing::Alone => Spacing::Alone,
399 bridge::Spacing::Joint => Spacing::Joint,
400 }
401 }
402
spacing_to_external(spacing: Spacing) -> bridge::Spacing403 fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
404 match spacing {
405 Spacing::Alone => bridge::Spacing::Alone,
406 Spacing::Joint => bridge::Spacing::Joint,
407 }
408 }
409
410 impl server::Group for Rustc {
new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group411 fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group {
412 Self::Group { delimiter: delim_to_internal(delimiter), token_trees: stream.token_trees }
413 }
delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter414 fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
415 delim_to_external(group.delimiter)
416 }
417
418 // NOTE: Return value of do not include delimiter
stream(&mut self, group: &Self::Group) -> Self::TokenStream419 fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
420 TokenStream { token_trees: group.token_trees.clone() }
421 }
422
span(&mut self, group: &Self::Group) -> Self::Span423 fn span(&mut self, group: &Self::Group) -> Self::Span {
424 group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
425 }
426
set_span(&mut self, group: &mut Self::Group, span: Self::Span)427 fn set_span(&mut self, group: &mut Self::Group, span: Self::Span) {
428 if let Some(delim) = &mut group.delimiter {
429 delim.id = span;
430 }
431 }
432
span_open(&mut self, group: &Self::Group) -> Self::Span433 fn span_open(&mut self, group: &Self::Group) -> Self::Span {
434 // FIXME we only store one `TokenId` for the delimiters
435 group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
436 }
437
span_close(&mut self, group: &Self::Group) -> Self::Span438 fn span_close(&mut self, group: &Self::Group) -> Self::Span {
439 // FIXME we only store one `TokenId` for the delimiters
440 group.delimiter.map(|it| it.id).unwrap_or_else(tt::TokenId::unspecified)
441 }
442 }
443
444 impl server::Punct for Rustc {
new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct445 fn new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct {
446 tt::Punct {
447 char: ch,
448 spacing: spacing_to_internal(spacing),
449 id: tt::TokenId::unspecified(),
450 }
451 }
as_char(&mut self, punct: Self::Punct) -> char452 fn as_char(&mut self, punct: Self::Punct) -> char {
453 punct.char
454 }
spacing(&mut self, punct: Self::Punct) -> bridge::Spacing455 fn spacing(&mut self, punct: Self::Punct) -> bridge::Spacing {
456 spacing_to_external(punct.spacing)
457 }
span(&mut self, punct: Self::Punct) -> Self::Span458 fn span(&mut self, punct: Self::Punct) -> Self::Span {
459 punct.id
460 }
with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct461 fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
462 tt::Punct { id: span, ..punct }
463 }
464 }
465
466 impl server::Ident for Rustc {
new(&mut self, string: &str, _span: Self::Span, _is_raw: bool) -> Self::Ident467 fn new(&mut self, string: &str, _span: Self::Span, _is_raw: bool) -> Self::Ident {
468 IdentId(
469 self.ident_interner.intern(&IdentData(tt::Ident {
470 text: string.into(),
471 id: tt::TokenId::unspecified(),
472 })),
473 )
474 }
475
span(&mut self, ident: Self::Ident) -> Self::Span476 fn span(&mut self, ident: Self::Ident) -> Self::Span {
477 self.ident_interner.get(ident.0).0.id
478 }
with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident479 fn with_span(&mut self, ident: Self::Ident, span: Self::Span) -> Self::Ident {
480 let data = self.ident_interner.get(ident.0);
481 let new = IdentData(tt::Ident { id: span, ..data.0.clone() });
482 IdentId(self.ident_interner.intern(&new))
483 }
484 }
485
486 impl server::Literal for Rustc {
debug_kind(&mut self, _literal: &Self::Literal) -> String487 fn debug_kind(&mut self, _literal: &Self::Literal) -> String {
488 // r-a: debug_kind and suffix are unsupported; corresponding client code has been changed to not call these.
489 // They must still be present to be ABI-compatible and work with upstream proc_macro.
490 "".to_owned()
491 }
from_str(&mut self, s: &str) -> Result<Self::Literal, ()>492 fn from_str(&mut self, s: &str) -> Result<Self::Literal, ()> {
493 Ok(Literal { text: s.into(), id: tt::TokenId::unspecified() })
494 }
symbol(&mut self, literal: &Self::Literal) -> String495 fn symbol(&mut self, literal: &Self::Literal) -> String {
496 literal.text.to_string()
497 }
suffix(&mut self, _literal: &Self::Literal) -> Option<String>498 fn suffix(&mut self, _literal: &Self::Literal) -> Option<String> {
499 None
500 }
501
to_string(&mut self, literal: &Self::Literal) -> String502 fn to_string(&mut self, literal: &Self::Literal) -> String {
503 literal.to_string()
504 }
505
integer(&mut self, n: &str) -> Self::Literal506 fn integer(&mut self, n: &str) -> Self::Literal {
507 let n = match n.parse::<i128>() {
508 Ok(n) => n.to_string(),
509 Err(_) => n.parse::<u128>().unwrap().to_string(),
510 };
511 Literal { text: n.into(), id: tt::TokenId::unspecified() }
512 }
513
typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal514 fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
515 macro_rules! def_suffixed_integer {
516 ($kind:ident, $($ty:ty),*) => {
517 match $kind {
518 $(
519 stringify!($ty) => {
520 let n: $ty = n.parse().unwrap();
521 format!(concat!("{}", stringify!($ty)), n)
522 }
523 )*
524 _ => unimplemented!("unknown args for typed_integer: n {}, kind {}", n, $kind),
525 }
526 }
527 }
528
529 let text = def_suffixed_integer! {kind, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize};
530
531 Literal { text: text.into(), id: tt::TokenId::unspecified() }
532 }
533
float(&mut self, n: &str) -> Self::Literal534 fn float(&mut self, n: &str) -> Self::Literal {
535 let n: f64 = n.parse().unwrap();
536 let mut text = f64::to_string(&n);
537 if !text.contains('.') {
538 text += ".0"
539 }
540 Literal { text: text.into(), id: tt::TokenId::unspecified() }
541 }
542
f32(&mut self, n: &str) -> Self::Literal543 fn f32(&mut self, n: &str) -> Self::Literal {
544 let n: f32 = n.parse().unwrap();
545 let text = format!("{}f32", n);
546 Literal { text: text.into(), id: tt::TokenId::unspecified() }
547 }
548
f64(&mut self, n: &str) -> Self::Literal549 fn f64(&mut self, n: &str) -> Self::Literal {
550 let n: f64 = n.parse().unwrap();
551 let text = format!("{}f64", n);
552 Literal { text: text.into(), id: tt::TokenId::unspecified() }
553 }
554
string(&mut self, string: &str) -> Self::Literal555 fn string(&mut self, string: &str) -> Self::Literal {
556 let mut escaped = String::new();
557 for ch in string.chars() {
558 escaped.extend(ch.escape_debug());
559 }
560 Literal { text: format!("\"{}\"", escaped).into(), id: tt::TokenId::unspecified() }
561 }
562
character(&mut self, ch: char) -> Self::Literal563 fn character(&mut self, ch: char) -> Self::Literal {
564 Literal { text: format!("'{}'", ch).into(), id: tt::TokenId::unspecified() }
565 }
566
byte_string(&mut self, bytes: &[u8]) -> Self::Literal567 fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
568 let string = bytes
569 .iter()
570 .cloned()
571 .flat_map(ascii::escape_default)
572 .map(Into::<char>::into)
573 .collect::<String>();
574
575 Literal { text: format!("b\"{}\"", string).into(), id: tt::TokenId::unspecified() }
576 }
577
span(&mut self, literal: &Self::Literal) -> Self::Span578 fn span(&mut self, literal: &Self::Literal) -> Self::Span {
579 literal.id
580 }
581
set_span(&mut self, literal: &mut Self::Literal, span: Self::Span)582 fn set_span(&mut self, literal: &mut Self::Literal, span: Self::Span) {
583 literal.id = span;
584 }
585
subspan( &mut self, _literal: &Self::Literal, _start: Bound<usize>, _end: Bound<usize>, ) -> Option<Self::Span>586 fn subspan(
587 &mut self,
588 _literal: &Self::Literal,
589 _start: Bound<usize>,
590 _end: Bound<usize>,
591 ) -> Option<Self::Span> {
592 // FIXME handle span
593 None
594 }
595 }
596
597 impl server::SourceFile for Rustc {
eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool598 fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
599 file1.eq(file2)
600 }
path(&mut self, file: &Self::SourceFile) -> String601 fn path(&mut self, file: &Self::SourceFile) -> String {
602 String::from(
603 file.path().to_str().expect("non-UTF8 file path in `proc_macro::SourceFile::path`"),
604 )
605 }
is_real(&mut self, file: &Self::SourceFile) -> bool606 fn is_real(&mut self, file: &Self::SourceFile) -> bool {
607 file.is_real()
608 }
609 }
610
611 impl server::Diagnostic for Rustc {
new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic612 fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
613 let mut diag = Diagnostic::new(level, msg);
614 diag.spans = spans;
615 diag
616 }
617
sub( &mut self, _diag: &mut Self::Diagnostic, _level: Level, _msg: &str, _spans: Self::MultiSpan, )618 fn sub(
619 &mut self,
620 _diag: &mut Self::Diagnostic,
621 _level: Level,
622 _msg: &str,
623 _spans: Self::MultiSpan,
624 ) {
625 // FIXME handle diagnostic
626 //
627 }
628
emit(&mut self, _diag: Self::Diagnostic)629 fn emit(&mut self, _diag: Self::Diagnostic) {
630 // FIXME handle diagnostic
631 // diag.emit()
632 }
633 }
634
635 impl server::Span for Rustc {
debug(&mut self, span: Self::Span) -> String636 fn debug(&mut self, span: Self::Span) -> String {
637 format!("{:?}", span.0)
638 }
def_site(&mut self) -> Self::Span639 fn def_site(&mut self) -> Self::Span {
640 // MySpan(self.span_interner.intern(&MySpanData(Span::def_site())))
641 // FIXME handle span
642 tt::TokenId::unspecified()
643 }
call_site(&mut self) -> Self::Span644 fn call_site(&mut self) -> Self::Span {
645 // MySpan(self.span_interner.intern(&MySpanData(Span::call_site())))
646 // FIXME handle span
647 tt::TokenId::unspecified()
648 }
source_file(&mut self, _span: Self::Span) -> Self::SourceFile649 fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
650 // let MySpanData(span) = self.span_interner.get(span.0);
651 unimplemented!()
652 }
save_span(&mut self, _span: Self::Span) -> usize653 fn save_span(&mut self, _span: Self::Span) -> usize {
654 // FIXME stub
655 0
656 }
recover_proc_macro_span(&mut self, _id: usize) -> Self::Span657 fn recover_proc_macro_span(&mut self, _id: usize) -> Self::Span {
658 // FIXME stub
659 tt::TokenId::unspecified()
660 }
661 /// Recent feature, not yet in the proc_macro
662 ///
663 /// See PR:
664 /// https://github.com/rust-lang/rust/pull/55780
source_text(&mut self, _span: Self::Span) -> Option<String>665 fn source_text(&mut self, _span: Self::Span) -> Option<String> {
666 None
667 }
668
parent(&mut self, _span: Self::Span) -> Option<Self::Span>669 fn parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
670 // FIXME handle span
671 None
672 }
source(&mut self, span: Self::Span) -> Self::Span673 fn source(&mut self, span: Self::Span) -> Self::Span {
674 // FIXME handle span
675 span
676 }
start(&mut self, _span: Self::Span) -> LineColumn677 fn start(&mut self, _span: Self::Span) -> LineColumn {
678 // FIXME handle span
679 LineColumn { line: 0, column: 0 }
680 }
end(&mut self, _span: Self::Span) -> LineColumn681 fn end(&mut self, _span: Self::Span) -> LineColumn {
682 // FIXME handle span
683 LineColumn { line: 0, column: 0 }
684 }
join(&mut self, _first: Self::Span, _second: Self::Span) -> Option<Self::Span>685 fn join(&mut self, _first: Self::Span, _second: Self::Span) -> Option<Self::Span> {
686 None
687 }
resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span688 fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span {
689 // FIXME handle span
690 tt::TokenId::unspecified()
691 }
692
mixed_site(&mut self) -> Self::Span693 fn mixed_site(&mut self) -> Self::Span {
694 // FIXME handle span
695 tt::TokenId::unspecified()
696 }
697 }
698
699 impl server::MultiSpan for Rustc {
new(&mut self) -> Self::MultiSpan700 fn new(&mut self) -> Self::MultiSpan {
701 // FIXME handle span
702 vec![]
703 }
704
push(&mut self, other: &mut Self::MultiSpan, span: Self::Span)705 fn push(&mut self, other: &mut Self::MultiSpan, span: Self::Span) {
706 //TODP
707 other.push(span)
708 }
709 }
710
711 #[cfg(test)]
712 mod tests {
713 use super::super::proc_macro::bridge::server::Literal;
714 use super::*;
715
716 #[test]
test_rustc_server_literals()717 fn test_rustc_server_literals() {
718 let mut srv = Rustc { ident_interner: IdentInterner::default() };
719 assert_eq!(srv.integer("1234").text, "1234");
720
721 assert_eq!(srv.typed_integer("12", "u8").text, "12u8");
722 assert_eq!(srv.typed_integer("255", "u16").text, "255u16");
723 assert_eq!(srv.typed_integer("1234", "u32").text, "1234u32");
724 assert_eq!(srv.typed_integer("15846685", "u64").text, "15846685u64");
725 assert_eq!(srv.typed_integer("15846685258", "u128").text, "15846685258u128");
726 assert_eq!(srv.typed_integer("156788984", "usize").text, "156788984usize");
727 assert_eq!(srv.typed_integer("127", "i8").text, "127i8");
728 assert_eq!(srv.typed_integer("255", "i16").text, "255i16");
729 assert_eq!(srv.typed_integer("1234", "i32").text, "1234i32");
730 assert_eq!(srv.typed_integer("15846685", "i64").text, "15846685i64");
731 assert_eq!(srv.typed_integer("15846685258", "i128").text, "15846685258i128");
732 assert_eq!(srv.float("0").text, "0.0");
733 assert_eq!(srv.float("15684.5867").text, "15684.5867");
734 assert_eq!(srv.f32("15684.58").text, "15684.58f32");
735 assert_eq!(srv.f64("15684.58").text, "15684.58f64");
736
737 assert_eq!(srv.string("hello_world").text, "\"hello_world\"");
738 assert_eq!(srv.character('c').text, "'c'");
739 assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\"");
740
741 // u128::max
742 assert_eq!(
743 srv.integer("340282366920938463463374607431768211455").text,
744 "340282366920938463463374607431768211455"
745 );
746 // i128::min
747 assert_eq!(
748 srv.integer("-170141183460469231731687303715884105728").text,
749 "-170141183460469231731687303715884105728"
750 );
751 }
752
753 #[test]
test_rustc_server_to_string()754 fn test_rustc_server_to_string() {
755 let s = TokenStream {
756 token_trees: vec![
757 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
758 text: "struct".into(),
759 id: tt::TokenId::unspecified(),
760 })),
761 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
762 text: "T".into(),
763 id: tt::TokenId::unspecified(),
764 })),
765 tt::TokenTree::Subtree(tt::Subtree {
766 delimiter: Some(tt::Delimiter {
767 id: tt::TokenId::unspecified(),
768 kind: tt::DelimiterKind::Brace,
769 }),
770 token_trees: vec![],
771 }),
772 ],
773 };
774
775 assert_eq!(s.to_string(), "struct T {}");
776 }
777
778 #[test]
test_rustc_server_from_str()779 fn test_rustc_server_from_str() {
780 use std::str::FromStr;
781 let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
782 delimiter: Some(tt::Delimiter {
783 id: tt::TokenId::unspecified(),
784 kind: tt::DelimiterKind::Parenthesis,
785 }),
786 token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
787 text: "a".into(),
788 id: tt::TokenId::unspecified(),
789 }))],
790 });
791
792 let t1 = TokenStream::from_str("(a)").unwrap();
793 assert_eq!(t1.token_trees.len(), 1);
794 assert_eq!(t1.token_trees[0], subtree_paren_a);
795
796 let t2 = TokenStream::from_str("(a);").unwrap();
797 assert_eq!(t2.token_trees.len(), 2);
798 assert_eq!(t2.token_trees[0], subtree_paren_a);
799
800 let underscore = TokenStream::from_str("_").unwrap();
801 assert_eq!(
802 underscore.token_trees[0],
803 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
804 text: "_".into(),
805 id: tt::TokenId::unspecified(),
806 }))
807 );
808 }
809 }
810