diff options
Diffstat (limited to 'crates/ra_mbe/src')
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 38 |
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 @@ | |||
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 | #[derive(Default)] |
4 | convert_tt(ast.syntax()) | 7 | pub struct TokenMap { |
8 | /// Maps `tt::TokenId` to the *relative* source range. | ||
9 | toknes: Vec<TextRange>, | ||
5 | } | 10 | } |
6 | 11 | ||
7 | fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { | 12 | pub 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 | |||
19 | impl 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 | |||
27 | fn 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 { |