1 //! Rustc proc-macro server implementation with tt
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.
9 //! FIXME: No span and source file information is implemented yet
11 use crate::proc_macro::bridge::{self, server};
13 use std::collections::HashMap;
15 use std::iter::FromIterator;
17 use std::{ascii, vec::IntoIter};
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;
26 #[derive(Debug, Clone)]
27 pub struct TokenStream {
28 pub subtree: tt::Subtree,
32 pub fn new() -> Self {
33 TokenStream { subtree: Default::default() }
36 pub fn with_subtree(subtree: tt::Subtree) -> Self {
37 if subtree.delimiter.is_some() {
39 subtree: tt::Subtree {
40 token_trees: vec![TokenTree::Subtree(subtree)],
45 TokenStream { subtree }
49 pub fn is_empty(&self) -> bool {
50 self.subtree.token_trees.is_empty()
54 /// Creates a token stream containing a single token tree.
55 impl From<TokenTree> for TokenStream {
56 fn from(tree: TokenTree) -> TokenStream {
57 TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } }
61 /// Collects a number of token trees into a single stream.
62 impl FromIterator<TokenTree> for TokenStream {
63 fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
64 trees.into_iter().map(TokenStream::from).collect()
68 /// A "flattening" operation on token streams, collects token trees
69 /// from multiple token streams into a single stream.
70 impl FromIterator<TokenStream> for TokenStream {
71 fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
72 let mut builder = TokenStreamBuilder::new();
73 streams.into_iter().for_each(|stream| builder.push(stream));
78 impl Extend<TokenTree> for TokenStream {
79 fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
80 self.extend(trees.into_iter().map(TokenStream::from));
84 impl Extend<TokenStream> for TokenStream {
85 fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
89 tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
90 self.subtree.token_trees.extend(subtree.token_trees);
93 self.subtree.token_trees.push(tkn);
101 type Level = crate::proc_macro::Level;
102 type LineColumn = crate::proc_macro::LineColumn;
103 type SourceFile = crate::proc_macro::SourceFile;
105 /// A structure representing a diagnostic message and associated children
107 #[derive(Clone, Debug)]
108 pub struct Diagnostic {
112 children: Vec<Diagnostic>,
116 /// Creates a new diagnostic with the given `level` and `message`.
117 pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
118 Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
122 // Rustc Server Ident has to be `Copyable`
123 // We use a stub here for bypassing
124 #[derive(Hash, Eq, PartialEq, Copy, Clone)]
125 pub struct IdentId(u32);
127 #[derive(Clone, Hash, Eq, PartialEq)]
128 struct IdentData(tt::Ident);
131 struct IdentInterner {
132 idents: HashMap<IdentData, u32>,
133 ident_data: Vec<IdentData>,
137 fn intern(&mut self, data: &IdentData) -> u32 {
138 if let Some(index) = self.idents.get(data) {
142 let index = self.idents.len() as u32;
143 self.ident_data.push(data.clone());
144 self.idents.insert(data.clone(), index);
148 fn get(&self, index: u32) -> &IdentData {
149 &self.ident_data[index as usize]
153 fn get_mut(&mut self, index: u32) -> &mut IdentData {
154 self.ident_data.get_mut(index as usize).expect("Should be consistent")
158 pub struct TokenStreamBuilder {
162 /// Public implementation details for the `TokenStream` type, such as iterators.
163 pub mod token_stream {
164 use std::str::FromStr;
166 use super::{TokenStream, TokenTree};
168 /// An iterator over `TokenStream`'s `TokenTree`s.
169 /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
170 /// and returns whole groups as token trees.
171 impl IntoIterator for TokenStream {
172 type Item = TokenTree;
173 type IntoIter = super::IntoIter<TokenTree>;
175 fn into_iter(self) -> Self::IntoIter {
176 self.subtree.token_trees.into_iter()
180 type LexError = String;
182 /// Attempts to break the string into tokens and parse those tokens into a token stream.
183 /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
184 /// or characters not existing in the language.
185 /// All tokens in the parsed stream get `Span::call_site()` spans.
187 /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
188 /// change these errors into `LexError`s later.
189 impl FromStr for TokenStream {
192 fn from_str(src: &str) -> Result<TokenStream, LexError> {
193 let (subtree, _token_map) =
194 mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?;
196 let subtree = subtree_replace_token_ids_with_unspecified(subtree);
197 Ok(TokenStream::with_subtree(subtree))
201 impl ToString for TokenStream {
202 fn to_string(&self) -> String {
203 let tt = self.subtree.clone().into();
208 fn to_text(tkn: &tt::TokenTree) -> String {
210 tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
211 tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
212 tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
213 tt::TokenTree::Subtree(subtree) => {
214 let content = subtree
217 .fold((String::new(), true), |(last, last_to_joint), tkn| {
218 let s = [last, to_text(tkn)].join(if last_to_joint { "" } else { " " });
219 let mut is_joint = false;
220 if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
221 if punct.spacing == tt::Spacing::Joint {
229 let (open, close) = match subtree.delimiter.map(|it| it.kind) {
231 Some(tt::DelimiterKind::Brace) => ("{", "}"),
232 Some(tt::DelimiterKind::Parenthesis) => ("(", ")"),
233 Some(tt::DelimiterKind::Bracket) => ("[", "]"),
235 format!("{}{}{}", open, content, close)
240 fn subtree_replace_token_ids_with_unspecified(subtree: tt::Subtree) -> tt::Subtree {
244 .map(|d| tt::Delimiter { id: tt::TokenId::unspecified(), ..d }),
248 .map(|t| token_tree_replace_token_ids_with_unspecified(t))
253 fn token_tree_replace_token_ids_with_unspecified(tt: tt::TokenTree) -> tt::TokenTree {
255 tt::TokenTree::Leaf(leaf) => {
256 tt::TokenTree::Leaf(leaf_replace_token_ids_with_unspecified(leaf))
258 tt::TokenTree::Subtree(subtree) => {
259 tt::TokenTree::Subtree(subtree_replace_token_ids_with_unspecified(subtree))
264 fn leaf_replace_token_ids_with_unspecified(leaf: tt::Leaf) -> tt::Leaf {
266 tt::Leaf::Literal(lit) => {
267 tt::Leaf::Literal(tt::Literal { id: tt::TokenId::unspecified(), ..lit })
269 tt::Leaf::Punct(punct) => {
270 tt::Leaf::Punct(tt::Punct { id: tt::TokenId::unspecified(), ..punct })
272 tt::Leaf::Ident(ident) => {
273 tt::Leaf::Ident(tt::Ident { id: tt::TokenId::unspecified(), ..ident })
279 impl TokenStreamBuilder {
280 fn new() -> TokenStreamBuilder {
281 TokenStreamBuilder { acc: TokenStream::new() }
284 fn push(&mut self, stream: TokenStream) {
285 self.acc.extend(stream.into_iter())
288 fn build(self) -> TokenStream {
293 pub struct FreeFunctions;
296 pub struct TokenStreamIter {
297 trees: IntoIter<TokenTree>,
302 ident_interner: IdentInterner,
303 // FIXME: store span information here.
306 impl server::Types for Rustc {
307 type FreeFunctions = FreeFunctions;
308 type TokenStream = TokenStream;
309 type TokenStreamBuilder = TokenStreamBuilder;
310 type TokenStreamIter = TokenStreamIter;
313 type Ident = IdentId;
314 type Literal = Literal;
315 type SourceFile = SourceFile;
316 type Diagnostic = Diagnostic;
318 type MultiSpan = Vec<Span>;
321 impl server::FreeFunctions for Rustc {
322 fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {
323 // FIXME: track env var accesses
324 // https://github.com/rust-lang/rust/pull/71858
328 impl server::TokenStream for Rustc {
329 fn new(&mut self) -> Self::TokenStream {
330 Self::TokenStream::new()
333 fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
336 fn from_str(&mut self, src: &str) -> Self::TokenStream {
337 use std::str::FromStr;
339 Self::TokenStream::from_str(src).expect("cannot parse string")
341 fn to_string(&mut self, stream: &Self::TokenStream) -> String {
346 tree: bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
347 ) -> Self::TokenStream {
349 bridge::TokenTree::Group(group) => {
350 let tree = TokenTree::from(group);
351 Self::TokenStream::from_iter(vec![tree])
354 bridge::TokenTree::Ident(IdentId(index)) => {
355 let IdentData(ident) = self.ident_interner.get(index).clone();
356 let ident: tt::Ident = ident;
357 let leaf = tt::Leaf::from(ident);
358 let tree = TokenTree::from(leaf);
359 Self::TokenStream::from_iter(vec![tree])
362 bridge::TokenTree::Literal(literal) => {
363 let leaf = tt::Leaf::from(literal);
364 let tree = TokenTree::from(leaf);
365 Self::TokenStream::from_iter(vec![tree])
368 bridge::TokenTree::Punct(p) => {
369 let leaf = tt::Leaf::from(p);
370 let tree = TokenTree::from(leaf);
371 Self::TokenStream::from_iter(vec![tree])
376 fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
377 let trees: Vec<TokenTree> = stream.into_iter().collect();
378 TokenStreamIter { trees: trees.into_iter() }
382 impl server::TokenStreamBuilder for Rustc {
383 fn new(&mut self) -> Self::TokenStreamBuilder {
384 Self::TokenStreamBuilder::new()
386 fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) {
389 fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
394 impl server::TokenStreamIter for Rustc {
397 iter: &mut Self::TokenStreamIter,
398 ) -> Option<bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
399 iter.trees.next().map(|tree| match tree {
400 TokenTree::Subtree(group) => bridge::TokenTree::Group(group),
401 TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
402 bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident))))
404 TokenTree::Leaf(tt::Leaf::Literal(literal)) => bridge::TokenTree::Literal(literal),
405 TokenTree::Leaf(tt::Leaf::Punct(punct)) => bridge::TokenTree::Punct(punct),
410 fn delim_to_internal(d: bridge::Delimiter) -> Option<tt::Delimiter> {
412 bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
413 bridge::Delimiter::Brace => tt::DelimiterKind::Brace,
414 bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket,
415 bridge::Delimiter::None => return None,
417 Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind })
420 fn delim_to_external(d: Option<tt::Delimiter>) -> bridge::Delimiter {
421 match d.map(|it| it.kind) {
422 Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis,
423 Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace,
424 Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket,
425 None => bridge::Delimiter::None,
429 fn spacing_to_internal(spacing: bridge::Spacing) -> Spacing {
431 bridge::Spacing::Alone => Spacing::Alone,
432 bridge::Spacing::Joint => Spacing::Joint,
436 fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
438 Spacing::Alone => bridge::Spacing::Alone,
439 Spacing::Joint => bridge::Spacing::Joint,
443 impl server::Group for Rustc {
444 fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group {
446 delimiter: delim_to_internal(delimiter),
447 token_trees: stream.subtree.token_trees,
450 fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
451 delim_to_external(group.delimiter)
454 // NOTE: Return value of do not include delimiter
455 fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
457 subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() },
461 fn span(&mut self, group: &Self::Group) -> Self::Span {
462 group.delimiter.map(|it| it.id).unwrap_or_else(|| tt::TokenId::unspecified())
465 fn set_span(&mut self, _group: &mut Self::Group, _span: Self::Span) {
469 fn span_open(&mut self, _group: &Self::Group) -> Self::Span {
471 // MySpan(self.span_interner.intern(&MySpanData(group.span_open())))
472 tt::TokenId::unspecified()
475 fn span_close(&mut self, _group: &Self::Group) -> Self::Span {
477 tt::TokenId::unspecified()
481 impl server::Punct for Rustc {
482 fn new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct {
485 spacing: spacing_to_internal(spacing),
486 id: tt::TokenId::unspecified(),
489 fn as_char(&mut self, punct: Self::Punct) -> char {
492 fn spacing(&mut self, punct: Self::Punct) -> bridge::Spacing {
493 spacing_to_external(punct.spacing)
495 fn span(&mut self, _punct: Self::Punct) -> Self::Span {
497 tt::TokenId::unspecified()
499 fn with_span(&mut self, punct: Self::Punct, _span: Self::Span) -> Self::Punct {
505 impl server::Ident for Rustc {
506 fn new(&mut self, string: &str, _span: Self::Span, _is_raw: bool) -> Self::Ident {
508 self.ident_interner.intern(&IdentData(tt::Ident {
510 id: tt::TokenId::unspecified(),
515 fn span(&mut self, _ident: Self::Ident) -> Self::Span {
517 tt::TokenId::unspecified()
519 fn with_span(&mut self, ident: Self::Ident, _span: Self::Span) -> Self::Ident {
525 impl server::Literal for Rustc {
526 fn debug_kind(&mut self, _literal: &Self::Literal) -> String {
527 // r-a: debug_kind and suffix are unsupported; corresponding client code has been changed to not call these.
528 // They must still be present to be ABI-compatible and work with upstream proc_macro.
531 fn symbol(&mut self, literal: &Self::Literal) -> String {
532 literal.text.to_string()
534 fn suffix(&mut self, _literal: &Self::Literal) -> Option<String> {
538 fn integer(&mut self, n: &str) -> Self::Literal {
539 let n: i128 = n.parse().unwrap();
540 Literal { text: n.to_string().into(), id: tt::TokenId::unspecified() }
543 fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
544 macro_rules! def_suffixed_integer {
545 ($kind:ident, $($ty:ty),*) => {
549 let n: $ty = n.parse().unwrap();
550 format!(concat!("{}", stringify!($ty)), n)
553 _ => unimplemented!("unknown args for typed_integer: n {}, kind {}", n, $kind),
558 let text = def_suffixed_integer! {kind, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize};
560 Literal { text: text.into(), id: tt::TokenId::unspecified() }
563 fn float(&mut self, n: &str) -> Self::Literal {
564 let n: f64 = n.parse().unwrap();
565 let mut text = f64::to_string(&n);
566 if !text.contains('.') {
569 Literal { text: text.into(), id: tt::TokenId::unspecified() }
572 fn f32(&mut self, n: &str) -> Self::Literal {
573 let n: f32 = n.parse().unwrap();
574 let text = format!("{}f32", n);
575 Literal { text: text.into(), id: tt::TokenId::unspecified() }
578 fn f64(&mut self, n: &str) -> Self::Literal {
579 let n: f64 = n.parse().unwrap();
580 let text = format!("{}f64", n);
581 Literal { text: text.into(), id: tt::TokenId::unspecified() }
584 fn string(&mut self, string: &str) -> Self::Literal {
585 let mut escaped = String::new();
586 for ch in string.chars() {
587 escaped.extend(ch.escape_debug());
589 Literal { text: format!("\"{}\"", escaped).into(), id: tt::TokenId::unspecified() }
592 fn character(&mut self, ch: char) -> Self::Literal {
593 Literal { text: format!("'{}'", ch).into(), id: tt::TokenId::unspecified() }
596 fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
600 .flat_map(ascii::escape_default)
601 .map(Into::<char>::into)
602 .collect::<String>();
604 Literal { text: format!("b\"{}\"", string).into(), id: tt::TokenId::unspecified() }
607 fn span(&mut self, literal: &Self::Literal) -> Self::Span {
611 fn set_span(&mut self, _literal: &mut Self::Literal, _span: Self::Span) {
617 _literal: &Self::Literal,
618 _start: Bound<usize>,
620 ) -> Option<Self::Span> {
626 impl server::SourceFile for Rustc {
627 fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
630 fn path(&mut self, file: &Self::SourceFile) -> String {
632 file.path().to_str().expect("non-UTF8 file path in `proc_macro::SourceFile::path`"),
635 fn is_real(&mut self, file: &Self::SourceFile) -> bool {
640 impl server::Diagnostic for Rustc {
641 fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
642 let mut diag = Diagnostic::new(level, msg);
649 _diag: &mut Self::Diagnostic,
652 _spans: Self::MultiSpan,
654 // FIXME handle diagnostic
658 fn emit(&mut self, _diag: Self::Diagnostic) {
659 // FIXME handle diagnostic
664 impl server::Span for Rustc {
665 fn debug(&mut self, span: Self::Span) -> String {
666 format!("{:?}", span.0)
668 fn def_site(&mut self) -> Self::Span {
669 // MySpan(self.span_interner.intern(&MySpanData(Span::def_site())))
671 tt::TokenId::unspecified()
673 fn call_site(&mut self) -> Self::Span {
674 // MySpan(self.span_interner.intern(&MySpanData(Span::call_site())))
676 tt::TokenId::unspecified()
678 fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
679 // let MySpanData(span) = self.span_interner.get(span.0);
683 /// Recent feature, not yet in the proc_macro
686 /// https://github.com/rust-lang/rust/pull/55780
687 fn source_text(&mut self, _span: Self::Span) -> Option<String> {
691 fn parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
695 fn source(&mut self, span: Self::Span) -> Self::Span {
699 fn start(&mut self, _span: Self::Span) -> LineColumn {
701 LineColumn { line: 0, column: 0 }
703 fn end(&mut self, _span: Self::Span) -> LineColumn {
705 LineColumn { line: 0, column: 0 }
707 fn join(&mut self, _first: Self::Span, _second: Self::Span) -> Option<Self::Span> {
710 fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span {
712 tt::TokenId::unspecified()
715 fn mixed_site(&mut self) -> Self::Span {
717 tt::TokenId::unspecified()
721 impl server::MultiSpan for Rustc {
722 fn new(&mut self) -> Self::MultiSpan {
727 fn push(&mut self, other: &mut Self::MultiSpan, span: Self::Span) {
736 use crate::proc_macro::bridge::server::Literal;
739 fn test_rustc_server_literals() {
740 let mut srv = Rustc { ident_interner: IdentInterner::default() };
741 assert_eq!(srv.integer("1234").text, "1234");
743 assert_eq!(srv.typed_integer("12", "u8").text, "12u8");
744 assert_eq!(srv.typed_integer("255", "u16").text, "255u16");
745 assert_eq!(srv.typed_integer("1234", "u32").text, "1234u32");
746 assert_eq!(srv.typed_integer("15846685", "u64").text, "15846685u64");
747 assert_eq!(srv.typed_integer("15846685258", "u128").text, "15846685258u128");
748 assert_eq!(srv.typed_integer("156788984", "usize").text, "156788984usize");
749 assert_eq!(srv.typed_integer("127", "i8").text, "127i8");
750 assert_eq!(srv.typed_integer("255", "i16").text, "255i16");
751 assert_eq!(srv.typed_integer("1234", "i32").text, "1234i32");
752 assert_eq!(srv.typed_integer("15846685", "i64").text, "15846685i64");
753 assert_eq!(srv.typed_integer("15846685258", "i128").text, "15846685258i128");
754 assert_eq!(srv.float("0").text, "0.0");
755 assert_eq!(srv.float("15684.5867").text, "15684.5867");
756 assert_eq!(srv.f32("15684.58").text, "15684.58f32");
757 assert_eq!(srv.f64("15684.58").text, "15684.58f64");
759 assert_eq!(srv.string("hello_world").text, "\"hello_world\"");
760 assert_eq!(srv.character('c').text, "'c'");
761 assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\"");
765 fn test_rustc_server_to_string() {
766 let s = TokenStream {
767 subtree: tt::Subtree {
770 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
771 text: "struct".into(),
772 id: tt::TokenId::unspecified(),
774 tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
776 id: tt::TokenId::unspecified(),
778 tt::TokenTree::Subtree(tt::Subtree {
779 delimiter: Some(tt::Delimiter {
780 id: tt::TokenId::unspecified(),
781 kind: tt::DelimiterKind::Brace,
789 assert_eq!(s.to_string(), "struct T {}");
793 fn test_rustc_server_from_str() {
794 use std::str::FromStr;
795 let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
796 delimiter: Some(tt::Delimiter {
797 id: tt::TokenId::unspecified(),
798 kind: tt::DelimiterKind::Parenthesis,
800 token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
802 id: tt::TokenId::unspecified(),
806 let t1 = TokenStream::from_str("(a)").unwrap();
807 assert_eq!(t1.subtree.token_trees.len(), 1);
808 assert_eq!(t1.subtree.token_trees[0], subtree_paren_a);
810 let t2 = TokenStream::from_str("(a);").unwrap();
811 assert_eq!(t2.subtree.token_trees.len(), 2);
812 assert_eq!(t2.subtree.token_trees[0], subtree_paren_a);