diff options
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r-- | crates/ra_hir_def/src/nameres/collector.rs | 49 | ||||
-rw-r--r-- | crates/ra_hir_def/src/nameres/tests/globs.rs | 90 |
2 files changed, 129 insertions, 10 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 2ced4f66b..a35ac1024 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -20,6 +20,7 @@ use test_utils::mark; | |||
20 | use crate::{ | 20 | use crate::{ |
21 | attr::Attrs, | 21 | attr::Attrs, |
22 | db::DefDatabase, | 22 | db::DefDatabase, |
23 | item_scope::{ImportType, PerNsGlobImports}, | ||
23 | item_tree::{ | 24 | item_tree::{ |
24 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind, | 25 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind, |
25 | }, | 26 | }, |
@@ -80,6 +81,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr | |||
80 | mod_dirs: FxHashMap::default(), | 81 | mod_dirs: FxHashMap::default(), |
81 | cfg_options, | 82 | cfg_options, |
82 | proc_macros, | 83 | proc_macros, |
84 | from_glob_import: Default::default(), | ||
83 | }; | 85 | }; |
84 | collector.collect(); | 86 | collector.collect(); |
85 | collector.finish() | 87 | collector.finish() |
@@ -186,6 +188,7 @@ struct DefCollector<'a> { | |||
186 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, | 188 | mod_dirs: FxHashMap<LocalModuleId, ModDir>, |
187 | cfg_options: &'a CfgOptions, | 189 | cfg_options: &'a CfgOptions, |
188 | proc_macros: Vec<(Name, ProcMacroExpander)>, | 190 | proc_macros: Vec<(Name, ProcMacroExpander)>, |
191 | from_glob_import: PerNsGlobImports, | ||
189 | } | 192 | } |
190 | 193 | ||
191 | impl DefCollector<'_> { | 194 | impl DefCollector<'_> { |
@@ -305,6 +308,7 @@ impl DefCollector<'_> { | |||
305 | self.def_map.root, | 308 | self.def_map.root, |
306 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 309 | &[(name, PerNs::macros(macro_, Visibility::Public))], |
307 | Visibility::Public, | 310 | Visibility::Public, |
311 | ImportType::Named, | ||
308 | ); | 312 | ); |
309 | } | 313 | } |
310 | } | 314 | } |
@@ -330,6 +334,7 @@ impl DefCollector<'_> { | |||
330 | self.def_map.root, | 334 | self.def_map.root, |
331 | &[(name, PerNs::macros(macro_, Visibility::Public))], | 335 | &[(name, PerNs::macros(macro_, Visibility::Public))], |
332 | Visibility::Public, | 336 | Visibility::Public, |
337 | ImportType::Named, | ||
333 | ); | 338 | ); |
334 | } | 339 | } |
335 | 340 | ||
@@ -383,7 +388,6 @@ impl DefCollector<'_> { | |||
383 | let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); | 388 | let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); |
384 | for mut directive in imports { | 389 | for mut directive in imports { |
385 | directive.status = self.resolve_import(directive.module_id, &directive.import); | 390 | directive.status = self.resolve_import(directive.module_id, &directive.import); |
386 | |||
387 | match directive.status { | 391 | match directive.status { |
388 | PartialResolvedImport::Indeterminate(_) => { | 392 | PartialResolvedImport::Indeterminate(_) => { |
389 | self.record_resolved_import(&directive); | 393 | self.record_resolved_import(&directive); |
@@ -477,7 +481,7 @@ impl DefCollector<'_> { | |||
477 | .filter(|(_, res)| !res.is_none()) | 481 | .filter(|(_, res)| !res.is_none()) |
478 | .collect::<Vec<_>>(); | 482 | .collect::<Vec<_>>(); |
479 | 483 | ||
480 | self.update(module_id, &items, vis); | 484 | self.update(module_id, &items, vis, ImportType::Glob); |
481 | } else { | 485 | } else { |
482 | // glob import from same crate => we do an initial | 486 | // glob import from same crate => we do an initial |
483 | // import, and then need to propagate any further | 487 | // import, and then need to propagate any further |
@@ -499,7 +503,7 @@ impl DefCollector<'_> { | |||
499 | .filter(|(_, res)| !res.is_none()) | 503 | .filter(|(_, res)| !res.is_none()) |
500 | .collect::<Vec<_>>(); | 504 | .collect::<Vec<_>>(); |
501 | 505 | ||
502 | self.update(module_id, &items, vis); | 506 | self.update(module_id, &items, vis, ImportType::Glob); |
503 | // record the glob import in case we add further items | 507 | // record the glob import in case we add further items |
504 | let glob = self.glob_imports.entry(m.local_id).or_default(); | 508 | let glob = self.glob_imports.entry(m.local_id).or_default(); |
505 | if !glob.iter().any(|(mid, _)| *mid == module_id) { | 509 | if !glob.iter().any(|(mid, _)| *mid == module_id) { |
@@ -529,7 +533,7 @@ impl DefCollector<'_> { | |||
529 | (name, res) | 533 | (name, res) |
530 | }) | 534 | }) |
531 | .collect::<Vec<_>>(); | 535 | .collect::<Vec<_>>(); |
532 | self.update(module_id, &resolutions, vis); | 536 | self.update(module_id, &resolutions, vis, ImportType::Glob); |
533 | } | 537 | } |
534 | Some(d) => { | 538 | Some(d) => { |
535 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); | 539 | log::debug!("glob import {:?} from non-module/enum {:?}", import, d); |
@@ -555,15 +559,21 @@ impl DefCollector<'_> { | |||
555 | } | 559 | } |
556 | } | 560 | } |
557 | 561 | ||
558 | self.update(module_id, &[(name, def)], vis); | 562 | self.update(module_id, &[(name, def)], vis, ImportType::Named); |
559 | } | 563 | } |
560 | None => mark::hit!(bogus_paths), | 564 | None => mark::hit!(bogus_paths), |
561 | } | 565 | } |
562 | } | 566 | } |
563 | } | 567 | } |
564 | 568 | ||
565 | fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)], vis: Visibility) { | 569 | fn update( |
566 | self.update_recursive(module_id, resolutions, vis, 0) | 570 | &mut self, |
571 | module_id: LocalModuleId, | ||
572 | resolutions: &[(Name, PerNs)], | ||
573 | vis: Visibility, | ||
574 | import_type: ImportType, | ||
575 | ) { | ||
576 | self.update_recursive(module_id, resolutions, vis, import_type, 0) | ||
567 | } | 577 | } |
568 | 578 | ||
569 | fn update_recursive( | 579 | fn update_recursive( |
@@ -573,6 +583,7 @@ impl DefCollector<'_> { | |||
573 | // All resolutions are imported with this visibility; the visibilies in | 583 | // All resolutions are imported with this visibility; the visibilies in |
574 | // the `PerNs` values are ignored and overwritten | 584 | // the `PerNs` values are ignored and overwritten |
575 | vis: Visibility, | 585 | vis: Visibility, |
586 | import_type: ImportType, | ||
576 | depth: usize, | 587 | depth: usize, |
577 | ) { | 588 | ) { |
578 | if depth > 100 { | 589 | if depth > 100 { |
@@ -582,7 +593,12 @@ impl DefCollector<'_> { | |||
582 | let scope = &mut self.def_map.modules[module_id].scope; | 593 | let scope = &mut self.def_map.modules[module_id].scope; |
583 | let mut changed = false; | 594 | let mut changed = false; |
584 | for (name, res) in resolutions { | 595 | for (name, res) in resolutions { |
585 | changed |= scope.push_res(name.clone(), res.with_visibility(vis)); | 596 | changed |= scope.push_res_with_import( |
597 | &mut self.from_glob_import, | ||
598 | (module_id, name.clone()), | ||
599 | res.with_visibility(vis), | ||
600 | import_type, | ||
601 | ); | ||
586 | } | 602 | } |
587 | 603 | ||
588 | if !changed { | 604 | if !changed { |
@@ -601,7 +617,13 @@ impl DefCollector<'_> { | |||
601 | if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { | 617 | if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) { |
602 | continue; | 618 | continue; |
603 | } | 619 | } |
604 | self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1); | 620 | self.update_recursive( |
621 | glob_importing_module, | ||
622 | resolutions, | ||
623 | glob_import_vis, | ||
624 | ImportType::Glob, | ||
625 | depth + 1, | ||
626 | ); | ||
605 | } | 627 | } |
606 | } | 628 | } |
607 | 629 | ||
@@ -923,6 +945,7 @@ impl ModCollector<'_, '_> { | |||
923 | self.module_id, | 945 | self.module_id, |
924 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], | 946 | &[(name.clone(), PerNs::from_def(id, vis, has_constructor))], |
925 | vis, | 947 | vis, |
948 | ImportType::Named, | ||
926 | ) | 949 | ) |
927 | } | 950 | } |
928 | } | 951 | } |
@@ -1025,7 +1048,12 @@ impl ModCollector<'_, '_> { | |||
1025 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; | 1048 | let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; |
1026 | let def: ModuleDefId = module.into(); | 1049 | let def: ModuleDefId = module.into(); |
1027 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); | 1050 | self.def_collector.def_map.modules[self.module_id].scope.define_def(def); |
1028 | self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis, false))], vis); | 1051 | self.def_collector.update( |
1052 | self.module_id, | ||
1053 | &[(name, PerNs::from_def(def, vis, false))], | ||
1054 | vis, | ||
1055 | ImportType::Named, | ||
1056 | ); | ||
1029 | res | 1057 | res |
1030 | } | 1058 | } |
1031 | 1059 | ||
@@ -1154,6 +1182,7 @@ mod tests { | |||
1154 | mod_dirs: FxHashMap::default(), | 1182 | mod_dirs: FxHashMap::default(), |
1155 | cfg_options: &CfgOptions::default(), | 1183 | cfg_options: &CfgOptions::default(), |
1156 | proc_macros: Default::default(), | 1184 | proc_macros: Default::default(), |
1185 | from_glob_import: Default::default(), | ||
1157 | }; | 1186 | }; |
1158 | collector.collect(); | 1187 | collector.collect(); |
1159 | collector.def_map | 1188 | collector.def_map |
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs index 2f440975a..7f3d7509c 100644 --- a/crates/ra_hir_def/src/nameres/tests/globs.rs +++ b/crates/ra_hir_def/src/nameres/tests/globs.rs | |||
@@ -276,3 +276,93 @@ fn glob_shadowed_def() { | |||
276 | "### | 276 | "### |
277 | ); | 277 | ); |
278 | } | 278 | } |
279 | |||
280 | #[test] | ||
281 | fn glob_shadowed_def_reversed() { | ||
282 | let map = def_map( | ||
283 | r###" | ||
284 | //- /lib.rs | ||
285 | mod foo; | ||
286 | mod bar; | ||
287 | |||
288 | use bar::baz; | ||
289 | use foo::*; | ||
290 | |||
291 | use baz::Bar; | ||
292 | |||
293 | //- /foo.rs | ||
294 | pub mod baz { | ||
295 | pub struct Foo; | ||
296 | } | ||
297 | |||
298 | //- /bar.rs | ||
299 | pub mod baz { | ||
300 | pub struct Bar; | ||
301 | } | ||
302 | "###, | ||
303 | ); | ||
304 | assert_snapshot!(map, @r###" | ||
305 | ⋮crate | ||
306 | ⋮Bar: t v | ||
307 | ⋮bar: t | ||
308 | ⋮baz: t | ||
309 | ⋮foo: t | ||
310 | ⋮ | ||
311 | ⋮crate::bar | ||
312 | ⋮baz: t | ||
313 | ⋮ | ||
314 | ⋮crate::bar::baz | ||
315 | ⋮Bar: t v | ||
316 | ⋮ | ||
317 | ⋮crate::foo | ||
318 | ⋮baz: t | ||
319 | ⋮ | ||
320 | ⋮crate::foo::baz | ||
321 | ⋮Foo: t v | ||
322 | "### | ||
323 | ); | ||
324 | } | ||
325 | |||
326 | #[test] | ||
327 | fn glob_shadowed_def_dependencies() { | ||
328 | let map = def_map( | ||
329 | r###" | ||
330 | //- /lib.rs | ||
331 | mod a { pub mod foo { pub struct X; } } | ||
332 | mod b { pub use super::a::foo; } | ||
333 | mod c { pub mod foo { pub struct Y; } } | ||
334 | mod d { | ||
335 | use super::c::foo; | ||
336 | use super::b::*; | ||
337 | use foo::Y; | ||
338 | } | ||
339 | "###, | ||
340 | ); | ||
341 | assert_snapshot!(map, @r###" | ||
342 | ⋮crate | ||
343 | ⋮a: t | ||
344 | ⋮b: t | ||
345 | ⋮c: t | ||
346 | ⋮d: t | ||
347 | ⋮ | ||
348 | ⋮crate::d | ||
349 | ⋮Y: t v | ||
350 | ⋮foo: t | ||
351 | ⋮ | ||
352 | ⋮crate::c | ||
353 | ⋮foo: t | ||
354 | ⋮ | ||
355 | ⋮crate::c::foo | ||
356 | ⋮Y: t v | ||
357 | ⋮ | ||
358 | ⋮crate::b | ||
359 | ⋮foo: t | ||
360 | ⋮ | ||
361 | ⋮crate::a | ||
362 | ⋮foo: t | ||
363 | ⋮ | ||
364 | ⋮crate::a::foo | ||
365 | ⋮X: t v | ||
366 | "### | ||
367 | ); | ||
368 | } | ||