aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe')
-rw-r--r--crates/ra_mbe/src/lib.rs8
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs38
2 files changed, 36 insertions, 10 deletions
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs
index b9f555ef6..ec2fd1eb5 100644
--- a/crates/ra_mbe/src/lib.rs
+++ b/crates/ra_mbe/src/lib.rs
@@ -144,8 +144,8 @@ impl_froms!(TokenTree: Leaf, Subtree);
144 let macro_invocation = 144 let macro_invocation =
145 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 145 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
146 146
147 let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); 147 let (definition_tt, _) = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
148 let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap(); 148 let (invocation_tt, _) = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
149 let rules = crate::MacroRules::parse(&definition_tt).unwrap(); 149 let rules = crate::MacroRules::parse(&definition_tt).unwrap();
150 let expansion = rules.expand(&invocation_tt).unwrap(); 150 let expansion = rules.expand(&invocation_tt).unwrap();
151 assert_eq!( 151 assert_eq!(
@@ -160,7 +160,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
160 let macro_definition = 160 let macro_definition =
161 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 161 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
162 162
163 let definition_tt = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap(); 163 let (definition_tt, _) = ast_to_token_tree(macro_definition.token_tree().unwrap()).unwrap();
164 crate::MacroRules::parse(&definition_tt).unwrap() 164 crate::MacroRules::parse(&definition_tt).unwrap()
165 } 165 }
166 166
@@ -169,7 +169,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
169 let macro_invocation = 169 let macro_invocation =
170 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); 170 source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
171 171
172 let invocation_tt = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap(); 172 let (invocation_tt, _) = ast_to_token_tree(macro_invocation.token_tree().unwrap()).unwrap();
173 173
174 let expaned = rules.expand(&invocation_tt).unwrap(); 174 let expaned = rules.expand(&invocation_tt).unwrap();
175 assert_eq!(expaned.to_string(), expansion); 175 assert_eq!(expaned.to_string(), expansion);
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index d734f5597..798f9d8fa 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -1,10 +1,34 @@
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#[derive(Default)]
4 convert_tt(ast.syntax()) 7pub struct TokenMap {
8 /// Maps `tt::TokenId` to the *relative* source range.
9 toknes: Vec<TextRange>,
5} 10}
6 11
7fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { 12pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> {
13 let mut token_map = TokenMap::default();
14 let node = ast.syntax();
15 let tt = convert_tt(&mut token_map, node.range().start(), node)?;
16 Some((tt, token_map))
17}
18
19impl TokenMap {
20 fn alloc(&mut self, relative_range: TextRange) -> tt::TokenId {
21 let id = self.toknes.len();
22 self.toknes.push(relative_range);
23 tt::TokenId(id as u32)
24 }
25}
26
27fn convert_tt(
28 token_map: &mut TokenMap,
29 global_offset: TextUnit,
30 tt: &SyntaxNode,
31) -> Option<tt::Subtree> {
8 let first_child = tt.first_child()?; 32 let first_child = tt.first_child()?;
9 let last_child = tt.last_child()?; 33 let last_child = tt.last_child()?;
10 let delimiter = match (first_child.kind(), last_child.kind()) { 34 let delimiter = match (first_child.kind(), last_child.kind()) {
@@ -34,10 +58,12 @@ fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
34 } 58 }
35 } else { 59 } else {
36 let child: tt::TokenTree = if child.kind() == TOKEN_TREE { 60 let child: tt::TokenTree = if child.kind() == TOKEN_TREE {
37 convert_tt(child)?.into() 61 convert_tt(token_map, global_offset, child)?.into()
38 } else if child.kind().is_keyword() || child.kind() == IDENT { 62 } else if child.kind().is_keyword() || child.kind() == IDENT {
63 let relative_range = child.range() - global_offset;
64 let id = token_map.alloc(relative_range);
39 let text = child.leaf_text().unwrap().clone(); 65 let text = child.leaf_text().unwrap().clone();
40 tt::Leaf::from(tt::Ident { text, id: tt::TokenId::unspecified() }).into() 66 tt::Leaf::from(tt::Ident { text, id }).into()
41 } else if child.kind().is_literal() { 67 } else if child.kind().is_literal() {
42 tt::Leaf::from(tt::Literal { text: child.leaf_text().unwrap().clone() }).into() 68 tt::Leaf::from(tt::Literal { text: child.leaf_text().unwrap().clone() }).into()
43 } else { 69 } else {