mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 19:23:50 +00:00
Merge #7110
7110: Deduplicate macros when offering completion r=matklad a=AdnoC Closes https://github.com/rust-analyzer/rust-analyzer/issues/7081 When iterating over the names within the `hir_def::resolver::Scope` for a module, track what macros are in the `hir_def::item_scope::ItemScope::legacy_macros` collection for the module. When iterating over names from the prelude, do not proccess the name if it had been in the `legacy_macros` collection. This is implemented with a `FxHashSet` in the `Scope::process_names` function that is populated when iterating over `legacy_macros` and checked when iterating over the prelude. Alternative implementation could instead query the `legacy_macros` `FxHashMap` directly when processing names in the prelude. Also, I'd like to add a test for this, but I'm not sure where it could be added. Co-authored-by: AdnoC <adam.r.cutler@gmail.com>
This commit is contained in:
commit
184f4cbf5d
@ -7,7 +7,7 @@ use hir_expand::MacroDefId;
|
||||
|
||||
use crate::{item_scope::ItemInNs, visibility::Visibility, ModuleDefId};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PerNs {
|
||||
pub types: Option<(ModuleDefId, Visibility)>,
|
||||
pub values: Option<(ModuleDefId, Visibility)>,
|
||||
|
@ -490,6 +490,7 @@ pub enum ScopeDef {
|
||||
|
||||
impl Scope {
|
||||
fn process_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
|
||||
let mut seen = FxHashSet::default();
|
||||
match self {
|
||||
Scope::ModuleScope(m) => {
|
||||
// FIXME: should we provide `self` here?
|
||||
@ -503,7 +504,9 @@ impl Scope {
|
||||
f(name.clone(), ScopeDef::PerNs(def));
|
||||
});
|
||||
m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
|
||||
f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_, Visibility::Public)));
|
||||
let scope = PerNs::macros(macro_, Visibility::Public);
|
||||
seen.insert((name.clone(), scope));
|
||||
f(name.clone(), ScopeDef::PerNs(scope));
|
||||
});
|
||||
m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| {
|
||||
f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public)));
|
||||
@ -514,7 +517,10 @@ impl Scope {
|
||||
if let Some(prelude) = m.crate_def_map.prelude {
|
||||
let prelude_def_map = db.crate_def_map(prelude.krate);
|
||||
prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
|
||||
f(name.clone(), ScopeDef::PerNs(def));
|
||||
let seen_tuple = (name.clone(), def);
|
||||
if !seen.contains(&seen_tuple) {
|
||||
f(seen_tuple.0, ScopeDef::PerNs(def));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ impl RawVisibility {
|
||||
}
|
||||
|
||||
/// Visibility of an item, with the path resolved.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Visibility {
|
||||
/// Visibility is restricted to a certain module.
|
||||
Module(ModuleId),
|
||||
|
Loading…
Reference in New Issue
Block a user