aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs96
1 files changed, 46 insertions, 50 deletions
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index d897ac5de..a49e63ace 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -22,7 +22,7 @@ pub struct TokenMap {
22 22
23/// Maps relative range of the expanded syntax node to `tt::TokenId` 23/// Maps relative range of the expanded syntax node to `tt::TokenId`
24#[derive(Debug, PartialEq, Eq, Default)] 24#[derive(Debug, PartialEq, Eq, Default)]
25pub struct ExpandedRangeMap { 25pub struct RevTokenMap {
26 ranges: Vec<(TextRange, tt::TokenId)>, 26 ranges: Vec<(TextRange, tt::TokenId)>,
27} 27}
28 28
@@ -58,7 +58,7 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke
58fn fragment_to_syntax_node( 58fn fragment_to_syntax_node(
59 tt: &tt::Subtree, 59 tt: &tt::Subtree,
60 fragment_kind: FragmentKind, 60 fragment_kind: FragmentKind,
61) -> Result<(Parse<SyntaxNode>, ExpandedRangeMap), ExpandError> { 61) -> Result<(Parse<SyntaxNode>, RevTokenMap), ExpandError> {
62 let tmp; 62 let tmp;
63 let tokens = match tt { 63 let tokens = match tt {
64 tt::Subtree { delimiter: tt::Delimiter::None, token_trees } => token_trees.as_slice(), 64 tt::Subtree { delimiter: tt::Delimiter::None, token_trees } => token_trees.as_slice(),
@@ -79,44 +79,29 @@ fn fragment_to_syntax_node(
79 Ok((parse, range_map)) 79 Ok((parse, range_map))
80} 80}
81 81
82/// Parses the token tree (result of macro expansion) to an expression 82macro_rules! impl_token_tree_conversions {
83pub fn token_tree_to_expr( 83 ($($(#[$attr:meta])* $name:ident => ($kind:ident, $t:ty) ),*) => {
84 tt: &tt::Subtree, 84 $(
85) -> Result<(Parse<ast::Expr>, ExpandedRangeMap), ExpandError> { 85 $(#[$attr])*
86 let (parse, map) = fragment_to_syntax_node(tt, Expr)?; 86 pub fn $name(tt: &tt::Subtree) -> Result<(Parse<$t>, RevTokenMap), ExpandError> {
87 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map)) 87 let (parse, map) = fragment_to_syntax_node(tt, $kind)?;
88} 88 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map))
89 89 }
90/// Parses the token tree (result of macro expansion) to a Pattern 90 )*
91pub fn token_tree_to_pat( 91 }
92 tt: &tt::Subtree,
93) -> Result<(Parse<ast::Pat>, ExpandedRangeMap), ExpandError> {
94 let (parse, map) = fragment_to_syntax_node(tt, Pattern)?;
95 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map))
96}
97
98/// Parses the token tree (result of macro expansion) to a Type
99pub fn token_tree_to_ty(
100 tt: &tt::Subtree,
101) -> Result<(Parse<ast::TypeRef>, ExpandedRangeMap), ExpandError> {
102 let (parse, map) = fragment_to_syntax_node(tt, Type)?;
103 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map))
104}
105
106/// Parses the token tree (result of macro expansion) as a sequence of stmts
107pub fn token_tree_to_macro_stmts(
108 tt: &tt::Subtree,
109) -> Result<(Parse<ast::MacroStmts>, ExpandedRangeMap), ExpandError> {
110 let (parse, map) = fragment_to_syntax_node(tt, Statements)?;
111 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map))
112} 92}
113 93
114/// Parses the token tree (result of macro expansion) as a sequence of items 94impl_token_tree_conversions! {
115pub fn token_tree_to_items( 95 /// Parses the token tree (result of macro expansion) to an expression
116 tt: &tt::Subtree, 96 token_tree_to_expr => (Expr, ast::Expr),
117) -> Result<(Parse<ast::MacroItems>, ExpandedRangeMap), ExpandError> { 97 /// Parses the token tree (result of macro expansion) to a Pattern
118 let (parse, map) = fragment_to_syntax_node(tt, Items)?; 98 token_tree_to_pat => (Pattern, ast::Pat),
119 parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map)) 99 /// Parses the token tree (result of macro expansion) to a Type
100 token_tree_to_ty => (Type, ast::TypeRef),
101 /// Parses the token tree (result of macro expansion) as a sequence of stmts
102 token_tree_to_macro_stmts => (Statements, ast::MacroStmts),
103 /// Parses the token tree (result of macro expansion) as a sequence of items
104 token_tree_to_items => (Items, ast::MacroItems)
120} 105}
121 106
122impl TokenMap { 107impl TokenMap {
@@ -132,15 +117,28 @@ impl TokenMap {
132 } 117 }
133} 118}
134 119
135impl ExpandedRangeMap { 120impl RevTokenMap {
136 fn add(&mut self, relative_range: TextRange, token_id: &tt::TokenId) { 121 fn add(&mut self, relative_range: TextRange, token_id: tt::TokenId) {
137 self.ranges.push((relative_range, token_id.clone())) 122 self.ranges.push((relative_range, token_id.clone()))
138 } 123 }
139 124
125 /// Map a given token map to (Expanded syntax node, Input tokens) text-ranges pair
126 ///
127 /// This function do the following things:
128 ///
129 /// 1. Undo the increment of token-id `shift`:
130 /// When we output a token from from macro argument, we increased its id
131 /// by `shift` (so it's guaranteed to not to collide with anything from the definition)
132 /// We undo the increment here to rollback to its original token id.
133 /// 2. Offset the input tokens (`to`) by `parent` text-range:
134 /// We transforms the input tokens text-ranges from relative to original first token
135 /// to parent text-range
136 /// 3. Maps expanded tokens text-ranges to parent text-ranges
137 ///
140 pub fn map_ranges( 138 pub fn map_ranges(
141 &self, 139 &self,
142 to: &TokenMap, 140 to: &TokenMap,
143 start: TextUnit, 141 parent: TextRange,
144 shift: u32, 142 shift: u32,
145 ) -> Vec<(TextRange, TextRange)> { 143 ) -> Vec<(TextRange, TextRange)> {
146 self.ranges 144 self.ranges
@@ -149,7 +147,7 @@ impl ExpandedRangeMap {
149 let adjusted_id = tt::TokenId(tid.0.checked_sub(shift)?); 147 let adjusted_id = tt::TokenId(tid.0.checked_sub(shift)?);
150 let to_range = to.relative_range_of(adjusted_id)?; 148 let to_range = to.relative_range_of(adjusted_id)?;
151 149
152 Some((*r, TextRange::offset_len(to_range.start() + start, to_range.len()))) 150 Some((*r, TextRange::offset_len(to_range.start() + parent.start(), to_range.len())))
153 }) 151 })
154 .collect() 152 .collect()
155 } 153 }
@@ -301,7 +299,7 @@ struct TtTreeSink<'a> {
301 cursor: Cursor<'a>, 299 cursor: Cursor<'a>,
302 text_pos: TextUnit, 300 text_pos: TextUnit,
303 inner: SyntaxTreeBuilder, 301 inner: SyntaxTreeBuilder,
304 range_map: ExpandedRangeMap, 302 range_map: RevTokenMap,
305 303
306 // Number of roots 304 // Number of roots
307 // Use for detect ill-form tree which is not single root 305 // Use for detect ill-form tree which is not single root
@@ -316,11 +314,11 @@ impl<'a> TtTreeSink<'a> {
316 text_pos: 0.into(), 314 text_pos: 0.into(),
317 inner: SyntaxTreeBuilder::default(), 315 inner: SyntaxTreeBuilder::default(),
318 roots: smallvec::SmallVec::new(), 316 roots: smallvec::SmallVec::new(),
319 range_map: ExpandedRangeMap::default(), 317 range_map: RevTokenMap::default(),
320 } 318 }
321 } 319 }
322 320
323 fn finish(self) -> (Parse<SyntaxNode>, ExpandedRangeMap) { 321 fn finish(self) -> (Parse<SyntaxNode>, RevTokenMap) {
324 (self.inner.finish(), self.range_map) 322 (self.inner.finish(), self.range_map)
325 } 323 }
326} 324}
@@ -355,11 +353,9 @@ impl<'a> TreeSink for TtTreeSink<'a> {
355 // Mark the range if needed 353 // Mark the range if needed
356 if let tt::Leaf::Ident(ident) = leaf { 354 if let tt::Leaf::Ident(ident) = leaf {
357 if kind == IDENT { 355 if kind == IDENT {
358 let range = TextRange::offset_len( 356 let range =
359 self.text_pos + TextUnit::of_str(&self.buf), 357 TextRange::offset_len(self.text_pos, TextUnit::of_str(&ident.text));
360 TextUnit::of_str(&ident.text), 358 self.range_map.add(range, ident.id);
361 );
362 self.range_map.add(range, &ident.id);
363 } 359 }
364 } 360 }
365 361