about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2022-03-18 11:55:53 +0100
committerLukas Wirth <lukastw97@gmail.com>2022-03-18 12:01:59 +0100
commit828196be3bd92ba33e62270d24dae79bd2eb5125 (patch)
tree2ada73ff6d50de07d05e8c9f4faa9916ac14cb8d
parentbd17933c31b7e4e8b1750c59a8de2e4ab0268c33 (diff)
downloadrust-828196be3bd92ba33e62270d24dae79bd2eb5125.tar.gz
rust-828196be3bd92ba33e62270d24dae79bd2eb5125.zip
fix: Fix runnables trying to add doc tests in the crate root from #[macro_export] macros
-rw-r--r--crates/hir/src/lib.rs10
-rw-r--r--crates/hir_def/src/data.rs8
-rw-r--r--crates/hir_def/src/item_scope.rs1
-rw-r--r--crates/ide/src/runnables.rs72
-rw-r--r--crates/ide_db/src/defs.rs2
-rw-r--r--crates/ide_db/src/helpers.rs8
6 files changed, 98 insertions, 3 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ee4ff0aebbd..9207614c68d 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -570,6 +570,12 @@ impl Module {
             .collect()
     }
 
+    pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
+        let def_map = self.id.def_map(db.upcast());
+        let scope = &def_map[self.id.local_id].scope;
+        scope.legacy_macros().map(|(_, it)| MacroId::from(it).into()).collect()
+    }
+
     pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
         let def_map = self.id.def_map(db.upcast());
         def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
@@ -1789,6 +1795,10 @@ impl Macro {
         }
     }
 
+    pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
+        matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
+    }
+
     pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
         match self.id {
             MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs
index 456ed9e6103..ffb733c2b97 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -315,6 +315,7 @@ impl Macro2Data {
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct MacroRulesData {
     pub name: Name,
+    pub macro_export: bool,
 }
 
 impl MacroRulesData {
@@ -326,7 +327,12 @@ impl MacroRulesData {
         let item_tree = loc.id.item_tree(db);
         let makro = &item_tree[loc.id.value];
 
-        Arc::new(MacroRulesData { name: makro.name.clone() })
+        let macro_export = item_tree
+            .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
+            .by_key("macro_export")
+            .exists();
+
+        Arc::new(MacroRulesData { name: makro.name.clone(), macro_export })
     }
 }
 #[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index e6fdd41bd86..f1330b34d1f 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -63,6 +63,7 @@ pub struct ItemScope {
     // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
     // be all resolved to the last one defined if shadowing happens.
     legacy_macros: FxHashMap<Name, MacroRulesId>,
+    /// The derive macro invocations in this scope.
     attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
     /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
     /// paired with the derive macro invocations for the specific attribute.
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 1507e7cdd07..2c8e898d723 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -157,7 +157,13 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
             Definition::SelfType(impl_) => runnable_impl(&sema, &impl_),
             _ => None,
         };
-        add_opt(runnable.or_else(|| module_def_doctest(sema.db, def)), Some(def));
+        add_opt(
+            runnable
+                .or_else(|| module_def_doctest(sema.db, def))
+                // #[macro_export] mbe macros are declared in the root, while their definition may reside in a different module
+                .filter(|it| it.nav.file_id == file_id),
+            Some(def),
+        );
         if let Definition::SelfType(impl_) = def {
             impl_.items(db).into_iter().for_each(|assoc| {
                 let runnable = match assoc {
@@ -2074,4 +2080,68 @@ impl<T, U> Foo<T, U> {
             "#]],
         );
     }
+
+    #[test]
+    fn doc_test_macro_export_mbe() {
+        check(
+            r#"
+//- /lib.rs
+$0
+mod foo;
+
+//- /foo.rs
+/// ```
+/// fn foo() {
+/// }
+/// ```
+#[macro_export]
+macro_rules! foo {
+    () => {
+
+    };
+}
+"#,
+            &[],
+            expect![[r#"
+                []
+            "#]],
+        );
+        check(
+            r#"
+//- /lib.rs
+$0
+/// ```
+/// fn foo() {
+/// }
+/// ```
+#[macro_export]
+macro_rules! foo {
+    () => {
+
+    };
+}
+"#,
+            &[DocTest],
+            expect![[r#"
+                [
+                    Runnable {
+                        use_name_in_title: false,
+                        nav: NavigationTarget {
+                            file_id: FileId(
+                                0,
+                            ),
+                            full_range: 1..94,
+                            name: "foo",
+                        },
+                        kind: DocTest {
+                            test_id: Path(
+                                "foo",
+                            ),
+                        },
+                        cfg: None,
+                    },
+                ]
+            "#]],
+        );
+    }
 }
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index e60c3b04e85..36457a5364f 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -447,7 +447,7 @@ impl NameRefClass {
 
 impl_from!(
     Field, Module, Function, Adt, Variant, Const, Static, Trait, TypeAlias, BuiltinType, Local,
-    GenericParam, Label
+    GenericParam, Label, Macro
     for Definition
 );
 
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index 4046c2febb6..d4fda397d68 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -76,6 +76,14 @@ pub fn visit_file_defs(
         cb(def.into());
     }
     module.impl_defs(db).into_iter().for_each(|impl_| cb(impl_.into()));
+
+    let is_root = module.is_crate_root(db);
+    module
+        .legacy_macros(db)
+        .into_iter()
+        // don't show legacy macros declared in the crate-root that were already covered in declarations earlier
+        .filter(|it| !(is_root && it.is_macro_export(db)))
+        .for_each(|mac| cb(mac.into()));
 }
 
 /// Checks if the given lint is equal or is contained by the other lint which may or may not be a group.