aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/syntax_bridge.rs
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2019-11-03 14:46:12 +0000
committerEdwin Cheng <[email protected]>2019-11-04 17:38:20 +0000
commit159da285e9d8594a2cc4436b5cee7874b07806c9 (patch)
tree15630e1158cfb7d7305cedd93c1a644b28f9b776 /crates/ra_mbe/src/syntax_bridge.rs
parent9fd546bec23ac817a45da28889e76118969db91e (diff)
Add macro_expansion_info in hir_expand
Diffstat (limited to 'crates/ra_mbe/src/syntax_bridge.rs')
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs113
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;
15use std::sync::atomic::{AtomicU32, Ordering}; 15use 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)]
18pub struct TokenMap { 19pub 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)]
40pub 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).
39pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> { 47pub 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
66fn fragment_to_syntax_node( 74fn 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
91pub fn token_tree_to_expr(tt: &tt::Subtree) -> Result<Parse<ast::Expr>, ExpandError> { 100pub 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
97pub fn token_tree_to_pat(tt: &tt::Subtree) -> Result<Parse<ast::Pat>, ExpandError> { 108pub 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
103pub fn token_tree_to_ty(tt: &tt::Subtree) -> Result<Parse<ast::TypeRef>, ExpandError> { 116pub 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
109pub fn token_tree_to_macro_stmts(tt: &tt::Subtree) -> Result<Parse<ast::MacroStmts>, ExpandError> { 124pub 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
115pub fn token_tree_to_items(tt: &tt::Subtree) -> Result<Parse<ast::MacroItems>, ExpandError> { 132pub 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
120impl TokenMap { 139impl TokenMap {
@@ -133,6 +152,28 @@ impl TokenMap {
133 } 152 }
134} 153}
135 154
155impl 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
288impl<'a> TtTreeSink<'a> { 331impl<'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) {