]> git.lizzy.rs Git - rust.git/blob - crates/mbe/src/syntax_bridge.rs
Merge #11182
[rust.git] / crates / mbe / src / syntax_bridge.rs
1 //! Conversions between [`SyntaxNode`] and [`tt::TokenTree`].
2
3 use rustc_hash::{FxHashMap, FxHashSet};
4 use stdx::non_empty_vec::NonEmptyVec;
5 use syntax::{
6     ast::{self, make::tokens::doc_comment},
7     AstToken, Parse, PreorderWithTokens, SmolStr, SyntaxElement, SyntaxKind,
8     SyntaxKind::*,
9     SyntaxNode, SyntaxToken, SyntaxTreeBuilder, TextRange, TextSize, WalkEvent, T,
10 };
11 use tt::buffer::{Cursor, TokenBuffer};
12
13 use crate::{to_parser_input::to_parser_input, tt_iter::TtIter, TokenMap};
14
15 /// Convert the syntax node to a `TokenTree` (what macro
16 /// will consume).
17 pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> (tt::Subtree, TokenMap) {
18     syntax_node_to_token_tree_censored(node, &Default::default())
19 }
20
21 /// Convert the syntax node to a `TokenTree` (what macro will consume)
22 /// with the censored range excluded.
23 pub fn syntax_node_to_token_tree_censored(
24     node: &SyntaxNode,
25     censor: &FxHashSet<SyntaxNode>,
26 ) -> (tt::Subtree, TokenMap) {
27     let global_offset = node.text_range().start();
28     let mut c = Convertor::new(node, global_offset, censor);
29     let subtree = convert_tokens(&mut c);
30     c.id_alloc.map.shrink_to_fit();
31     (subtree, c.id_alloc.map)
32 }
33
34 // The following items are what `rustc` macro can be parsed into :
35 // link: https://github.com/rust-lang/rust/blob/9ebf47851a357faa4cd97f4b1dc7835f6376e639/src/libsyntax/ext/expand.rs#L141
36 // * Expr(P<ast::Expr>)                     -> token_tree_to_expr
37 // * Pat(P<ast::Pat>)                       -> token_tree_to_pat
38 // * Ty(P<ast::Ty>)                         -> token_tree_to_ty
39 // * Stmts(SmallVec<[ast::Stmt; 1]>)        -> token_tree_to_stmts
40 // * Items(SmallVec<[P<ast::Item>; 1]>)     -> token_tree_to_items
41 //
42 // * TraitItems(SmallVec<[ast::TraitItem; 1]>)
43 // * AssocItems(SmallVec<[ast::AssocItem; 1]>)
44 // * ForeignItems(SmallVec<[ast::ForeignItem; 1]>
45
46 pub fn token_tree_to_syntax_node(
47     tt: &tt::Subtree,
48     entry_point: parser::TopEntryPoint,
49 ) -> (Parse<SyntaxNode>, TokenMap) {
50     let buffer = match tt {
51         tt::Subtree { delimiter: None, token_trees } => {
52             TokenBuffer::from_tokens(token_trees.as_slice())
53         }
54         _ => TokenBuffer::from_subtree(tt),
55     };
56     let parser_input = to_parser_input(&buffer);
57     let parser_output = entry_point.parse(&parser_input);
58     let mut tree_sink = TtTreeSink::new(buffer.begin());
59     for event in parser_output.iter() {
60         match event {
61             parser::Step::Token { kind, n_input_tokens: n_raw_tokens } => {
62                 tree_sink.token(kind, n_raw_tokens)
63             }
64             parser::Step::Enter { kind } => tree_sink.start_node(kind),
65             parser::Step::Exit => tree_sink.finish_node(),
66             parser::Step::Error { msg } => tree_sink.error(msg.to_string()),
67         }
68     }
69     let (parse, range_map) = tree_sink.finish();
70     (parse, range_map)
71 }
72
73 /// Convert a string to a `TokenTree`
74 pub fn parse_to_token_tree(text: &str) -> Option<(tt::Subtree, TokenMap)> {
75     let lexed = parser::LexedStr::new(text);
76     if lexed.errors().next().is_some() {
77         return None;
78     }
79
80     let mut conv = RawConvertor {
81         lexed,
82         pos: 0,
83         id_alloc: TokenIdAlloc {
84             map: Default::default(),
85             global_offset: TextSize::default(),
86             next_id: 0,
87         },
88     };
89
90     let subtree = convert_tokens(&mut conv);
91     Some((subtree, conv.id_alloc.map))
92 }
93
94 /// Split token tree with separate expr: $($e:expr)SEP*
95 pub fn parse_exprs_with_sep(tt: &tt::Subtree, sep: char) -> Vec<tt::Subtree> {
96     if tt.token_trees.is_empty() {
97         return Vec::new();
98     }
99
100     let mut iter = TtIter::new(tt);
101     let mut res = Vec::new();
102
103     while iter.peek_n(0).is_some() {
104         let expanded = iter.expect_fragment(parser::PrefixEntryPoint::Expr);
105
106         res.push(match expanded.value {
107             None => break,
108             Some(tt @ tt::TokenTree::Leaf(_)) => {
109                 tt::Subtree { delimiter: None, token_trees: vec![tt] }
110             }
111             Some(tt::TokenTree::Subtree(tt)) => tt,
112         });
113
114         let mut fork = iter.clone();
115         if fork.expect_char(sep).is_err() {
116             break;
117         }
118         iter = fork;
119     }
120
121     if iter.peek_n(0).is_some() {
122         res.push(tt::Subtree { delimiter: None, token_trees: iter.into_iter().cloned().collect() });
123     }
124
125     res
126 }
127
128 fn convert_tokens<C: TokenConvertor>(conv: &mut C) -> tt::Subtree {
129     struct StackEntry {
130         subtree: tt::Subtree,
131         idx: usize,
132         open_range: TextRange,
133     }
134
135     let entry = StackEntry {
136         subtree: tt::Subtree { delimiter: None, ..Default::default() },
137         // never used (delimiter is `None`)
138         idx: !0,
139         open_range: TextRange::empty(TextSize::of('.')),
140     };
141     let mut stack = NonEmptyVec::new(entry);
142
143     loop {
144         let StackEntry { subtree, .. } = stack.last_mut();
145         let result = &mut subtree.token_trees;
146         let (token, range) = match conv.bump() {
147             Some(it) => it,
148             None => break,
149         };
150
151         let kind = token.kind(&conv);
152         if kind == COMMENT {
153             if let Some(tokens) = conv.convert_doc_comment(&token) {
154                 // FIXME: There has to be a better way to do this
155                 // Add the comments token id to the converted doc string
156                 let id = conv.id_alloc().alloc(range);
157                 result.extend(tokens.into_iter().map(|mut tt| {
158                     if let tt::TokenTree::Subtree(sub) = &mut tt {
159                         if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(lit))) =
160                             sub.token_trees.get_mut(2)
161                         {
162                             lit.id = id
163                         }
164                     }
165                     tt
166                 }));
167             }
168             continue;
169         }
170         let tt = if kind.is_punct() && kind != UNDERSCORE {
171             assert_eq!(range.len(), TextSize::of('.'));
172
173             if let Some(delim) = subtree.delimiter {
174                 let expected = match delim.kind {
175                     tt::DelimiterKind::Parenthesis => T![')'],
176                     tt::DelimiterKind::Brace => T!['}'],
177                     tt::DelimiterKind::Bracket => T![']'],
178                 };
179
180                 if kind == expected {
181                     if let Some(entry) = stack.pop() {
182                         conv.id_alloc().close_delim(entry.idx, Some(range));
183                         stack.last_mut().subtree.token_trees.push(entry.subtree.into());
184                     }
185                     continue;
186                 }
187             }
188
189             let delim = match kind {
190                 T!['('] => Some(tt::DelimiterKind::Parenthesis),
191                 T!['{'] => Some(tt::DelimiterKind::Brace),
192                 T!['['] => Some(tt::DelimiterKind::Bracket),
193                 _ => None,
194             };
195
196             if let Some(kind) = delim {
197                 let mut subtree = tt::Subtree::default();
198                 let (id, idx) = conv.id_alloc().open_delim(range);
199                 subtree.delimiter = Some(tt::Delimiter { id, kind });
200                 stack.push(StackEntry { subtree, idx, open_range: range });
201                 continue;
202             }
203
204             let spacing = match conv.peek().map(|next| next.kind(&conv)) {
205                 Some(kind)
206                     if !kind.is_trivia()
207                         && kind.is_punct()
208                         && kind != T!['[']
209                         && kind != T!['{']
210                         && kind != T!['(']
211                         && kind != UNDERSCORE =>
212                 {
213                     tt::Spacing::Joint
214                 }
215                 _ => tt::Spacing::Alone,
216             };
217             let char = match token.to_char(&conv) {
218                 Some(c) => c,
219                 None => {
220                     panic!("Token from lexer must be single char: token = {:#?}", token);
221                 }
222             };
223             tt::Leaf::from(tt::Punct { char, spacing, id: conv.id_alloc().alloc(range) }).into()
224         } else {
225             macro_rules! make_leaf {
226                 ($i:ident) => {
227                     tt::$i { id: conv.id_alloc().alloc(range), text: token.to_text(conv) }.into()
228                 };
229             }
230             let leaf: tt::Leaf = match kind {
231                 T![true] | T![false] => make_leaf!(Ident),
232                 IDENT => make_leaf!(Ident),
233                 UNDERSCORE => make_leaf!(Ident),
234                 k if k.is_keyword() => make_leaf!(Ident),
235                 k if k.is_literal() => make_leaf!(Literal),
236                 LIFETIME_IDENT => {
237                     let char_unit = TextSize::of('\'');
238                     let r = TextRange::at(range.start(), char_unit);
239                     let apostrophe = tt::Leaf::from(tt::Punct {
240                         char: '\'',
241                         spacing: tt::Spacing::Joint,
242                         id: conv.id_alloc().alloc(r),
243                     });
244                     result.push(apostrophe.into());
245
246                     let r = TextRange::at(range.start() + char_unit, range.len() - char_unit);
247                     let ident = tt::Leaf::from(tt::Ident {
248                         text: SmolStr::new(&token.to_text(conv)[1..]),
249                         id: conv.id_alloc().alloc(r),
250                     });
251                     result.push(ident.into());
252                     continue;
253                 }
254                 _ => continue,
255             };
256
257             leaf.into()
258         };
259         result.push(tt);
260     }
261
262     // If we get here, we've consumed all input tokens.
263     // We might have more than one subtree in the stack, if the delimiters are improperly balanced.
264     // Merge them so we're left with one.
265     while let Some(entry) = stack.pop() {
266         let parent = stack.last_mut();
267
268         conv.id_alloc().close_delim(entry.idx, None);
269         let leaf: tt::Leaf = tt::Punct {
270             id: conv.id_alloc().alloc(entry.open_range),
271             char: match entry.subtree.delimiter.unwrap().kind {
272                 tt::DelimiterKind::Parenthesis => '(',
273                 tt::DelimiterKind::Brace => '{',
274                 tt::DelimiterKind::Bracket => '[',
275             },
276             spacing: tt::Spacing::Alone,
277         }
278         .into();
279         parent.subtree.token_trees.push(leaf.into());
280         parent.subtree.token_trees.extend(entry.subtree.token_trees);
281     }
282
283     let subtree = stack.into_last().subtree;
284     if let [tt::TokenTree::Subtree(first)] = &*subtree.token_trees {
285         first.clone()
286     } else {
287         subtree
288     }
289 }
290
291 /// Returns the textual content of a doc comment block as a quoted string
292 /// That is, strips leading `///` (or `/**`, etc)
293 /// and strips the ending `*/`
294 /// And then quote the string, which is needed to convert to `tt::Literal`
295 fn doc_comment_text(comment: &ast::Comment) -> SmolStr {
296     let prefix_len = comment.prefix().len();
297     let mut text = &comment.text()[prefix_len..];
298
299     // Remove ending "*/"
300     if comment.kind().shape == ast::CommentShape::Block {
301         text = &text[0..text.len() - 2];
302     }
303
304     // Quote the string
305     // Note that `tt::Literal` expect an escaped string
306     let text = format!("\"{}\"", text.escape_debug());
307     text.into()
308 }
309
310 fn convert_doc_comment(token: &syntax::SyntaxToken) -> Option<Vec<tt::TokenTree>> {
311     cov_mark::hit!(test_meta_doc_comments);
312     let comment = ast::Comment::cast(token.clone())?;
313     let doc = comment.kind().doc?;
314
315     // Make `doc="\" Comments\""
316     let meta_tkns = vec![mk_ident("doc"), mk_punct('='), mk_doc_literal(&comment)];
317
318     // Make `#![]`
319     let mut token_trees = Vec::with_capacity(3);
320     token_trees.push(mk_punct('#'));
321     if let ast::CommentPlacement::Inner = doc {
322         token_trees.push(mk_punct('!'));
323     }
324     token_trees.push(tt::TokenTree::from(tt::Subtree {
325         delimiter: Some(tt::Delimiter {
326             kind: tt::DelimiterKind::Bracket,
327             id: tt::TokenId::unspecified(),
328         }),
329         token_trees: meta_tkns,
330     }));
331
332     return Some(token_trees);
333
334     // Helper functions
335     fn mk_ident(s: &str) -> tt::TokenTree {
336         tt::TokenTree::from(tt::Leaf::from(tt::Ident {
337             text: s.into(),
338             id: tt::TokenId::unspecified(),
339         }))
340     }
341
342     fn mk_punct(c: char) -> tt::TokenTree {
343         tt::TokenTree::from(tt::Leaf::from(tt::Punct {
344             char: c,
345             spacing: tt::Spacing::Alone,
346             id: tt::TokenId::unspecified(),
347         }))
348     }
349
350     fn mk_doc_literal(comment: &ast::Comment) -> tt::TokenTree {
351         let lit = tt::Literal { text: doc_comment_text(comment), id: tt::TokenId::unspecified() };
352
353         tt::TokenTree::from(tt::Leaf::from(lit))
354     }
355 }
356
357 struct TokenIdAlloc {
358     map: TokenMap,
359     global_offset: TextSize,
360     next_id: u32,
361 }
362
363 impl TokenIdAlloc {
364     fn alloc(&mut self, absolute_range: TextRange) -> tt::TokenId {
365         let relative_range = absolute_range - self.global_offset;
366         let token_id = tt::TokenId(self.next_id);
367         self.next_id += 1;
368         self.map.insert(token_id, relative_range);
369         token_id
370     }
371
372     fn open_delim(&mut self, open_abs_range: TextRange) -> (tt::TokenId, usize) {
373         let token_id = tt::TokenId(self.next_id);
374         self.next_id += 1;
375         let idx = self.map.insert_delim(
376             token_id,
377             open_abs_range - self.global_offset,
378             open_abs_range - self.global_offset,
379         );
380         (token_id, idx)
381     }
382
383     fn close_delim(&mut self, idx: usize, close_abs_range: Option<TextRange>) {
384         match close_abs_range {
385             None => {
386                 self.map.remove_delim(idx);
387             }
388             Some(close) => {
389                 self.map.update_close_delim(idx, close - self.global_offset);
390             }
391         }
392     }
393 }
394
395 /// A raw token (straight from lexer) convertor
396 struct RawConvertor<'a> {
397     lexed: parser::LexedStr<'a>,
398     pos: usize,
399     id_alloc: TokenIdAlloc,
400 }
401
402 trait SrcToken<Ctx>: std::fmt::Debug {
403     fn kind(&self, ctx: &Ctx) -> SyntaxKind;
404
405     fn to_char(&self, ctx: &Ctx) -> Option<char>;
406
407     fn to_text(&self, ctx: &Ctx) -> SmolStr;
408 }
409
410 trait TokenConvertor: Sized {
411     type Token: SrcToken<Self>;
412
413     fn convert_doc_comment(&self, token: &Self::Token) -> Option<Vec<tt::TokenTree>>;
414
415     fn bump(&mut self) -> Option<(Self::Token, TextRange)>;
416
417     fn peek(&self) -> Option<Self::Token>;
418
419     fn id_alloc(&mut self) -> &mut TokenIdAlloc;
420 }
421
422 impl<'a> SrcToken<RawConvertor<'a>> for usize {
423     fn kind(&self, ctx: &RawConvertor<'a>) -> SyntaxKind {
424         ctx.lexed.kind(*self)
425     }
426
427     fn to_char(&self, ctx: &RawConvertor<'a>) -> Option<char> {
428         ctx.lexed.text(*self).chars().next()
429     }
430
431     fn to_text(&self, ctx: &RawConvertor<'_>) -> SmolStr {
432         ctx.lexed.text(*self).into()
433     }
434 }
435
436 impl<'a> TokenConvertor for RawConvertor<'a> {
437     type Token = usize;
438
439     fn convert_doc_comment(&self, &token: &usize) -> Option<Vec<tt::TokenTree>> {
440         let text = self.lexed.text(token);
441         convert_doc_comment(&doc_comment(text))
442     }
443
444     fn bump(&mut self) -> Option<(Self::Token, TextRange)> {
445         if self.pos == self.lexed.len() {
446             return None;
447         }
448         let token = self.pos;
449         self.pos += 1;
450         let range = self.lexed.text_range(token);
451         let range = TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
452
453         Some((token, range))
454     }
455
456     fn peek(&self) -> Option<Self::Token> {
457         if self.pos == self.lexed.len() {
458             return None;
459         }
460         Some(self.pos)
461     }
462
463     fn id_alloc(&mut self) -> &mut TokenIdAlloc {
464         &mut self.id_alloc
465     }
466 }
467
468 struct Convertor<'c> {
469     id_alloc: TokenIdAlloc,
470     current: Option<SyntaxToken>,
471     preorder: PreorderWithTokens,
472     censor: &'c FxHashSet<SyntaxNode>,
473     range: TextRange,
474     punct_offset: Option<(SyntaxToken, TextSize)>,
475 }
476
477 impl<'c> Convertor<'c> {
478     fn new(
479         node: &SyntaxNode,
480         global_offset: TextSize,
481         censor: &'c FxHashSet<SyntaxNode>,
482     ) -> Convertor<'c> {
483         let range = node.text_range();
484         let mut preorder = node.preorder_with_tokens();
485         let first = Self::next_token(&mut preorder, censor);
486         Convertor {
487             id_alloc: { TokenIdAlloc { map: TokenMap::default(), global_offset, next_id: 0 } },
488             current: first,
489             preorder,
490             range,
491             censor,
492             punct_offset: None,
493         }
494     }
495
496     fn next_token(
497         preorder: &mut PreorderWithTokens,
498         censor: &FxHashSet<SyntaxNode>,
499     ) -> Option<SyntaxToken> {
500         while let Some(ev) = preorder.next() {
501             let ele = match ev {
502                 WalkEvent::Enter(ele) => ele,
503                 _ => continue,
504             };
505             match ele {
506                 SyntaxElement::Token(t) => return Some(t),
507                 SyntaxElement::Node(node) if censor.contains(&node) => preorder.skip_subtree(),
508                 SyntaxElement::Node(_) => (),
509             }
510         }
511         None
512     }
513 }
514
515 #[derive(Debug)]
516 enum SynToken {
517     Ordinary(SyntaxToken),
518     Punch(SyntaxToken, TextSize),
519 }
520
521 impl SynToken {
522     fn token(&self) -> &SyntaxToken {
523         match self {
524             SynToken::Ordinary(it) | SynToken::Punch(it, _) => it,
525         }
526     }
527 }
528
529 impl<'a> SrcToken<Convertor<'a>> for SynToken {
530     fn kind(&self, _ctx: &Convertor<'a>) -> SyntaxKind {
531         self.token().kind()
532     }
533     fn to_char(&self, _ctx: &Convertor<'a>) -> Option<char> {
534         match self {
535             SynToken::Ordinary(_) => None,
536             SynToken::Punch(it, i) => it.text().chars().nth((*i).into()),
537         }
538     }
539     fn to_text(&self, _ctx: &Convertor<'a>) -> SmolStr {
540         self.token().text().into()
541     }
542 }
543
544 impl TokenConvertor for Convertor<'_> {
545     type Token = SynToken;
546     fn convert_doc_comment(&self, token: &Self::Token) -> Option<Vec<tt::TokenTree>> {
547         convert_doc_comment(token.token())
548     }
549
550     fn bump(&mut self) -> Option<(Self::Token, TextRange)> {
551         if let Some((punct, offset)) = self.punct_offset.clone() {
552             if usize::from(offset) + 1 < punct.text().len() {
553                 let offset = offset + TextSize::of('.');
554                 let range = punct.text_range();
555                 self.punct_offset = Some((punct.clone(), offset));
556                 let range = TextRange::at(range.start() + offset, TextSize::of('.'));
557                 return Some((SynToken::Punch(punct, offset), range));
558             }
559         }
560
561         let curr = self.current.clone()?;
562         if !&self.range.contains_range(curr.text_range()) {
563             return None;
564         }
565         self.current = Self::next_token(&mut self.preorder, self.censor);
566         let token = if curr.kind().is_punct() {
567             self.punct_offset = Some((curr.clone(), 0.into()));
568             let range = curr.text_range();
569             let range = TextRange::at(range.start(), TextSize::of('.'));
570             (SynToken::Punch(curr, 0.into()), range)
571         } else {
572             self.punct_offset = None;
573             let range = curr.text_range();
574             (SynToken::Ordinary(curr), range)
575         };
576
577         Some(token)
578     }
579
580     fn peek(&self) -> Option<Self::Token> {
581         if let Some((punct, mut offset)) = self.punct_offset.clone() {
582             offset += TextSize::of('.');
583             if usize::from(offset) < punct.text().len() {
584                 return Some(SynToken::Punch(punct, offset));
585             }
586         }
587
588         let curr = self.current.clone()?;
589         if !self.range.contains_range(curr.text_range()) {
590             return None;
591         }
592
593         let token = if curr.kind().is_punct() {
594             SynToken::Punch(curr, 0.into())
595         } else {
596             SynToken::Ordinary(curr)
597         };
598         Some(token)
599     }
600
601     fn id_alloc(&mut self) -> &mut TokenIdAlloc {
602         &mut self.id_alloc
603     }
604 }
605
606 struct TtTreeSink<'a> {
607     buf: String,
608     cursor: Cursor<'a>,
609     open_delims: FxHashMap<tt::TokenId, TextSize>,
610     text_pos: TextSize,
611     inner: SyntaxTreeBuilder,
612     token_map: TokenMap,
613 }
614
615 impl<'a> TtTreeSink<'a> {
616     fn new(cursor: Cursor<'a>) -> Self {
617         TtTreeSink {
618             buf: String::new(),
619             cursor,
620             open_delims: FxHashMap::default(),
621             text_pos: 0.into(),
622             inner: SyntaxTreeBuilder::default(),
623             token_map: TokenMap::default(),
624         }
625     }
626
627     fn finish(mut self) -> (Parse<SyntaxNode>, TokenMap) {
628         self.token_map.shrink_to_fit();
629         (self.inner.finish(), self.token_map)
630     }
631 }
632
633 fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> &'static str {
634     let texts = match d {
635         tt::DelimiterKind::Parenthesis => "()",
636         tt::DelimiterKind::Brace => "{}",
637         tt::DelimiterKind::Bracket => "[]",
638     };
639
640     let idx = closing as usize;
641     &texts[idx..texts.len() - (1 - idx)]
642 }
643
644 impl<'a> TtTreeSink<'a> {
645     fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) {
646         if kind == LIFETIME_IDENT {
647             n_tokens = 2;
648         }
649
650         let mut last = self.cursor;
651         for _ in 0..n_tokens {
652             let tmp: u8;
653             if self.cursor.eof() {
654                 break;
655             }
656             last = self.cursor;
657             let text: &str = loop {
658                 break match self.cursor.token_tree() {
659                     Some(tt::buffer::TokenTreeRef::Leaf(leaf, _)) => {
660                         // Mark the range if needed
661                         let (text, id) = match leaf {
662                             tt::Leaf::Ident(ident) => (ident.text.as_str(), ident.id),
663                             tt::Leaf::Punct(punct) => {
664                                 assert!(punct.char.is_ascii());
665                                 tmp = punct.char as u8;
666                                 (std::str::from_utf8(std::slice::from_ref(&tmp)).unwrap(), punct.id)
667                             }
668                             tt::Leaf::Literal(lit) => (lit.text.as_str(), lit.id),
669                         };
670                         let range = TextRange::at(self.text_pos, TextSize::of(text));
671                         self.token_map.insert(id, range);
672                         self.cursor = self.cursor.bump();
673                         text
674                     }
675                     Some(tt::buffer::TokenTreeRef::Subtree(subtree, _)) => {
676                         self.cursor = self.cursor.subtree().unwrap();
677                         match subtree.delimiter {
678                             Some(d) => {
679                                 self.open_delims.insert(d.id, self.text_pos);
680                                 delim_to_str(d.kind, false)
681                             }
682                             None => continue,
683                         }
684                     }
685                     None => {
686                         let parent = self.cursor.end().unwrap();
687                         self.cursor = self.cursor.bump();
688                         match parent.delimiter {
689                             Some(d) => {
690                                 if let Some(open_delim) = self.open_delims.get(&d.id) {
691                                     let open_range = TextRange::at(*open_delim, TextSize::of('('));
692                                     let close_range =
693                                         TextRange::at(self.text_pos, TextSize::of('('));
694                                     self.token_map.insert_delim(d.id, open_range, close_range);
695                                 }
696                                 delim_to_str(d.kind, true)
697                             }
698                             None => continue,
699                         }
700                     }
701                 };
702             };
703             self.buf += text;
704             self.text_pos += TextSize::of(text);
705         }
706
707         self.inner.token(kind, self.buf.as_str());
708         self.buf.clear();
709         // Add whitespace between adjoint puncts
710         let next = last.bump();
711         if let (
712             Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(curr), _)),
713             Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(_), _)),
714         ) = (last.token_tree(), next.token_tree())
715         {
716             // Note: We always assume the semi-colon would be the last token in
717             // other parts of RA such that we don't add whitespace here.
718             if curr.spacing == tt::Spacing::Alone && curr.char != ';' {
719                 self.inner.token(WHITESPACE, " ");
720                 self.text_pos += TextSize::of(' ');
721             }
722         }
723     }
724
725     fn start_node(&mut self, kind: SyntaxKind) {
726         self.inner.start_node(kind);
727     }
728
729     fn finish_node(&mut self) {
730         self.inner.finish_node();
731     }
732
733     fn error(&mut self, error: String) {
734         self.inner.error(error, self.text_pos)
735     }
736 }