about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-expand/src/lib.rs2
-rw-r--r--crates/ide/src/navigation_target.rs26
2 files changed, 21 insertions, 7 deletions
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index b5197d4c25d..6a122e0859c 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -220,6 +220,8 @@ pub enum MacroCallKind {
     },
     Attr {
         ast_id: AstId<ast::Item>,
+        // FIXME: This is being interned, subtrees can very quickly differ just slightly causing
+        // leakage problems here
         attr_args: Option<Arc<tt::Subtree>>,
         /// Syntactical index of the invoking `#[attribute]`.
         ///
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index 6cb7d7724d5..8dcbea50920 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -724,11 +724,8 @@ fn orig_range_with_focus(
 ) -> UpmappingResult<(FileRange, Option<TextRange>)> {
     let Some(name) = name else { return orig_range(db, hir_file, value) };
 
-    let call_range = || {
-        db.lookup_intern_macro_call(hir_file.macro_file().unwrap().macro_call_id)
-            .kind
-            .original_call_range(db)
-    };
+    let call_kind =
+        || db.lookup_intern_macro_call(hir_file.macro_file().unwrap().macro_call_id).kind;
 
     let def_range = || {
         db.lookup_intern_macro_call(hir_file.macro_file().unwrap().macro_call_id)
@@ -755,7 +752,22 @@ fn orig_range_with_focus(
                             }
                             // name lies outside the node, so instead point to the macro call which
                             // *should* contain the name
-                            _ => call_range(),
+                            _ => {
+                                let kind = call_kind();
+                                let range = kind.clone().original_call_range_with_body(db);
+                                //If the focus range is in the attribute/derive body, we
+                                // need to point the call site to the entire body, if not, fall back
+                                // to the name range of the attribute/derive call
+                                // FIXME: Do this differently, this is very inflexible the caller
+                                // should choose this behavior
+                                if range.file_id == focus_range.file_id
+                                    && range.range.contains_range(focus_range.range)
+                                {
+                                    range
+                                } else {
+                                    kind.original_call_range(db)
+                                }
+                            }
                         },
                         Some(focus_range),
                     ),
@@ -784,7 +796,7 @@ fn orig_range_with_focus(
                     // node is in macro def, just show the focus
                     _ => (
                         // show the macro call
-                        (call_range(), None),
+                        (call_kind().original_call_range(db), None),
                         Some((focus_range, Some(focus_range))),
                     ),
                 }