diff options
Diffstat (limited to 'crates/ra_mbe/src/syntax_bridge.rs')
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 113 |
1 files changed, 94 insertions, 19 deletions
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 8d9217518..5db6647e3 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -15,6 +15,7 @@ use crate::ExpandError; | |||
15 | use std::sync::atomic::{AtomicU32, Ordering}; | 15 | use std::sync::atomic::{AtomicU32, Ordering}; |
16 | 16 | ||
17 | /// Maps `tt::TokenId` to the relative range of the original token. | 17 | /// Maps `tt::TokenId` to the relative range of the original token. |
18 | #[derive(Debug, PartialEq, Eq)] | ||
18 | pub struct TokenMap { | 19 | pub struct TokenMap { |
19 | /// Maps `tt::TokenId` to the *relative* source range. | 20 | /// Maps `tt::TokenId` to the *relative* source range. |
20 | tokens: Vec<TextRange>, | 21 | tokens: Vec<TextRange>, |
@@ -34,6 +35,13 @@ impl std::default::Default for TokenMap { | |||
34 | } | 35 | } |
35 | } | 36 | } |
36 | 37 | ||
38 | /// Maps Relative range of the expanded syntax node to `tt::TokenId` | ||
39 | #[derive(Debug, PartialEq, Eq, Default)] | ||
40 | pub struct ExpandedRangeMap { | ||
41 | /// Maps `tt::TokenId` to the *relative* source range. | ||
42 | ranges: Vec<(TextRange, tt::TokenId)>, | ||
43 | } | ||
44 | |||
37 | /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro | 45 | /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro |
38 | /// will consume). | 46 | /// will consume). |
39 | pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> { | 47 | pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> { |
@@ -66,7 +74,7 @@ pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, Toke | |||
66 | fn fragment_to_syntax_node( | 74 | fn fragment_to_syntax_node( |
67 | tt: &tt::Subtree, | 75 | tt: &tt::Subtree, |
68 | fragment_kind: FragmentKind, | 76 | fragment_kind: FragmentKind, |
69 | ) -> Result<Parse<SyntaxNode>, ExpandError> { | 77 | ) -> Result<(Parse<SyntaxNode>, ExpandedRangeMap), ExpandError> { |
70 | let tmp; | 78 | let tmp; |
71 | let tokens = match tt { | 79 | let tokens = match tt { |
72 | tt::Subtree { delimiter: tt::Delimiter::None, token_trees } => token_trees.as_slice(), | 80 | tt::Subtree { delimiter: tt::Delimiter::None, token_trees } => token_trees.as_slice(), |
@@ -77,44 +85,55 @@ fn fragment_to_syntax_node( | |||
77 | }; | 85 | }; |
78 | let buffer = TokenBuffer::new(&tokens); | 86 | let buffer = TokenBuffer::new(&tokens); |
79 | let mut token_source = SubtreeTokenSource::new(&buffer); | 87 | let mut token_source = SubtreeTokenSource::new(&buffer); |
80 | let mut tree_sink = TtTreeSink::new(buffer.begin()); | 88 | let mut range_map = ExpandedRangeMap::default(); |
89 | let mut tree_sink = TtTreeSink::new(buffer.begin(), &mut range_map); | ||
81 | ra_parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind); | 90 | ra_parser::parse_fragment(&mut token_source, &mut tree_sink, fragment_kind); |
82 | if tree_sink.roots.len() != 1 { | 91 | if tree_sink.roots.len() != 1 { |
83 | return Err(ExpandError::ConversionError); | 92 | return Err(ExpandError::ConversionError); |
84 | } | 93 | } |
85 | //FIXME: would be cool to report errors | 94 | //FIXME: would be cool to report errors |
86 | let parse = tree_sink.inner.finish(); | 95 | let parse = tree_sink.inner.finish(); |
87 | Ok(parse) | 96 | Ok((parse, range_map)) |
88 | } | 97 | } |
89 | 98 | ||
90 | /// Parses the token tree (result of macro expansion) to an expression | 99 | /// Parses the token tree (result of macro expansion) to an expression |
91 | pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> { | 100 | pub fn token_tree_to_expr( |
92 | let parse = fragment_to_syntax_node(tt, Expr)?; | 101 | tt: &tt::Subtree, |
93 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 102 | ) -> Result<(Parse<ast::Expr>, ExpandedRangeMap), ExpandError> { |
103 | let (parse, map) = fragment_to_syntax_node(tt, Expr)?; | ||
104 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map)) | ||
94 | } | 105 | } |
95 | 106 | ||
96 | /// Parses the token tree (result of macro expansion) to a Pattern | 107 | /// Parses the token tree (result of macro expansion) to a Pattern |
97 | pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> { | 108 | pub fn token_tree_to_pat( |
98 | let parse = fragment_to_syntax_node(tt, Pattern)?; | 109 | tt: &tt::Subtree, |
99 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 110 | ) -> Result<(Parse<ast::Pat>, ExpandedRangeMap), ExpandError> { |
111 | let (parse, map) = fragment_to_syntax_node(tt, Pattern)?; | ||
112 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map)) | ||
100 | } | 113 | } |
101 | 114 | ||
102 | /// Parses the token tree (result of macro expansion) to a Type | 115 | /// Parses the token tree (result of macro expansion) to a Type |
103 | pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> { | 116 | pub fn token_tree_to_ty( |
104 | let parse = fragment_to_syntax_node(tt, Type)?; | 117 | tt: &tt::Subtree, |
105 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 118 | ) -> Result<(Parse<ast::TypeRef>, ExpandedRangeMap), ExpandError> { |
119 | let (parse, map) = fragment_to_syntax_node(tt, Type)?; | ||
120 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map)) | ||
106 | } | 121 | } |
107 | 122 | ||
108 | /// Parses the token tree (result of macro expansion) as a sequence of stmts | 123 | /// Parses the token tree (result of macro expansion) as a sequence of stmts |
109 | pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> { | 124 | pub fn token_tree_to_macro_stmts( |
110 | let parse = fragment_to_syntax_node(tt, Statements)?; | 125 | tt: &tt::Subtree, |
111 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 126 | ) -> Result<(Parse<ast::MacroStmts>, ExpandedRangeMap), ExpandError> { |
127 | let (parse, map) = fragment_to_syntax_node(tt, Statements)?; | ||
128 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map)) | ||
112 | } | 129 | } |
113 | 130 | ||
114 | /// Parses the token tree (result of macro expansion) as a sequence of items | 131 | /// Parses the token tree (result of macro expansion) as a sequence of items |
115 | pub fn token_tree_to_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { | 132 | pub fn token_tree_to_items( |
116 | let parse = fragment_to_syntax_node(tt, Items)?; | 133 | tt: &tt::Subtree, |
117 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError) | 134 | ) -> Result<(Parse<ast::MacroItems>, ExpandedRangeMap), ExpandError> { |
135 | let (parse, map) = fragment_to_syntax_node(tt, Items)?; | ||
136 | parse.cast().ok_or_else(|| crate::ExpandError::ConversionError).map(|p| (p, map)) | ||
118 | } | 137 | } |
119 | 138 | ||
120 | impl TokenMap { | 139 | impl TokenMap { |
@@ -133,6 +152,28 @@ impl TokenMap { | |||
133 | } | 152 | } |
134 | } | 153 | } |
135 | 154 | ||
155 | impl ExpandedRangeMap { | ||
156 | fn set(&mut self, relative_range: TextRange, token_id: &tt::TokenId) { | ||
157 | self.ranges.push((relative_range, token_id.clone())) | ||
158 | } | ||
159 | |||
160 | pub fn ranges(&self, to: &TokenMap) -> Vec<(TextRange, TextRange)> { | ||
161 | self.ranges | ||
162 | .iter() | ||
163 | .filter_map(|(r, tid)| { | ||
164 | if to.map_id == tid.map_id() { | ||
165 | return None; | ||
166 | } | ||
167 | if let Some(to_range) = to.relative_range_of(*tid) { | ||
168 | Some((*r, to_range)) | ||
169 | } else { | ||
170 | None | ||
171 | } | ||
172 | }) | ||
173 | .collect() | ||
174 | } | ||
175 | } | ||
176 | |||
136 | /// Returns the textual content of a doc comment block as a quoted string | 177 | /// Returns the textual content of a doc comment block as a quoted string |
137 | /// That is, strips leading `///` (or `/**`, etc) | 178 | /// That is, strips leading `///` (or `/**`, etc) |
138 | /// and strips the ending `*/` | 179 | /// and strips the ending `*/` |
@@ -279,6 +320,8 @@ struct TtTreeSink<'a> { | |||
279 | cursor: Cursor<'a>, | 320 | cursor: Cursor<'a>, |
280 | text_pos: TextUnit, | 321 | text_pos: TextUnit, |
281 | inner: SyntaxTreeBuilder, | 322 | inner: SyntaxTreeBuilder, |
323 | range_marker: Option<(TextRange, tt::TokenId)>, | ||
324 | range_map: &'a mut ExpandedRangeMap, | ||
282 | 325 | ||
283 | // Number of roots | 326 | // Number of roots |
284 | // Use for detect ill-form tree which is not single root | 327 | // Use for detect ill-form tree which is not single root |
@@ -286,13 +329,15 @@ struct TtTreeSink<'a> { | |||
286 | } | 329 | } |
287 | 330 | ||
288 | impl<'a> TtTreeSink<'a> { | 331 | impl<'a> TtTreeSink<'a> { |
289 | fn new(cursor: Cursor<'a>) -> Self { | 332 | fn new(cursor: Cursor<'a>, range_map: &'a mut ExpandedRangeMap) -> Self { |
290 | TtTreeSink { | 333 | TtTreeSink { |
291 | buf: String::new(), | 334 | buf: String::new(), |
292 | cursor, | 335 | cursor, |
293 | text_pos: 0.into(), | 336 | text_pos: 0.into(), |
294 | inner: SyntaxTreeBuilder::default(), | 337 | inner: SyntaxTreeBuilder::default(), |
295 | roots: smallvec::SmallVec::new(), | 338 | roots: smallvec::SmallVec::new(), |
339 | range_map, | ||
340 | range_marker: None, | ||
296 | } | 341 | } |
297 | } | 342 | } |
298 | } | 343 | } |
@@ -317,6 +362,8 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
317 | return; | 362 | return; |
318 | } | 363 | } |
319 | 364 | ||
365 | let mut last_ident = None; | ||
366 | |||
320 | for _ in 0..n_tokens { | 367 | for _ in 0..n_tokens { |
321 | if self.cursor.eof() { | 368 | if self.cursor.eof() { |
322 | break; | 369 | break; |
@@ -326,6 +373,10 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
326 | Some(tt::TokenTree::Leaf(leaf)) => { | 373 | Some(tt::TokenTree::Leaf(leaf)) => { |
327 | self.cursor = self.cursor.bump(); | 374 | self.cursor = self.cursor.bump(); |
328 | self.buf += &format!("{}", leaf); | 375 | self.buf += &format!("{}", leaf); |
376 | |||
377 | if let tt::Leaf::Ident(ident) = leaf { | ||
378 | last_ident = Some(ident); | ||
379 | } | ||
329 | } | 380 | } |
330 | Some(tt::TokenTree::Subtree(subtree)) => { | 381 | Some(tt::TokenTree::Subtree(subtree)) => { |
331 | self.cursor = self.cursor.subtree().unwrap(); | 382 | self.cursor = self.cursor.subtree().unwrap(); |
@@ -345,6 +396,14 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
345 | self.buf.clear(); | 396 | self.buf.clear(); |
346 | self.inner.token(kind, text); | 397 | self.inner.token(kind, text); |
347 | 398 | ||
399 | // Mark the range if needed | ||
400 | if let Some((range, token_id)) = self.range_marker.as_mut() { | ||
401 | if let Some(ident) = last_ident { | ||
402 | *range = TextRange::offset_len(range.start(), TextUnit::of_str(&ident.text)); | ||
403 | *token_id = ident.id; | ||
404 | } | ||
405 | } | ||
406 | |||
348 | // Add whitespace between adjoint puncts | 407 | // Add whitespace between adjoint puncts |
349 | let next = self.cursor.bump(); | 408 | let next = self.cursor.bump(); |
350 | if let ( | 409 | if let ( |
@@ -354,6 +413,7 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
354 | { | 413 | { |
355 | if curr.spacing == tt::Spacing::Alone { | 414 | if curr.spacing == tt::Spacing::Alone { |
356 | self.inner.token(WHITESPACE, " ".into()); | 415 | self.inner.token(WHITESPACE, " ".into()); |
416 | self.text_pos += TextUnit::of_char(' '); | ||
357 | } | 417 | } |
358 | } | 418 | } |
359 | } | 419 | } |
@@ -361,6 +421,15 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
361 | fn start_node(&mut self, kind: SyntaxKind) { | 421 | fn start_node(&mut self, kind: SyntaxKind) { |
362 | self.inner.start_node(kind); | 422 | self.inner.start_node(kind); |
363 | 423 | ||
424 | self.range_marker = if kind == IDENT { | ||
425 | Some(( | ||
426 | TextRange::offset_len(self.text_pos, TextUnit::from_usize(0)), | ||
427 | tt::TokenId::unspecified(), | ||
428 | )) | ||
429 | } else { | ||
430 | None | ||
431 | }; | ||
432 | |||
364 | match self.roots.last_mut() { | 433 | match self.roots.last_mut() { |
365 | None | Some(0) => self.roots.push(1), | 434 | None | Some(0) => self.roots.push(1), |
366 | Some(ref mut n) => **n += 1, | 435 | Some(ref mut n) => **n += 1, |
@@ -370,6 +439,12 @@ impl<'a> TreeSink for TtTreeSink<'a> { | |||
370 | fn finish_node(&mut self) { | 439 | fn finish_node(&mut self) { |
371 | self.inner.finish_node(); | 440 | self.inner.finish_node(); |
372 | *self.roots.last_mut().unwrap() -= 1; | 441 | *self.roots.last_mut().unwrap() -= 1; |
442 | |||
443 | if let Some(range) = self.range_marker { | ||
444 | if range.1 != tt::TokenId::unspecified() { | ||
445 | self.range_map.set(range.0, &range.1) | ||
446 | } | ||
447 | } | ||
373 | } | 448 | } |
374 | 449 | ||
375 | fn error(&mut self, error: ParseError) { | 450 | fn error(&mut self, error: ParseError) { |