aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/semantics.rs16
-rw-r--r--crates/ide/src/expand_macro.rs34
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;
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use syntax::{ 5use 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
10use crate::FilePosition; 9use crate::FilePosition;
@@ -28,16 +27,37 @@ pub struct ExpandedMacro {
28pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> { 27pub(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
43fn expand_macro_recur( 63fn expand_macro_recur(