aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/syntax_bridge.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-11 18:32:18 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-11 18:32:18 +0000
commita78142cc648cd0c95dcaabc598d614f0edc24eb6 (patch)
tree6547cd1d0e5b7494ac6b9ec9b446ba0db4c149ad /crates/ra_mbe/src/syntax_bridge.rs
parentb356ab46f2b7482bf1ae0c0f6cd5a87ece8742bf (diff)
parentae312680d6d7bb0cc00d2b8d9799249d36e0136e (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.rs46
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 @@
1use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxKind::*}; 1use ra_syntax::{
2 AstNode, SyntaxNode, TextRange,
3 ast, SyntaxKind::*, TextUnit
4};
2 5
3pub 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)]
8pub struct TokenMap {
9 /// Maps `tt::TokenId` to the *relative* source range.
10 toknes: Vec<TextRange>,
5} 11}
6 12
7fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { 13/// Convert the syntax tree (what user has written) to a `TokenTree` (what macro
14/// will consume).
15pub 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
22impl 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
35fn 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 {