diff options
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r-- | crates/ra_hir_def/src/item_scope.rs | 113 |
1 files changed, 79 insertions, 34 deletions
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 4d446c707..7fc53d86d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs | |||
@@ -11,6 +11,7 @@ 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 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, | 12 | LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId, |
13 | }; | 13 | }; |
14 | use std::collections::hash_map::Entry; | ||
14 | 15 | ||
15 | #[derive(Copy, Clone)] | 16 | #[derive(Copy, Clone)] |
16 | pub(crate) enum ImportType { | 17 | pub(crate) enum ImportType { |
@@ -27,7 +28,11 @@ pub struct PerNsGlobImports { | |||
27 | 28 | ||
28 | #[derive(Debug, Default, PartialEq, Eq)] | 29 | #[derive(Debug, Default, PartialEq, Eq)] |
29 | pub struct ItemScope { | 30 | pub struct ItemScope { |
30 | visible: FxHashMap<Name, PerNs>, | 31 | types: FxHashMap<Name, (ModuleDefId, Visibility)>, |
32 | values: FxHashMap<Name, (ModuleDefId, Visibility)>, | ||
33 | macros: FxHashMap<Name, (MacroDefId, Visibility)>, | ||
34 | unresolved: FxHashSet<Name>, | ||
35 | |||
31 | defs: Vec<ModuleDefId>, | 36 | defs: Vec<ModuleDefId>, |
32 | impls: Vec<ImplId>, | 37 | impls: Vec<ImplId>, |
33 | /// Macros visible in current module in legacy textual scope | 38 | /// Macros visible in current module in legacy textual scope |
@@ -65,14 +70,22 @@ pub(crate) enum BuiltinShadowMode { | |||
65 | /// Other methods will only resolve values, types and module scoped macros only. | 70 | /// Other methods will only resolve values, types and module scoped macros only. |
66 | impl ItemScope { | 71 | impl ItemScope { |
67 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { | 72 | pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { |
68 | //FIXME: shadowing | 73 | // FIXME: shadowing |
69 | self.visible.iter().map(|(n, def)| (n, *def)) | 74 | let keys: FxHashSet<_> = self |
75 | .types | ||
76 | .keys() | ||
77 | .chain(self.values.keys()) | ||
78 | .chain(self.macros.keys()) | ||
79 | .chain(self.unresolved.iter()) | ||
80 | .collect(); | ||
81 | |||
82 | keys.into_iter().map(move |name| (name, self.get(name))) | ||
70 | } | 83 | } |
71 | 84 | ||
72 | pub fn entries_without_primitives<'a>( | 85 | pub fn entries_without_primitives<'a>( |
73 | &'a self, | 86 | &'a self, |
74 | ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { | 87 | ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { |
75 | self.visible.iter().map(|(n, def)| (n, *def)) | 88 | self.entries() |
76 | } | 89 | } |
77 | 90 | ||
78 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { | 91 | pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { |
@@ -91,7 +104,7 @@ impl ItemScope { | |||
91 | 104 | ||
92 | /// Iterate over all module scoped macros | 105 | /// Iterate over all module scoped macros |
93 | pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | 106 | pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { |
94 | self.visible.iter().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) | 107 | self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) |
95 | } | 108 | } |
96 | 109 | ||
97 | /// Iterate over all legacy textual scoped macros visible at the end of the module | 110 | /// Iterate over all legacy textual scoped macros visible at the end of the module |
@@ -101,12 +114,16 @@ impl ItemScope { | |||
101 | 114 | ||
102 | /// Get a name from current module scope, legacy macros are not included | 115 | /// Get a name from current module scope, legacy macros are not included |
103 | pub(crate) fn get(&self, name: &Name) -> PerNs { | 116 | pub(crate) fn get(&self, name: &Name) -> PerNs { |
104 | self.visible.get(name).copied().unwrap_or_else(PerNs::none) | 117 | PerNs { |
118 | types: self.types.get(name).copied(), | ||
119 | values: self.values.get(name).copied(), | ||
120 | macros: self.macros.get(name).copied(), | ||
121 | } | ||
105 | } | 122 | } |
106 | 123 | ||
107 | pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { | 124 | pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { |
108 | for (name, per_ns) in &self.visible { | 125 | for (name, per_ns) in self.entries() { |
109 | if let Some(vis) = item.match_with(*per_ns) { | 126 | if let Some(vis) = item.match_with(per_ns) { |
110 | return Some((name, vis)); | 127 | return Some((name, vis)); |
111 | } | 128 | } |
112 | } | 129 | } |
@@ -114,8 +131,8 @@ impl ItemScope { | |||
114 | } | 131 | } |
115 | 132 | ||
116 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { | 133 | pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { |
117 | self.visible.values().filter_map(|def| match def.take_types() { | 134 | self.types.values().filter_map(|(def, _)| match def { |
118 | Some(ModuleDefId::TraitId(t)) => Some(t), | 135 | ModuleDefId::TraitId(t) => Some(*t), |
119 | _ => None, | 136 | _ => None, |
120 | }) | 137 | }) |
121 | } | 138 | } |
@@ -138,21 +155,39 @@ impl ItemScope { | |||
138 | 155 | ||
139 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { | 156 | pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { |
140 | let mut changed = false; | 157 | let mut changed = false; |
141 | let existing = self.visible.entry(name).or_default(); | ||
142 | 158 | ||
143 | if existing.types.is_none() && def.types.is_some() { | 159 | if let Some(types) = def.types { |
144 | existing.types = def.types; | 160 | match self.types.entry(name.clone()) { |
145 | changed = true; | 161 | Entry::Occupied(_) => {} |
162 | Entry::Vacant(e) => { | ||
163 | e.insert(types); | ||
164 | changed = true; | ||
165 | } | ||
166 | } | ||
146 | } | 167 | } |
147 | 168 | if let Some(values) = def.values { | |
148 | if existing.values.is_none() && def.values.is_some() { | 169 | match self.values.entry(name.clone()) { |
149 | existing.values = def.values; | 170 | Entry::Occupied(_) => {} |
150 | changed = true; | 171 | Entry::Vacant(e) => { |
172 | e.insert(values); | ||
173 | changed = true; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | if let Some(macros) = def.macros { | ||
178 | match self.macros.entry(name.clone()) { | ||
179 | Entry::Occupied(_) => {} | ||
180 | Entry::Vacant(e) => { | ||
181 | e.insert(macros); | ||
182 | changed = true; | ||
183 | } | ||
184 | } | ||
151 | } | 185 | } |
152 | 186 | ||
153 | if existing.macros.is_none() && def.macros.is_some() { | 187 | if def.is_none() { |
154 | existing.macros = def.macros; | 188 | if self.unresolved.insert(name) { |
155 | changed = true; | 189 | changed = true; |
190 | } | ||
156 | } | 191 | } |
157 | 192 | ||
158 | changed | 193 | changed |
@@ -166,17 +201,17 @@ impl ItemScope { | |||
166 | def_import_type: ImportType, | 201 | def_import_type: ImportType, |
167 | ) -> bool { | 202 | ) -> bool { |
168 | let mut changed = false; | 203 | let mut changed = false; |
169 | let existing = self.visible.entry(lookup.1.clone()).or_default(); | ||
170 | 204 | ||
171 | macro_rules! check_changed { | 205 | macro_rules! check_changed { |
172 | ( | 206 | ( |
173 | $changed:ident, | 207 | $changed:ident, |
174 | ( $existing:ident / $def:ident ) . $field:ident, | 208 | ( $this:ident / $def:ident ) . $field:ident, |
175 | $glob_imports:ident [ $lookup:ident ], | 209 | $glob_imports:ident [ $lookup:ident ], |
176 | $def_import_type:ident | 210 | $def_import_type:ident |
177 | ) => { | 211 | ) => {{ |
178 | match ($existing.$field, $def.$field) { | 212 | let existing = $this.$field.entry($lookup.1.clone()); |
179 | (None, Some(_)) => { | 213 | match (existing, $def.$field) { |
214 | (Entry::Vacant(entry), Some(_)) => { | ||
180 | match $def_import_type { | 215 | match $def_import_type { |
181 | ImportType::Glob => { | 216 | ImportType::Glob => { |
182 | $glob_imports.$field.insert($lookup.clone()); | 217 | $glob_imports.$field.insert($lookup.clone()); |
@@ -186,32 +221,42 @@ impl ItemScope { | |||
186 | } | 221 | } |
187 | } | 222 | } |
188 | 223 | ||
189 | $existing.$field = $def.$field; | 224 | if let Some(fld) = $def.$field { |
225 | entry.insert(fld); | ||
226 | } | ||
190 | $changed = true; | 227 | $changed = true; |
191 | } | 228 | } |
192 | (Some(_), Some(_)) | 229 | (Entry::Occupied(mut entry), Some(_)) |
193 | if $glob_imports.$field.contains(&$lookup) | 230 | if $glob_imports.$field.contains(&$lookup) |
194 | && matches!($def_import_type, ImportType::Named) => | 231 | && matches!($def_import_type, ImportType::Named) => |
195 | { | 232 | { |
196 | mark::hit!(import_shadowed); | 233 | mark::hit!(import_shadowed); |
197 | $glob_imports.$field.remove(&$lookup); | 234 | $glob_imports.$field.remove(&$lookup); |
198 | $existing.$field = $def.$field; | 235 | if let Some(fld) = $def.$field { |
236 | entry.insert(fld); | ||
237 | } | ||
199 | $changed = true; | 238 | $changed = true; |
200 | } | 239 | } |
201 | _ => {} | 240 | _ => {} |
202 | } | 241 | } |
203 | }; | 242 | }}; |
204 | } | 243 | } |
205 | 244 | ||
206 | check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type); | 245 | check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type); |
207 | check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type); | 246 | check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type); |
208 | check_changed!(changed, (existing / def).macros, glob_imports[lookup], def_import_type); | 247 | check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type); |
248 | |||
249 | if def.is_none() { | ||
250 | if self.unresolved.insert(lookup.1) { | ||
251 | changed = true; | ||
252 | } | ||
253 | } | ||
209 | 254 | ||
210 | changed | 255 | changed |
211 | } | 256 | } |
212 | 257 | ||
213 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { | 258 | pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { |
214 | self.visible.iter().map(|(name, res)| (name.clone(), *res)) | 259 | self.entries().map(|(name, res)| (name.clone(), res)) |
215 | } | 260 | } |
216 | 261 | ||
217 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { | 262 | pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { |