aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/item_scope.rs
diff options
context:
space:
mode:
authorZac Pullar-Strecker <[email protected]>2020-07-31 03:12:44 +0100
committerZac Pullar-Strecker <[email protected]>2020-07-31 03:12:44 +0100
commitf05d7b41a719d848844b054a16477b29d0f063c6 (patch)
tree0a8a0946e8aef2ce64d4c13d0035ba41cce2daf3 /crates/ra_hir_def/src/item_scope.rs
parent73ff610e41959e3e7c78a2b4b25b086883132956 (diff)
parent6b7cb8b5ab539fc4333ce34bc29bf77c976f232a (diff)
Merge remote-tracking branch 'upstream/master' into 503-hover-doc-links
Hasn't fixed tests yet.
Diffstat (limited to 'crates/ra_hir_def/src/item_scope.rs')
-rw-r--r--crates/ra_hir_def/src/item_scope.rs132
1 files changed, 90 insertions, 42 deletions
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index 4d446c707..8fee4b15e 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -1,6 +1,8 @@
1//! Describes items defined or visible (ie, imported) in a certain scope. 1//! Describes items defined or visible (ie, imported) in a certain scope.
2//! This is shared between modules and blocks. 2//! This is shared between modules and blocks.
3 3
4use std::collections::hash_map::Entry;
5
4use hir_expand::name::Name; 6use hir_expand::name::Name;
5use once_cell::sync::Lazy; 7use once_cell::sync::Lazy;
6use ra_db::CrateId; 8use ra_db::CrateId;
@@ -27,9 +29,15 @@ pub struct PerNsGlobImports {
27 29
28#[derive(Debug, Default, PartialEq, Eq)] 30#[derive(Debug, Default, PartialEq, Eq)]
29pub struct ItemScope { 31pub struct ItemScope {
30 visible: FxHashMap<Name, PerNs>, 32 types: FxHashMap<Name, (ModuleDefId, Visibility)>,
33 values: FxHashMap<Name, (ModuleDefId, Visibility)>,
34 macros: FxHashMap<Name, (MacroDefId, Visibility)>,
35 unresolved: FxHashSet<Name>,
36
31 defs: Vec<ModuleDefId>, 37 defs: Vec<ModuleDefId>,
32 impls: Vec<ImplId>, 38 impls: Vec<ImplId>,
39 /// Traits imported via `use Trait as _;`.
40 unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
33 /// Macros visible in current module in legacy textual scope 41 /// Macros visible in current module in legacy textual scope
34 /// 42 ///
35 /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. 43 /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first.
@@ -65,14 +73,16 @@ pub(crate) enum BuiltinShadowMode {
65/// Other methods will only resolve values, types and module scoped macros only. 73/// Other methods will only resolve values, types and module scoped macros only.
66impl ItemScope { 74impl ItemScope {
67 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { 75 pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
68 //FIXME: shadowing 76 // FIXME: shadowing
69 self.visible.iter().map(|(n, def)| (n, *def)) 77 let keys: FxHashSet<_> = self
70 } 78 .types
71 79 .keys()
72 pub fn entries_without_primitives<'a>( 80 .chain(self.values.keys())
73 &'a self, 81 .chain(self.macros.keys())
74 ) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a { 82 .chain(self.unresolved.iter())
75 self.visible.iter().map(|(n, def)| (n, *def)) 83 .collect();
84
85 keys.into_iter().map(move |name| (name, self.get(name)))
76 } 86 }
77 87
78 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ { 88 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
@@ -91,7 +101,7 @@ impl ItemScope {
91 101
92 /// Iterate over all module scoped macros 102 /// Iterate over all module scoped macros
93 pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 103 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_))) 104 self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
95 } 105 }
96 106
97 /// Iterate over all legacy textual scoped macros visible at the end of the module 107 /// Iterate over all legacy textual scoped macros visible at the end of the module
@@ -101,12 +111,16 @@ impl ItemScope {
101 111
102 /// Get a name from current module scope, legacy macros are not included 112 /// Get a name from current module scope, legacy macros are not included
103 pub(crate) fn get(&self, name: &Name) -> PerNs { 113 pub(crate) fn get(&self, name: &Name) -> PerNs {
104 self.visible.get(name).copied().unwrap_or_else(PerNs::none) 114 PerNs {
115 types: self.types.get(name).copied(),
116 values: self.values.get(name).copied(),
117 macros: self.macros.get(name).copied(),
118 }
105 } 119 }
106 120
107 pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> { 121 pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
108 for (name, per_ns) in &self.visible { 122 for (name, per_ns) in self.entries() {
109 if let Some(vis) = item.match_with(*per_ns) { 123 if let Some(vis) = item.match_with(per_ns) {
110 return Some((name, vis)); 124 return Some((name, vis));
111 } 125 }
112 } 126 }
@@ -114,10 +128,13 @@ impl ItemScope {
114 } 128 }
115 129
116 pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a { 130 pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
117 self.visible.values().filter_map(|def| match def.take_types() { 131 self.types
118 Some(ModuleDefId::TraitId(t)) => Some(t), 132 .values()
119 _ => None, 133 .filter_map(|(def, _)| match def {
120 }) 134 ModuleDefId::TraitId(t) => Some(*t),
135 _ => None,
136 })
137 .chain(self.unnamed_trait_imports.keys().copied())
121 } 138 }
122 139
123 pub(crate) fn define_def(&mut self, def: ModuleDefId) { 140 pub(crate) fn define_def(&mut self, def: ModuleDefId) {
@@ -136,23 +153,40 @@ impl ItemScope {
136 self.legacy_macros.insert(name, mac); 153 self.legacy_macros.insert(name, mac);
137 } 154 }
138 155
156 pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
157 self.unnamed_trait_imports.get(&tr).copied()
158 }
159
160 pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
161 self.unnamed_trait_imports.insert(tr, vis);
162 }
163
139 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { 164 pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
140 let mut changed = false; 165 let mut changed = false;
141 let existing = self.visible.entry(name).or_default();
142 166
143 if existing.types.is_none() && def.types.is_some() { 167 if let Some(types) = def.types {
144 existing.types = def.types; 168 self.types.entry(name.clone()).or_insert_with(|| {
145 changed = true; 169 changed = true;
170 types
171 });
146 } 172 }
147 173 if let Some(values) = def.values {
148 if existing.values.is_none() && def.values.is_some() { 174 self.values.entry(name.clone()).or_insert_with(|| {
149 existing.values = def.values; 175 changed = true;
150 changed = true; 176 values
177 });
178 }
179 if let Some(macros) = def.macros {
180 self.macros.entry(name.clone()).or_insert_with(|| {
181 changed = true;
182 macros
183 });
151 } 184 }
152 185
153 if existing.macros.is_none() && def.macros.is_some() { 186 if def.is_none() {
154 existing.macros = def.macros; 187 if self.unresolved.insert(name) {
155 changed = true; 188 changed = true;
189 }
156 } 190 }
157 191
158 changed 192 changed
@@ -166,17 +200,17 @@ impl ItemScope {
166 def_import_type: ImportType, 200 def_import_type: ImportType,
167 ) -> bool { 201 ) -> bool {
168 let mut changed = false; 202 let mut changed = false;
169 let existing = self.visible.entry(lookup.1.clone()).or_default();
170 203
171 macro_rules! check_changed { 204 macro_rules! check_changed {
172 ( 205 (
173 $changed:ident, 206 $changed:ident,
174 ( $existing:ident / $def:ident ) . $field:ident, 207 ( $this:ident / $def:ident ) . $field:ident,
175 $glob_imports:ident [ $lookup:ident ], 208 $glob_imports:ident [ $lookup:ident ],
176 $def_import_type:ident 209 $def_import_type:ident
177 ) => { 210 ) => {{
178 match ($existing.$field, $def.$field) { 211 let existing = $this.$field.entry($lookup.1.clone());
179 (None, Some(_)) => { 212 match (existing, $def.$field) {
213 (Entry::Vacant(entry), Some(_)) => {
180 match $def_import_type { 214 match $def_import_type {
181 ImportType::Glob => { 215 ImportType::Glob => {
182 $glob_imports.$field.insert($lookup.clone()); 216 $glob_imports.$field.insert($lookup.clone());
@@ -186,32 +220,46 @@ impl ItemScope {
186 } 220 }
187 } 221 }
188 222
189 $existing.$field = $def.$field; 223 if let Some(fld) = $def.$field {
224 entry.insert(fld);
225 }
190 $changed = true; 226 $changed = true;
191 } 227 }
192 (Some(_), Some(_)) 228 (Entry::Occupied(mut entry), Some(_))
193 if $glob_imports.$field.contains(&$lookup) 229 if $glob_imports.$field.contains(&$lookup)
194 && matches!($def_import_type, ImportType::Named) => 230 && matches!($def_import_type, ImportType::Named) =>
195 { 231 {
196 mark::hit!(import_shadowed); 232 mark::hit!(import_shadowed);
197 $glob_imports.$field.remove(&$lookup); 233 $glob_imports.$field.remove(&$lookup);
198 $existing.$field = $def.$field; 234 if let Some(fld) = $def.$field {
235 entry.insert(fld);
236 }
199 $changed = true; 237 $changed = true;
200 } 238 }
201 _ => {} 239 _ => {}
202 } 240 }
203 }; 241 }};
204 } 242 }
205 243
206 check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type); 244 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); 245 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); 246 check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type);
247
248 if def.is_none() {
249 if self.unresolved.insert(lookup.1) {
250 changed = true;
251 }
252 }
209 253
210 changed 254 changed
211 } 255 }
212 256
213 pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a { 257 pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Option<Name>, PerNs)> + 'a {
214 self.visible.iter().map(|(name, res)| (name.clone(), *res)) 258 self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
259 self.unnamed_trait_imports
260 .iter()
261 .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
262 )
215 } 263 }
216 264
217 pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { 265 pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {