diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/macros.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir/src/macros/tt.rs | 12 |
2 files changed, 43 insertions, 7 deletions
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index 647df4260..9ba381685 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs | |||
@@ -16,6 +16,7 @@ use std::sync::Arc; | |||
16 | 16 | ||
17 | use ra_syntax::{ | 17 | use ra_syntax::{ |
18 | TextRange, TextUnit, SourceFile, AstNode, SyntaxNode, TreeArc, SyntaxNodePtr, | 18 | TextRange, TextUnit, SourceFile, AstNode, SyntaxNode, TreeArc, SyntaxNodePtr, |
19 | SyntaxKind::*, | ||
19 | ast::{self, NameOwner}, | 20 | ast::{self, NameOwner}, |
20 | }; | 21 | }; |
21 | 22 | ||
@@ -201,6 +202,39 @@ pub(crate) fn expand_macro_invocation( | |||
201 | def.expand(input).map(Arc::new) | 202 | def.expand(input).map(Arc::new) |
202 | } | 203 | } |
203 | 204 | ||
204 | fn macro_call_to_tt(call: &ast::MacroCall) -> Option<tt::TokenTree> { | 205 | fn macro_call_to_tt(call: &ast::MacroCall) -> Option<tt::Subtree> { |
205 | None | 206 | let tt = call.token_tree()?; |
207 | convert_tt(tt.syntax()) | ||
208 | } | ||
209 | |||
210 | fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> { | ||
211 | let first_child = tt.first_child()?; | ||
212 | let last_child = tt.last_child()?; | ||
213 | let delimiter = match (first_child.kind(), last_child.kind()) { | ||
214 | (L_PAREN, R_PAREN) => tt::Delimiter::Parenthesis, | ||
215 | (L_CURLY, R_CURLY) => tt::Delimiter::Brace, | ||
216 | (L_BRACK, R_BRACK) => tt::Delimiter::Bracket, | ||
217 | _ => return None, | ||
218 | }; | ||
219 | let mut token_trees = Vec::new(); | ||
220 | for child in tt.children().skip(1) { | ||
221 | if child == first_child || child == last_child || child.kind().is_trivia() { | ||
222 | continue; | ||
223 | } | ||
224 | let child = if child.kind() == TOKEN_TREE { | ||
225 | convert_tt(child)?.into() | ||
226 | } else if child.kind().is_keyword() { | ||
227 | let text = child.leaf_text().unwrap().clone(); | ||
228 | tt::Leaf::from(tt::Ident { text }).into() | ||
229 | } else { | ||
230 | return None; | ||
231 | }; | ||
232 | token_trees.push(child) | ||
233 | } | ||
234 | |||
235 | let res = tt::Subtree { | ||
236 | delimiter, | ||
237 | token_trees, | ||
238 | }; | ||
239 | Some(res) | ||
206 | } | 240 | } |
diff --git a/crates/ra_hir/src/macros/tt.rs b/crates/ra_hir/src/macros/tt.rs index 817cb262e..11b1089d3 100644 --- a/crates/ra_hir/src/macros/tt.rs +++ b/crates/ra_hir/src/macros/tt.rs | |||
@@ -4,16 +4,18 @@ pub(crate) enum TokenTree { | |||
4 | Leaf(Leaf), | 4 | Leaf(Leaf), |
5 | Subtree(Subtree), | 5 | Subtree(Subtree), |
6 | } | 6 | } |
7 | impl_froms!(TokenTree: Leaf, Subtree); | ||
7 | 8 | ||
8 | pub(crate) enum Leaf { | 9 | pub(crate) enum Leaf { |
9 | Literal(Literal), | 10 | Literal(Literal), |
10 | Punct(Punct), | 11 | Punct(Punct), |
11 | Ident(Ident), | 12 | Ident(Ident), |
12 | } | 13 | } |
14 | impl_froms!(Leaf: Literal, Punct, Ident); | ||
13 | 15 | ||
14 | pub(crate) struct Subtree { | 16 | pub(crate) struct Subtree { |
15 | delimiter: Delimiter, | 17 | pub(crate) delimiter: Delimiter, |
16 | token_trees: Vec<TokenTree>, | 18 | pub(crate) token_trees: Vec<TokenTree>, |
17 | } | 19 | } |
18 | 20 | ||
19 | pub(crate) enum Delimiter { | 21 | pub(crate) enum Delimiter { |
@@ -24,13 +26,13 @@ pub(crate) enum Delimiter { | |||
24 | } | 26 | } |
25 | 27 | ||
26 | pub(crate) struct Literal { | 28 | pub(crate) struct Literal { |
27 | text: SmolStr, | 29 | pub(crate) text: SmolStr, |
28 | } | 30 | } |
29 | 31 | ||
30 | pub(crate) struct Punct { | 32 | pub(crate) struct Punct { |
31 | char: char, | 33 | pub(crate) char: char, |
32 | } | 34 | } |
33 | 35 | ||
34 | pub(crate) struct Ident { | 36 | pub(crate) struct Ident { |
35 | text: SmolStr, | 37 | pub(crate) text: SmolStr, |
36 | } | 38 | } |