diff options
-rw-r--r-- | crates/hir/src/semantics.rs | 16 | ||||
-rw-r--r-- | crates/ide/src/expand_macro.rs | 34 |
2 files changed, 43 insertions, 7 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 0d55e4a3e..920e18208 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -117,6 +117,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
117 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { | 117 | pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { |
118 | self.imp.expand(macro_call) | 118 | self.imp.expand(macro_call) |
119 | } | 119 | } |
120 | |||
121 | /// If `item` has an attribute macro attached to it, expands it. | ||
122 | pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> { | ||
123 | self.imp.expand_attr_macro(item) | ||
124 | } | ||
125 | |||
120 | pub fn speculative_expand( | 126 | pub fn speculative_expand( |
121 | &self, | 127 | &self, |
122 | actual_macro_call: &ast::MacroCall, | 128 | actual_macro_call: &ast::MacroCall, |
@@ -332,6 +338,16 @@ impl<'db> SemanticsImpl<'db> { | |||
332 | Some(node) | 338 | Some(node) |
333 | } | 339 | } |
334 | 340 | ||
341 | fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> { | ||
342 | let sa = self.analyze(item.syntax()); | ||
343 | let src = InFile::new(sa.file_id, item.clone()); | ||
344 | let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?; | ||
345 | let file_id = macro_call_id.as_file(); | ||
346 | let node = self.db.parse_or_expand(file_id)?; | ||
347 | self.cache(node.clone(), file_id); | ||
348 | Some(node) | ||
349 | } | ||
350 | |||
335 | fn speculative_expand( | 351 | fn speculative_expand( |
336 | &self, | 352 | &self, |
337 | actual_macro_call: &ast::MacroCall, | 353 | actual_macro_call: &ast::MacroCall, |
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index e0d01fa96..3f38e2145 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs | |||
@@ -3,8 +3,7 @@ use std::iter; | |||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::RootDatabase; | 4 | use ide_db::RootDatabase; |
5 | use syntax::{ | 5 | use syntax::{ |
6 | algo::find_node_at_offset, ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*, | 6 | ast, match_ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*, SyntaxNode, WalkEvent, T, |
7 | SyntaxNode, WalkEvent, T, | ||
8 | }; | 7 | }; |
9 | 8 | ||
10 | use crate::FilePosition; | 9 | use crate::FilePosition; |
@@ -28,16 +27,37 @@ pub struct ExpandedMacro { | |||
28 | pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> { | 27 | pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> { |
29 | let sema = Semantics::new(db); | 28 | let sema = Semantics::new(db); |
30 | let file = sema.parse(position.file_id); | 29 | let file = sema.parse(position.file_id); |
31 | let mac = find_node_at_offset::<ast::MacroCall>(file.syntax(), position.offset)?; | ||
32 | let name = mac.path()?.segment()?.name_ref()?; | ||
33 | 30 | ||
34 | let expanded = expand_macro_recur(&sema, &mac)?; | 31 | let tok = file.syntax().token_at_offset(position.offset).left_biased()?; |
32 | let mut expanded = None; | ||
33 | let mut name = None; | ||
34 | for node in tok.ancestors() { | ||
35 | match_ast! { | ||
36 | match node { | ||
37 | ast::MacroCall(mac) => { | ||
38 | name = Some(mac.path()?.segment()?.name_ref()?.to_string()); | ||
39 | expanded = expand_macro_recur(&sema, &mac); | ||
40 | break; | ||
41 | }, | ||
42 | ast::Item(item) => { | ||
43 | // FIXME: add the macro name | ||
44 | // FIXME: make this recursive too | ||
45 | name = Some("?".to_string()); | ||
46 | expanded = sema.expand_attr_macro(&item); | ||
47 | if expanded.is_some() { | ||
48 | break; | ||
49 | } | ||
50 | }, | ||
51 | _ => {} | ||
52 | } | ||
53 | } | ||
54 | } | ||
35 | 55 | ||
36 | // FIXME: | 56 | // FIXME: |
37 | // macro expansion may lose all white space information | 57 | // macro expansion may lose all white space information |
38 | // But we hope someday we can use ra_fmt for that | 58 | // But we hope someday we can use ra_fmt for that |
39 | let expansion = insert_whitespaces(expanded); | 59 | let expansion = insert_whitespaces(expanded?); |
40 | Some(ExpandedMacro { name: name.to_string(), expansion }) | 60 | Some(ExpandedMacro { name: name?, expansion }) |
41 | } | 61 | } |
42 | 62 | ||
43 | fn expand_macro_recur( | 63 | fn expand_macro_recur( |