diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-11 18:32:18 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-11 18:32:18 +0000 |
commit | a78142cc648cd0c95dcaabc598d614f0edc24eb6 (patch) | |
tree | 6547cd1d0e5b7494ac6b9ec9b446ba0db4c149ad /crates/ra_mbe/src/syntax_bridge.rs | |
parent | b356ab46f2b7482bf1ae0c0f6cd5a87ece8742bf (diff) | |
parent | ae312680d6d7bb0cc00d2b8d9799249d36e0136e (diff) |
Merge #791
791: docs r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_mbe/src/syntax_bridge.rs')
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 9a2eceaba..848c785f8 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -1,10 +1,42 @@ | |||
1 | use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxKind::*}; | 1 | use ra_syntax::{ |
2 | AstNode, SyntaxNode, TextRange, | ||
3 | ast, SyntaxKind::*, TextUnit | ||
4 | }; | ||
2 | 5 | ||
3 | pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<tt::Subtree> { | 6 | /// Maps `tt::TokenId` to the relative range of the original token. |
4 | convert_tt(ast.syntax()) | 7 | #[derive(Default)] |
8 | pub struct TokenMap { | ||
9 | /// Maps `tt::TokenId` to the *relative* source range. | ||
10 | toknes: Vec<TextRange>, | ||
5 | } | 11 | } |
6 | 12 | ||
7 | fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { | 13 | /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro |
14 | /// will consume). | ||
15 | pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> { | ||
16 | let mut token_map = TokenMap::default(); | ||
17 | let node = ast.syntax(); | ||
18 | let tt = convert_tt(&mut token_map, node.range().start(), node)?; | ||
19 | Some((tt, token_map)) | ||
20 | } | ||
21 | |||
22 | impl TokenMap { | ||
23 | pub fn relative_range_of(&self, tt: tt::TokenId) -> Option<TextRange> { | ||
24 | let idx = tt.0 as usize; | ||
25 | self.toknes.get(idx).map(|&it| it) | ||
26 | } | ||
27 | |||
28 | fn alloc(&mut self, relative_range: TextRange) -> tt::TokenId { | ||
29 | let id = self.toknes.len(); | ||
30 | self.toknes.push(relative_range); | ||
31 | tt::TokenId(id as u32) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | fn convert_tt( | ||
36 | token_map: &mut TokenMap, | ||
37 | global_offset: TextUnit, | ||
38 | tt: &SyntaxNode, | ||
39 | ) -> Option<tt::Subtree> { | ||
8 | let first_child = tt.first_child()?; | 40 | let first_child = tt.first_child()?; |
9 | let last_child = tt.last_child()?; | 41 | let last_child = tt.last_child()?; |
10 | let delimiter = match (first_child.kind(), last_child.kind()) { | 42 | let delimiter = match (first_child.kind(), last_child.kind()) { |
@@ -34,10 +66,12 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { | |||
34 | } | 66 | } |
35 | } else { | 67 | } else { |
36 | let child: tt::TokenTree = if child.kind() == TOKEN_TREE { | 68 | let child: tt::TokenTree = if child.kind() == TOKEN_TREE { |
37 | convert_tt(child)?.into() | 69 | convert_tt(token_map, global_offset, child)?.into() |
38 | } else if child.kind().is_keyword() || child.kind() == IDENT { | 70 | } else if child.kind().is_keyword() || child.kind() == IDENT { |
71 | let relative_range = child.range() - global_offset; | ||
72 | let id = token_map.alloc(relative_range); | ||
39 | let text = child.leaf_text().unwrap().clone(); | 73 | let text = child.leaf_text().unwrap().clone(); |
40 | tt::Leaf::from(tt::Ident { text }).into() | 74 | tt::Leaf::from(tt::Ident { text, id }).into() |
41 | } else if child.kind().is_literal() { | 75 | } else if child.kind().is_literal() { |
42 | tt::Leaf::from(tt::Literal { text: child.leaf_text().unwrap().clone() }).into() | 76 | tt::Leaf::from(tt::Literal { text: child.leaf_text().unwrap().clone() }).into() |
43 | } else { | 77 | } else { |