aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/resolver.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-01-14 10:00:46 +0000
committerGitHub <[email protected]>2021-01-14 10:00:46 +0000
commit184f4cbf5df909146b05aaa3b7f2f0b27ac36590 (patch)
treec9d803d2fefdc31278338fc67f6df8d1bf747a12 /crates/hir_def/src/resolver.rs
parent39167b97d8a62adadecc9b67caac65ec556768cf (diff)
parentcca0dfa79ed968d41464eb7beb7aaa970e2d429f (diff)
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 <[email protected]>
Diffstat (limited to 'crates/hir_def/src/resolver.rs')
-rw-r--r--crates/hir_def/src/resolver.rs10
1 files changed, 8 insertions, 2 deletions
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index e4152a0be..61059c349 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -490,6 +490,7 @@ pub enum ScopeDef {
490 490
491impl Scope { 491impl Scope {
492 fn process_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { 492 fn process_names(&self, db: &dyn DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) {
493 let mut seen = FxHashSet::default();
493 match self { 494 match self {
494 Scope::ModuleScope(m) => { 495 Scope::ModuleScope(m) => {
495 // FIXME: should we provide `self` here? 496 // FIXME: should we provide `self` here?
@@ -503,7 +504,9 @@ impl Scope {
503 f(name.clone(), ScopeDef::PerNs(def)); 504 f(name.clone(), ScopeDef::PerNs(def));
504 }); 505 });
505 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { 506 m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| {
506 f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_, Visibility::Public))); 507 let scope = PerNs::macros(macro_, Visibility::Public);
508 seen.insert((name.clone(), scope));
509 f(name.clone(), ScopeDef::PerNs(scope));
507 }); 510 });
508 m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| { 511 m.crate_def_map.extern_prelude.iter().for_each(|(name, &def)| {
509 f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public))); 512 f(name.clone(), ScopeDef::PerNs(PerNs::types(def, Visibility::Public)));
@@ -514,7 +517,10 @@ impl Scope {
514 if let Some(prelude) = m.crate_def_map.prelude { 517 if let Some(prelude) = m.crate_def_map.prelude {
515 let prelude_def_map = db.crate_def_map(prelude.krate); 518 let prelude_def_map = db.crate_def_map(prelude.krate);
516 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { 519 prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| {
517 f(name.clone(), ScopeDef::PerNs(def)); 520 let seen_tuple = (name.clone(), def);
521 if !seen.contains(&seen_tuple) {
522 f(seen_tuple.0, ScopeDef::PerNs(def));
523 }
518 }); 524 });
519 } 525 }
520 } 526 }