about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-14 09:22:04 +0000
committerbors <bors@rust-lang.org>2024-05-14 09:22:04 +0000
commit24cd4439ce9695a4efe08f9f2cb405e5e9c1c577 (patch)
treec16bfb36f86a98a6e8d9b13c9f8c66993c095fe5
parentb0ecc29a54c4d299c813edd4f6ad88f5ff73a670 (diff)
parent5fa2b06819cbc3c9cc221f29af5367939a517a22 (diff)
downloadrust-24cd4439ce9695a4efe08f9f2cb405e5e9c1c577.tar.gz
rust-24cd4439ce9695a4efe08f9f2cb405e5e9c1c577.zip
Auto merge of #17225 - Veykril:expand-macro-interlocked, r=Veykril
Expand macro recursively expands both fp-like and attribute macros when intertwined
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/expand_macro.rs42
1 files changed, 15 insertions, 27 deletions
diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
index e2d629a02fc..1ead045788f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
@@ -76,8 +76,6 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
         return derive;
     }
 
-    // FIXME: Intermix attribute and bang! expansions
-    // currently we only recursively expand one of the two types
     let mut anc = tok.parent_ancestors();
     let (name, expanded, kind) = loop {
         let node = anc.next()?;
@@ -86,7 +84,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
             if let Some(def) = sema.resolve_attr_macro_call(&item) {
                 break (
                     def.name(db).display(db).to_string(),
-                    expand_attr_macro_recur(&sema, &item)?,
+                    expand_macro_recur(&sema, &item)?,
                     SyntaxKind::MACRO_ITEMS,
                 );
             }
@@ -94,11 +92,9 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
         if let Some(mac) = ast::MacroCall::cast(node) {
             let mut name = mac.path()?.segment()?.name_ref()?.to_string();
             name.push('!');
-            break (
-                name,
-                expand_macro_recur(&sema, &mac)?,
-                mac.syntax().parent().map(|it| it.kind()).unwrap_or(SyntaxKind::MACRO_ITEMS),
-            );
+            let syntax_kind =
+                mac.syntax().parent().map(|it| it.kind()).unwrap_or(SyntaxKind::MACRO_ITEMS);
+            break (name, expand_macro_recur(&sema, &ast::Item::MacroCall(mac))?, syntax_kind);
         }
     };
 
@@ -112,31 +108,23 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
 
 fn expand_macro_recur(
     sema: &Semantics<'_, RootDatabase>,
-    macro_call: &ast::MacroCall,
-) -> Option<SyntaxNode> {
-    let expanded = sema.expand(macro_call)?.clone_for_update();
-    expand(sema, expanded, ast::MacroCall::cast, expand_macro_recur)
-}
-
-fn expand_attr_macro_recur(
-    sema: &Semantics<'_, RootDatabase>,
-    item: &ast::Item,
+    macro_call: &ast::Item,
 ) -> Option<SyntaxNode> {
-    let expanded = sema.expand_attr_macro(item)?.clone_for_update();
-    expand(sema, expanded, ast::Item::cast, expand_attr_macro_recur)
+    let expanded = match macro_call {
+        item @ ast::Item::MacroCall(macro_call) => {
+            sema.expand_attr_macro(item).or_else(|| sema.expand(macro_call))?.clone_for_update()
+        }
+        item => sema.expand_attr_macro(item)?.clone_for_update(),
+    };
+    expand(sema, expanded)
 }
 
-fn expand<T: AstNode>(
-    sema: &Semantics<'_, RootDatabase>,
-    expanded: SyntaxNode,
-    f: impl FnMut(SyntaxNode) -> Option<T>,
-    exp: impl Fn(&Semantics<'_, RootDatabase>, &T) -> Option<SyntaxNode>,
-) -> Option<SyntaxNode> {
-    let children = expanded.descendants().filter_map(f);
+fn expand(sema: &Semantics<'_, RootDatabase>, expanded: SyntaxNode) -> Option<SyntaxNode> {
+    let children = expanded.descendants().filter_map(ast::Item::cast);
     let mut replacements = Vec::new();
 
     for child in children {
-        if let Some(new_node) = exp(sema, &child) {
+        if let Some(new_node) = expand_macro_recur(sema, &child) {
             // check if the whole original syntax is replaced
             if expanded == *child.syntax() {
                 return Some(new_node);