aboutsummaryrefslogtreecommitdiff
path: root/crates/ide
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide')
-rw-r--r--crates/ide/src/expand_macro.rs34
-rw-r--r--crates/ide/src/syntax_highlighting.rs30
2 files changed, 57 insertions, 7 deletions
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(
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index 79c2f4a1e..b03f1c71f 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -192,6 +192,7 @@ fn traverse(
192 let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default(); 192 let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
193 193
194 let mut current_macro_call: Option<ast::MacroCall> = None; 194 let mut current_macro_call: Option<ast::MacroCall> = None;
195 let mut current_attr_macro_call = None;
195 let mut current_macro: Option<ast::Macro> = None; 196 let mut current_macro: Option<ast::Macro> = None;
196 let mut macro_highlighter = MacroHighlighter::default(); 197 let mut macro_highlighter = MacroHighlighter::default();
197 let mut inside_attribute = false; 198 let mut inside_attribute = false;
@@ -227,6 +228,19 @@ fn traverse(
227 } 228 }
228 _ => (), 229 _ => (),
229 } 230 }
231 match event.clone().map(|it| it.into_node().and_then(ast::Item::cast)) {
232 WalkEvent::Enter(Some(item)) => {
233 if sema.is_attr_macro_call(&item) {
234 current_attr_macro_call = Some(item);
235 }
236 }
237 WalkEvent::Leave(Some(item)) => {
238 if current_attr_macro_call == Some(item) {
239 current_attr_macro_call = None;
240 }
241 }
242 _ => (),
243 }
230 244
231 match event.clone().map(|it| it.into_node().and_then(ast::Macro::cast)) { 245 match event.clone().map(|it| it.into_node().and_then(ast::Macro::cast)) {
232 WalkEvent::Enter(Some(mac)) => { 246 WalkEvent::Enter(Some(mac)) => {
@@ -286,6 +300,22 @@ fn traverse(
286 } 300 }
287 None => token.into(), 301 None => token.into(),
288 } 302 }
303 } else if current_attr_macro_call.is_some() {
304 let token = match element.clone().into_token() {
305 Some(it) => it,
306 _ => continue,
307 };
308 let token = sema.descend_into_macros(token.clone());
309 match token.parent() {
310 Some(parent) => {
311 // We only care Name and Name_ref
312 match (token.kind(), parent.kind()) {
313 (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(),
314 _ => token.into(),
315 }
316 }
317 None => token.into(),
318 }
289 } else { 319 } else {
290 element.clone() 320 element.clone()
291 }; 321 };