Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/syntax_bridge.rs')
-rw-r--r--crates/mbe/src/syntax_bridge.rs32
1 files changed, 27 insertions, 5 deletions
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 0421d4c9b0..6aa034abdc 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -1,5 +1,7 @@
//! Conversions between [`SyntaxNode`] and [`tt::TokenTree`].
+use std::iter;
+
use parser::{FragmentKind, ParseError, TreeSink};
use rustc_hash::FxHashMap;
use syntax::{
@@ -16,8 +18,17 @@ use crate::{ExpandError, TokenMap};
/// Convert the syntax node to a `TokenTree` (what macro
/// will consume).
pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> (tt::Subtree, TokenMap) {
+ syntax_node_to_token_tree_censored(node, None)
+}
+
+/// Convert the syntax node to a `TokenTree` (what macro will consume)
+/// with the censored range excluded.
+pub fn syntax_node_to_token_tree_censored(
+ node: &SyntaxNode,
+ censor: Option<TextRange>,
+) -> (tt::Subtree, TokenMap) {
let global_offset = node.text_range().start();
- let mut c = Convertor::new(node, global_offset);
+ let mut c = Convertor::new(node, global_offset, censor);
let subtree = convert_tokens(&mut c);
c.id_alloc.map.shrink_to_fit();
(subtree, c.id_alloc.map)
@@ -446,16 +457,24 @@ impl<'a> TokenConvertor for RawConvertor<'a> {
struct Convertor {
id_alloc: TokenIdAlloc,
current: Option<SyntaxToken>,
+ censor: Option<TextRange>,
range: TextRange,
punct_offset: Option<(SyntaxToken, TextSize)>,
}
impl Convertor {
- fn new(node: &SyntaxNode, global_offset: TextSize) -> Convertor {
+ fn new(node: &SyntaxNode, global_offset: TextSize, censor: Option<TextRange>) -> Convertor {
+ let first = node.first_token();
+ let current = match censor {
+ Some(censor) => iter::successors(first, |token| token.next_token())
+ .find(|token| !censor.contains_range(token.text_range())),
+ None => first,
+ };
Convertor {
id_alloc: { TokenIdAlloc { map: TokenMap::default(), global_offset, next_id: 0 } },
- current: node.first_token(),
+ current,
range: node.text_range(),
+ censor,
punct_offset: None,
}
}
@@ -512,8 +531,11 @@ impl TokenConvertor for Convertor {
if !&self.range.contains_range(curr.text_range()) {
return None;
}
- self.current = curr.next_token();
-
+ self.current = match self.censor {
+ Some(censor) => iter::successors(curr.next_token(), |token| token.next_token())
+ .find(|token| !censor.contains_range(token.text_range())),
+ None => curr.next_token(),
+ };
let token = if curr.kind().is_punct() {
let range = curr.text_range();
let range = TextRange::at(range.start(), TextSize::of('.'));