about summary refs log tree commit diff
diff options
context:
space:
mode:
authorunexge <unexge@gmail.com>2023-12-16 18:00:29 +0000
committerunexge <unexge@gmail.com>2023-12-16 18:00:29 +0000
commit3b8801c3acc3f2976f47ee3da18f41a6aadd0a85 (patch)
tree8f7e866dae2a56d81ac47fb5859c4bc87a46369f
parent0e4902467f8cf74ddf9d5fc1121294c38bdb286f (diff)
downloadrust-3b8801c3acc3f2976f47ee3da18f41a6aadd0a85.tar.gz
rust-3b8801c3acc3f2976f47ee3da18f41a6aadd0a85.zip
Go to definition for macros in `#[macro_use(...)]`
-rw-r--r--crates/ide/src/goto_definition.rs71
1 files changed, 70 insertions, 1 deletions
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 7491879a67f..e0beba8fb38 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -4,7 +4,7 @@ use crate::{
     doc_links::token_as_doc_comment, navigation_target::ToNav, FilePosition, NavigationTarget,
     RangeInfo, TryToNav,
 };
-use hir::{AsAssocItem, AssocItem, DescendPreference, Semantics};
+use hir::{AsAssocItem, AssocItem, DescendPreference, ModuleDef, Semantics};
 use ide_db::{
     base_db::{AnchoredPath, FileId, FileLoader},
     defs::{Definition, IdentClass},
@@ -73,10 +73,15 @@ pub(crate) fn goto_definition(
         .into_iter()
         .filter_map(|token| {
             let parent = token.parent()?;
+
             if let Some(tt) = ast::TokenTree::cast(parent.clone()) {
                 if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), file_id) {
                     return Some(vec![x]);
                 }
+
+                if let Some(x) = try_lookup_macro_def_in_macro_use(sema, token.clone()) {
+                    return Some(vec![x]);
+                }
             }
             Some(
                 IdentClass::classify_node(sema, &parent)?
@@ -140,6 +145,27 @@ fn try_lookup_include_path(
     })
 }
 
+fn try_lookup_macro_def_in_macro_use(
+    sema: &Semantics<'_, RootDatabase>,
+    token: SyntaxToken,
+) -> Option<NavigationTarget> {
+    let extern_crate = token.parent()?.ancestors().find_map(ast::ExternCrate::cast)?;
+    let extern_crate = sema.to_def(&extern_crate)?;
+    let krate = extern_crate.resolved_crate(sema.db)?;
+
+    for mod_def in krate.root_module().declarations(sema.db) {
+        if let ModuleDef::Macro(mac) = mod_def {
+            if mac.name(sema.db).as_str() == Some(token.text()) {
+                if let Some(nav) = mac.try_to_nav(sema.db) {
+                    return Some(nav.call_site);
+                }
+            }
+        }
+    }
+
+    None
+}
+
 /// finds the trait definition of an impl'd item, except function
 /// e.g.
 /// ```rust
@@ -2081,4 +2107,47 @@ fn test() {
 "#,
         );
     }
+
+    #[test]
+    fn goto_macro_def_from_macro_use() {
+        check(
+            r#"
+//- /main.rs crate:main deps:mac
+#[macro_use(foo$0)]
+extern crate mac;
+
+//- /mac.rs crate:mac
+#[macro_export]
+macro_rules! foo {
+           //^^^
+    () => {};
+}
+            "#,
+        );
+
+        check(
+            r#"
+//- /main.rs crate:main deps:mac
+#[macro_use(foo, bar$0, baz)]
+extern crate mac;
+
+//- /mac.rs crate:mac
+#[macro_export]
+macro_rules! foo {
+    () => {};
+}
+
+#[macro_export]
+macro_rules! bar {
+           //^^^
+    () => {};
+}
+
+#[macro_export]
+macro_rules! baz {
+    () => {};
+}
+            "#,
+        );
+    }
 }