diff options
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 96 |
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)] |
25 | pub struct ExpandedRangeMap { | 25 | pub 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 | |||
58 | fn fragment_to_syntax_node( | 58 | fn 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 | 82 | macro_rules! impl_token_tree_conversions { |
83 | pub 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 | )* |
91 | pub 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 | ||
99 | pub 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 | ||
107 | pub 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 | 94 | impl_token_tree_conversions! { |
115 | pub 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 | ||
122 | impl TokenMap { | 107 | impl TokenMap { |
@@ -132,15 +117,28 @@ impl TokenMap { | |||
132 | } | 117 | } |
133 | } | 118 | } |
134 | 119 | ||
135 | impl ExpandedRangeMap { | 120 | impl 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 | ||