mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
fix: Fix runnables trying to add doc tests in the crate root from #[macro_export] macros
This commit is contained in:
parent
bd17933c31
commit
828196be3b
6 changed files with 98 additions and 3 deletions
|
@ -570,6 +570,12 @@ impl Module {
|
||||||
.collect()
|
.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> {
|
pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
|
||||||
let def_map = self.id.def_map(db.upcast());
|
let def_map = self.id.def_map(db.upcast());
|
||||||
def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
|
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 {
|
pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
|
||||||
match self.id {
|
match self.id {
|
||||||
MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
|
MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
|
||||||
|
|
|
@ -315,6 +315,7 @@ impl Macro2Data {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct MacroRulesData {
|
pub struct MacroRulesData {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
|
pub macro_export: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MacroRulesData {
|
impl MacroRulesData {
|
||||||
|
@ -326,7 +327,12 @@ impl MacroRulesData {
|
||||||
let item_tree = loc.id.item_tree(db);
|
let item_tree = loc.id.item_tree(db);
|
||||||
let makro = &item_tree[loc.id.value];
|
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)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|
|
@ -63,6 +63,7 @@ pub struct ItemScope {
|
||||||
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
// 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.
|
// be all resolved to the last one defined if shadowing happens.
|
||||||
legacy_macros: FxHashMap<Name, MacroRulesId>,
|
legacy_macros: FxHashMap<Name, MacroRulesId>,
|
||||||
|
/// The derive macro invocations in this scope.
|
||||||
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
|
||||||
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
|
/// 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.
|
/// paired with the derive macro invocations for the specific attribute.
|
||||||
|
|
|
@ -157,7 +157,13 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
|
||||||
Definition::SelfType(impl_) => runnable_impl(&sema, &impl_),
|
Definition::SelfType(impl_) => runnable_impl(&sema, &impl_),
|
||||||
_ => None,
|
_ => 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 {
|
if let Definition::SelfType(impl_) = def {
|
||||||
impl_.items(db).into_iter().for_each(|assoc| {
|
impl_.items(db).into_iter().for_each(|assoc| {
|
||||||
let runnable = match 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,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,7 +447,7 @@ impl NameRefClass {
|
||||||
|
|
||||||
impl_from!(
|
impl_from!(
|
||||||
Field, Module, Function, Adt, Variant, Const, Static, Trait, TypeAlias, BuiltinType, Local,
|
Field, Module, Function, Adt, Variant, Const, Static, Trait, TypeAlias, BuiltinType, Local,
|
||||||
GenericParam, Label
|
GenericParam, Label, Macro
|
||||||
for Definition
|
for Definition
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,14 @@ pub fn visit_file_defs(
|
||||||
cb(def.into());
|
cb(def.into());
|
||||||
}
|
}
|
||||||
module.impl_defs(db).into_iter().for_each(|impl_| cb(impl_.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.
|
/// Checks if the given lint is equal or is contained by the other lint which may or may not be a group.
|
||||||
|
|
Loading…
Reference in a new issue