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