diff options
Diffstat (limited to 'crates/ra_hir_def/src/item_scope.rs')
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 79 |
1 files changed, 69 insertions, 10 deletions
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index c81b966c3..4d446c707 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -4,14 +4,27 @@ | |||
4 | use hir_expand::name::Name; | 4 | use hir_expand::name::Name; |
5 | use once_cell::sync::Lazy; | 5 | use once_cell::sync::Lazy; |
6 | use ra_db::CrateId; | 6 | use ra_db::CrateId; |
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::{FxHashMap, FxHashSet}; |
8 | use test_utils::mark; | 8 | use test_utils::mark; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, | 11 | db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId, |
12 | Lookup, MacroDefId, ModuleDefId, TraitId, | 12 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #[derive(Copy, Clone)] | ||
16 | pub(crate) enum ImportType { | ||
17 | Glob, | ||
18 | Named, | ||
19 | } | ||
20 | |||
21 | #[derive(Debug, Default)] | ||
22 | pub struct PerNsGlobImports { | ||
23 | types: FxHashSet<(LocalModuleId, Name)>, | ||
24 | values: FxHashSet<(LocalModuleId, Name)>, | ||
25 | macros: FxHashSet<(LocalModuleId, Name)>, | ||
26 | } | ||
27 | |||
15 | #[derive(Debug, Default, PartialEq, Eq)] | 28 | #[derive(Debug, Default, PartialEq, Eq)] |
16 | pub struct ItemScope { | 29 | pub struct ItemScope { |
17 | visible: FxHashMap<Name, PerNs>, | 30 | visible: FxHashMap<Name, PerNs>, |
@@ -127,16 +140,62 @@ impl ItemScope { | |||
127 | let mut changed = false; | 140 | let mut changed = false; |
128 | let existing = self.visible.entry(name).or_default(); | 141 | let existing = self.visible.entry(name).or_default(); |
129 | 142 | ||
143 | if existing.types.is_none() && def.types.is_some() { | ||
144 | existing.types = def.types; | ||
145 | changed = true; | ||
146 | } | ||
147 | |||
148 | if existing.values.is_none() && def.values.is_some() { | ||
149 | existing.values = def.values; | ||
150 | changed = true; | ||
151 | } | ||
152 | |||
153 | if existing.macros.is_none() && def.macros.is_some() { | ||
154 | existing.macros = def.macros; | ||
155 | changed = true; | ||
156 | } | ||
157 | |||
158 | changed | ||
159 | } | ||
160 | |||
161 | pub(crate) fn push_res_with_import( | ||
162 | &mut self, | ||
163 | glob_imports: &mut PerNsGlobImports, | ||
164 | lookup: (LocalModuleId, Name), | ||
165 | def: PerNs, | ||
166 | def_import_type: ImportType, | ||
167 | ) -> bool { | ||
168 | let mut changed = false; | ||
169 | let existing = self.visible.entry(lookup.1.clone()).or_default(); | ||
170 | |||
130 | macro_rules! check_changed { | 171 | macro_rules! check_changed { |
131 | ($changed:ident, $existing:expr, $def:expr) => { | 172 | ( |
132 | match ($existing, $def) { | 173 | $changed:ident, |
174 | ( $existing:ident / $def:ident ) . $field:ident, | ||
175 | $glob_imports:ident [ $lookup:ident ], | ||
176 | $def_import_type:ident | ||
177 | ) => { | ||
178 | match ($existing.$field, $def.$field) { | ||
133 | (None, Some(_)) => { | 179 | (None, Some(_)) => { |
134 | $existing = $def; | 180 | match $def_import_type { |
181 | ImportType::Glob => { | ||
182 | $glob_imports.$field.insert($lookup.clone()); | ||
183 | } | ||
184 | ImportType::Named => { | ||
185 | $glob_imports.$field.remove(&$lookup); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | $existing.$field = $def.$field; | ||
135 | $changed = true; | 190 | $changed = true; |
136 | } | 191 | } |
137 | (Some(e), Some(d)) if e.0 != d.0 => { | 192 | (Some(_), Some(_)) |
193 | if $glob_imports.$field.contains(&$lookup) | ||
194 | && matches!($def_import_type, ImportType::Named) => | ||
195 | { | ||
138 | mark::hit!(import_shadowed); | 196 | mark::hit!(import_shadowed); |
139 | $existing = $def; | 197 | $glob_imports.$field.remove(&$lookup); |
198 | $existing.$field = $def.$field; | ||
140 | $changed = true; | 199 | $changed = true; |
141 | } | 200 | } |
142 | _ => {} | 201 | _ => {} |
@@ -144,9 +203,9 @@ impl ItemScope { | |||
144 | }; | 203 | }; |
145 | } | 204 | } |
146 | 205 | ||
147 | check_changed!(changed, existing.types, def.types); | 206 | check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type); |
148 | check_changed!(changed, existing.values, def.values); | 207 | check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type); |
149 | check_changed!(changed, existing.macros, def.macros); | 208 | check_changed!(changed, (existing / def).macros, glob_imports[lookup], def_import_type); |
150 | 209 | ||
151 | changed | 210 | changed |
152 | } | 211 | } |