aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/nameres')
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs109
-rw-r--r--crates/ra_hir_def/src/nameres/path_resolution.rs72
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs35
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs6
-rw-r--r--crates/ra_hir_def/src/nameres/tests/globs.rs97
-rw-r--r--crates/ra_hir_def/src/nameres/tests/incremental.rs4
6 files changed, 269 insertions, 54 deletions
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index b9f40d3dd..8a22b0585 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -24,6 +24,7 @@ use crate::{
24 }, 24 },
25 path::{ModPath, PathKind}, 25 path::{ModPath, PathKind},
26 per_ns::PerNs, 26 per_ns::PerNs,
27 visibility::Visibility,
27 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, 28 AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern,
28 LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 29 LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
29}; 30};
@@ -108,7 +109,7 @@ struct MacroDirective {
108struct DefCollector<'a, DB> { 109struct DefCollector<'a, DB> {
109 db: &'a DB, 110 db: &'a DB,
110 def_map: CrateDefMap, 111 def_map: CrateDefMap,
111 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, raw::Import)>>, 112 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
112 unresolved_imports: Vec<ImportDirective>, 113 unresolved_imports: Vec<ImportDirective>,
113 resolved_imports: Vec<ImportDirective>, 114 resolved_imports: Vec<ImportDirective>,
114 unexpanded_macros: Vec<MacroDirective>, 115 unexpanded_macros: Vec<MacroDirective>,
@@ -214,7 +215,11 @@ where
214 // In Rust, `#[macro_export]` macros are unconditionally visible at the 215 // In Rust, `#[macro_export]` macros are unconditionally visible at the
215 // crate root, even if the parent modules is **not** visible. 216 // crate root, even if the parent modules is **not** visible.
216 if export { 217 if export {
217 self.update(self.def_map.root, &[(name, PerNs::macros(macro_))]); 218 self.update(
219 self.def_map.root,
220 &[(name, PerNs::macros(macro_, Visibility::Public))],
221 Visibility::Public,
222 );
218 } 223 }
219 } 224 }
220 225
@@ -348,9 +353,12 @@ where
348 353
349 fn record_resolved_import(&mut self, directive: &ImportDirective) { 354 fn record_resolved_import(&mut self, directive: &ImportDirective) {
350 let module_id = directive.module_id; 355 let module_id = directive.module_id;
351 let import_id = directive.import_id;
352 let import = &directive.import; 356 let import = &directive.import;
353 let def = directive.status.namespaces(); 357 let def = directive.status.namespaces();
358 let vis = self
359 .def_map
360 .resolve_visibility(self.db, module_id, &directive.import.visibility)
361 .unwrap_or(Visibility::Public);
354 362
355 if import.is_glob { 363 if import.is_glob {
356 log::debug!("glob import: {:?}", import); 364 log::debug!("glob import: {:?}", import);
@@ -366,9 +374,16 @@ where
366 let scope = &item_map[m.local_id].scope; 374 let scope = &item_map[m.local_id].scope;
367 375
368 // Module scoped macros is included 376 // Module scoped macros is included
369 let items = scope.collect_resolutions(); 377 let items = scope
370 378 .resolutions()
371 self.update(module_id, &items); 379 // only keep visible names...
380 .map(|(n, res)| {
381 (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
382 })
383 .filter(|(_, res)| !res.is_none())
384 .collect::<Vec<_>>();
385
386 self.update(module_id, &items, vis);
372 } else { 387 } else {
373 // glob import from same crate => we do an initial 388 // glob import from same crate => we do an initial
374 // import, and then need to propagate any further 389 // import, and then need to propagate any further
@@ -376,13 +391,25 @@ where
376 let scope = &self.def_map[m.local_id].scope; 391 let scope = &self.def_map[m.local_id].scope;
377 392
378 // Module scoped macros is included 393 // Module scoped macros is included
379 let items = scope.collect_resolutions(); 394 let items = scope
380 395 .resolutions()
381 self.update(module_id, &items); 396 // only keep visible names...
397 .map(|(n, res)| {
398 (
399 n,
400 res.filter_visibility(|v| {
401 v.is_visible_from_def_map(&self.def_map, module_id)
402 }),
403 )
404 })
405 .filter(|(_, res)| !res.is_none())
406 .collect::<Vec<_>>();
407
408 self.update(module_id, &items, vis);
382 // record the glob import in case we add further items 409 // record the glob import in case we add further items
383 let glob = self.glob_imports.entry(m.local_id).or_default(); 410 let glob = self.glob_imports.entry(m.local_id).or_default();
384 if !glob.iter().any(|it| *it == (module_id, import_id)) { 411 if !glob.iter().any(|(mid, _)| *mid == module_id) {
385 glob.push((module_id, import_id)); 412 glob.push((module_id, vis));
386 } 413 }
387 } 414 }
388 } 415 }
@@ -396,11 +423,11 @@ where
396 .map(|(local_id, variant_data)| { 423 .map(|(local_id, variant_data)| {
397 let name = variant_data.name.clone(); 424 let name = variant_data.name.clone();
398 let variant = EnumVariantId { parent: e, local_id }; 425 let variant = EnumVariantId { parent: e, local_id };
399 let res = PerNs::both(variant.into(), variant.into()); 426 let res = PerNs::both(variant.into(), variant.into(), vis);
400 (name, res) 427 (name, res)
401 }) 428 })
402 .collect::<Vec<_>>(); 429 .collect::<Vec<_>>();
403 self.update(module_id, &resolutions); 430 self.update(module_id, &resolutions, vis);
404 } 431 }
405 Some(d) => { 432 Some(d) => {
406 log::debug!("glob import {:?} from non-module/enum {:?}", import, d); 433 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -422,21 +449,24 @@ where
422 } 449 }
423 } 450 }
424 451
425 self.update(module_id, &[(name, def)]); 452 self.update(module_id, &[(name, def)], vis);
426 } 453 }
427 None => tested_by!(bogus_paths), 454 None => tested_by!(bogus_paths),
428 } 455 }
429 } 456 }
430 } 457 }
431 458
432 fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)]) { 459 fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)], vis: Visibility) {
433 self.update_recursive(module_id, resolutions, 0) 460 self.update_recursive(module_id, resolutions, vis, 0)
434 } 461 }
435 462
436 fn update_recursive( 463 fn update_recursive(
437 &mut self, 464 &mut self,
438 module_id: LocalModuleId, 465 module_id: LocalModuleId,
439 resolutions: &[(Name, PerNs)], 466 resolutions: &[(Name, PerNs)],
467 // All resolutions are imported with this visibility; the visibilies in
468 // the `PerNs` values are ignored and overwritten
469 vis: Visibility,
440 depth: usize, 470 depth: usize,
441 ) { 471 ) {
442 if depth > 100 { 472 if depth > 100 {
@@ -446,7 +476,7 @@ where
446 let scope = &mut self.def_map.modules[module_id].scope; 476 let scope = &mut self.def_map.modules[module_id].scope;
447 let mut changed = false; 477 let mut changed = false;
448 for (name, res) in resolutions { 478 for (name, res) in resolutions {
449 changed |= scope.push_res(name.clone(), *res); 479 changed |= scope.push_res(name.clone(), res.with_visibility(vis));
450 } 480 }
451 481
452 if !changed { 482 if !changed {
@@ -459,9 +489,13 @@ where
459 .flat_map(|v| v.iter()) 489 .flat_map(|v| v.iter())
460 .cloned() 490 .cloned()
461 .collect::<Vec<_>>(); 491 .collect::<Vec<_>>();
462 for (glob_importing_module, _glob_import) in glob_imports { 492 for (glob_importing_module, glob_import_vis) in glob_imports {
463 // We pass the glob import so that the tracked import in those modules is that glob import 493 // we know all resolutions have the same visibility (`vis`), so we
464 self.update_recursive(glob_importing_module, resolutions, depth + 1); 494 // just need to check that once
495 if !vis.is_visible_from_def_map(&self.def_map, glob_importing_module) {
496 continue;
497 }
498 self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1);
465 } 499 }
466 } 500 }
467 501
@@ -633,9 +667,13 @@ where
633 let is_macro_use = attrs.by_key("macro_use").exists(); 667 let is_macro_use = attrs.by_key("macro_use").exists();
634 match module { 668 match module {
635 // inline module, just recurse 669 // inline module, just recurse
636 raw::ModuleData::Definition { name, items, ast_id } => { 670 raw::ModuleData::Definition { name, visibility, items, ast_id } => {
637 let module_id = 671 let module_id = self.push_child_module(
638 self.push_child_module(name.clone(), AstId::new(self.file_id, *ast_id), None); 672 name.clone(),
673 AstId::new(self.file_id, *ast_id),
674 None,
675 &visibility,
676 );
639 677
640 ModCollector { 678 ModCollector {
641 def_collector: &mut *self.def_collector, 679 def_collector: &mut *self.def_collector,
@@ -650,7 +688,7 @@ where
650 } 688 }
651 } 689 }
652 // out of line module, resolve, parse and recurse 690 // out of line module, resolve, parse and recurse
653 raw::ModuleData::Declaration { name, ast_id } => { 691 raw::ModuleData::Declaration { name, visibility, ast_id } => {
654 let ast_id = AstId::new(self.file_id, *ast_id); 692 let ast_id = AstId::new(self.file_id, *ast_id);
655 match self.mod_dir.resolve_declaration( 693 match self.mod_dir.resolve_declaration(
656 self.def_collector.db, 694 self.def_collector.db,
@@ -659,7 +697,12 @@ where
659 path_attr, 697 path_attr,
660 ) { 698 ) {
661 Ok((file_id, mod_dir)) => { 699 Ok((file_id, mod_dir)) => {
662 let module_id = self.push_child_module(name.clone(), ast_id, Some(file_id)); 700 let module_id = self.push_child_module(
701 name.clone(),
702 ast_id,
703 Some(file_id),
704 &visibility,
705 );
663 let raw_items = self.def_collector.db.raw_items(file_id.into()); 706 let raw_items = self.def_collector.db.raw_items(file_id.into());
664 ModCollector { 707 ModCollector {
665 def_collector: &mut *self.def_collector, 708 def_collector: &mut *self.def_collector,
@@ -690,7 +733,13 @@ where
690 name: Name, 733 name: Name,
691 declaration: AstId<ast::Module>, 734 declaration: AstId<ast::Module>,
692 definition: Option<FileId>, 735 definition: Option<FileId>,
736 visibility: &crate::visibility::RawVisibility,
693 ) -> LocalModuleId { 737 ) -> LocalModuleId {
738 let vis = self
739 .def_collector
740 .def_map
741 .resolve_visibility(self.def_collector.db, self.module_id, visibility)
742 .unwrap_or(Visibility::Public);
694 let modules = &mut self.def_collector.def_map.modules; 743 let modules = &mut self.def_collector.def_map.modules;
695 let res = modules.alloc(ModuleData::default()); 744 let res = modules.alloc(ModuleData::default());
696 modules[res].parent = Some(self.module_id); 745 modules[res].parent = Some(self.module_id);
@@ -702,7 +751,7 @@ where
702 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; 751 let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res };
703 let def: ModuleDefId = module.into(); 752 let def: ModuleDefId = module.into();
704 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 753 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
705 self.def_collector.update(self.module_id, &[(name, def.into())]); 754 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis);
706 res 755 res
707 } 756 }
708 757
@@ -716,6 +765,7 @@ where
716 765
717 let name = def.name.clone(); 766 let name = def.name.clone();
718 let container = ContainerId::ModuleId(module); 767 let container = ContainerId::ModuleId(module);
768 let vis = &def.visibility;
719 let def: ModuleDefId = match def.kind { 769 let def: ModuleDefId = match def.kind {
720 raw::DefKind::Function(ast_id) => FunctionLoc { 770 raw::DefKind::Function(ast_id) => FunctionLoc {
721 container: container.into(), 771 container: container.into(),
@@ -761,7 +811,12 @@ where
761 .into(), 811 .into(),
762 }; 812 };
763 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 813 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
764 self.def_collector.update(self.module_id, &[(name, def.into())]) 814 let vis = self
815 .def_collector
816 .def_map
817 .resolve_visibility(self.def_collector.db, self.module_id, vis)
818 .unwrap_or(Visibility::Public);
819 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis)
765 } 820 }
766 821
767 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { 822 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs
index 695014c7b..fd6422d60 100644
--- a/crates/ra_hir_def/src/nameres/path_resolution.rs
+++ b/crates/ra_hir_def/src/nameres/path_resolution.rs
@@ -21,6 +21,7 @@ use crate::{
21 nameres::{BuiltinShadowMode, CrateDefMap}, 21 nameres::{BuiltinShadowMode, CrateDefMap},
22 path::{ModPath, PathKind}, 22 path::{ModPath, PathKind},
23 per_ns::PerNs, 23 per_ns::PerNs,
24 visibility::{RawVisibility, Visibility},
24 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, 25 AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
25}; 26};
26 27
@@ -61,7 +62,35 @@ impl ResolvePathResult {
61 62
62impl CrateDefMap { 63impl CrateDefMap {
63 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs { 64 pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
64 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) 65 self.extern_prelude
66 .get(name)
67 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public))
68 }
69
70 pub(crate) fn resolve_visibility(
71 &self,
72 db: &impl DefDatabase,
73 original_module: LocalModuleId,
74 visibility: &RawVisibility,
75 ) -> Option<Visibility> {
76 match visibility {
77 RawVisibility::Module(path) => {
78 let (result, remaining) =
79 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
80 if remaining.is_some() {
81 return None;
82 }
83 let types = result.take_types()?;
84 match types {
85 ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)),
86 _ => {
87 // error: visibility needs to refer to module
88 None
89 }
90 }
91 }
92 RawVisibility::Public => Some(Visibility::Public),
93 }
65 } 94 }
66 95
67 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 96 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
@@ -88,17 +117,21 @@ impl CrateDefMap {
88 PathKind::DollarCrate(krate) => { 117 PathKind::DollarCrate(krate) => {
89 if krate == self.krate { 118 if krate == self.krate {
90 tested_by!(macro_dollar_crate_self); 119 tested_by!(macro_dollar_crate_self);
91 PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) 120 PerNs::types(
121 ModuleId { krate: self.krate, local_id: self.root }.into(),
122 Visibility::Public,
123 )
92 } else { 124 } else {
93 let def_map = db.crate_def_map(krate); 125 let def_map = db.crate_def_map(krate);
94 let module = ModuleId { krate, local_id: def_map.root }; 126 let module = ModuleId { krate, local_id: def_map.root };
95 tested_by!(macro_dollar_crate_other); 127 tested_by!(macro_dollar_crate_other);
96 PerNs::types(module.into()) 128 PerNs::types(module.into(), Visibility::Public)
97 } 129 }
98 } 130 }
99 PathKind::Crate => { 131 PathKind::Crate => PerNs::types(
100 PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) 132 ModuleId { krate: self.krate, local_id: self.root }.into(),
101 } 133 Visibility::Public,
134 ),
102 // plain import or absolute path in 2015: crate-relative with 135 // plain import or absolute path in 2015: crate-relative with
103 // fallback to extern prelude (with the simplification in 136 // fallback to extern prelude (with the simplification in
104 // rust-lang/rust#57745) 137 // rust-lang/rust#57745)
@@ -126,7 +159,10 @@ impl CrateDefMap {
126 let m = successors(Some(original_module), |m| self.modules[*m].parent) 159 let m = successors(Some(original_module), |m| self.modules[*m].parent)
127 .nth(lvl as usize); 160 .nth(lvl as usize);
128 if let Some(local_id) = m { 161 if let Some(local_id) = m {
129 PerNs::types(ModuleId { krate: self.krate, local_id }.into()) 162 PerNs::types(
163 ModuleId { krate: self.krate, local_id }.into(),
164 Visibility::Public,
165 )
130 } else { 166 } else {
131 log::debug!("super path in root module"); 167 log::debug!("super path in root module");
132 return ResolvePathResult::empty(ReachedFixedPoint::Yes); 168 return ResolvePathResult::empty(ReachedFixedPoint::Yes);
@@ -140,7 +176,7 @@ impl CrateDefMap {
140 }; 176 };
141 if let Some(def) = self.extern_prelude.get(&segment) { 177 if let Some(def) = self.extern_prelude.get(&segment) {
142 log::debug!("absolute path {:?} resolved to crate {:?}", path, def); 178 log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
143 PerNs::types(*def) 179 PerNs::types(*def, Visibility::Public)
144 } else { 180 } else {
145 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude 181 return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
146 } 182 }
@@ -148,7 +184,7 @@ impl CrateDefMap {
148 }; 184 };
149 185
150 for (i, segment) in segments { 186 for (i, segment) in segments {
151 let curr = match curr_per_ns.take_types() { 187 let (curr, vis) = match curr_per_ns.take_types_vis() {
152 Some(r) => r, 188 Some(r) => r,
153 None => { 189 None => {
154 // we still have path segments left, but the path so far 190 // we still have path segments left, but the path so far
@@ -189,11 +225,11 @@ impl CrateDefMap {
189 match enum_data.variant(&segment) { 225 match enum_data.variant(&segment) {
190 Some(local_id) => { 226 Some(local_id) => {
191 let variant = EnumVariantId { parent: e, local_id }; 227 let variant = EnumVariantId { parent: e, local_id };
192 PerNs::both(variant.into(), variant.into()) 228 PerNs::both(variant.into(), variant.into(), Visibility::Public)
193 } 229 }
194 None => { 230 None => {
195 return ResolvePathResult::with( 231 return ResolvePathResult::with(
196 PerNs::types(e.into()), 232 PerNs::types(e.into(), vis),
197 ReachedFixedPoint::Yes, 233 ReachedFixedPoint::Yes,
198 Some(i), 234 Some(i),
199 Some(self.krate), 235 Some(self.krate),
@@ -211,7 +247,7 @@ impl CrateDefMap {
211 ); 247 );
212 248
213 return ResolvePathResult::with( 249 return ResolvePathResult::with(
214 PerNs::types(s), 250 PerNs::types(s, vis),
215 ReachedFixedPoint::Yes, 251 ReachedFixedPoint::Yes,
216 Some(i), 252 Some(i),
217 Some(self.krate), 253 Some(self.krate),
@@ -235,11 +271,15 @@ impl CrateDefMap {
235 // - current module / scope 271 // - current module / scope
236 // - extern prelude 272 // - extern prelude
237 // - std prelude 273 // - std prelude
238 let from_legacy_macro = 274 let from_legacy_macro = self[module]
239 self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); 275 .scope
276 .get_legacy_macro(name)
277 .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public));
240 let from_scope = self[module].scope.get(name, shadow); 278 let from_scope = self[module].scope.get(name, shadow);
241 let from_extern_prelude = 279 let from_extern_prelude = self
242 self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); 280 .extern_prelude
281 .get(name)
282 .map_or(PerNs::none(), |&it| PerNs::types(it, Visibility::Public));
243 let from_prelude = self.resolve_in_prelude(db, name, shadow); 283 let from_prelude = self.resolve_in_prelude(db, name, shadow);
244 284
245 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) 285 from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 73dc08745..fac1169ef 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -16,12 +16,15 @@ use hir_expand::{
16use ra_arena::{impl_arena_id, Arena, RawId}; 16use ra_arena::{impl_arena_id, Arena, RawId};
17use ra_prof::profile; 17use ra_prof::profile;
18use ra_syntax::{ 18use ra_syntax::{
19 ast::{self, AttrsOwner, NameOwner}, 19 ast::{self, AttrsOwner, NameOwner, VisibilityOwner},
20 AstNode, 20 AstNode,
21}; 21};
22use test_utils::tested_by; 22use test_utils::tested_by;
23 23
24use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile}; 24use crate::{
25 attr::Attrs, db::DefDatabase, path::ModPath, visibility::RawVisibility, FileAstId, HirFileId,
26 InFile,
27};
25 28
26/// `RawItems` is a set of top-level items in a file (except for impls). 29/// `RawItems` is a set of top-level items in a file (except for impls).
27/// 30///
@@ -122,8 +125,17 @@ impl_arena_id!(Module);
122 125
123#[derive(Debug, PartialEq, Eq)] 126#[derive(Debug, PartialEq, Eq)]
124pub(super) enum ModuleData { 127pub(super) enum ModuleData {
125 Declaration { name: Name, ast_id: FileAstId<ast::Module> }, 128 Declaration {
126 Definition { name: Name, ast_id: FileAstId<ast::Module>, items: Vec<RawItem> }, 129 name: Name,
130 visibility: RawVisibility,
131 ast_id: FileAstId<ast::Module>,
132 },
133 Definition {
134 name: Name,
135 visibility: RawVisibility,
136 ast_id: FileAstId<ast::Module>,
137 items: Vec<RawItem>,
138 },
127} 139}
128 140
129#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 141#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -138,6 +150,7 @@ pub struct ImportData {
138 pub(super) is_prelude: bool, 150 pub(super) is_prelude: bool,
139 pub(super) is_extern_crate: bool, 151 pub(super) is_extern_crate: bool,
140 pub(super) is_macro_use: bool, 152 pub(super) is_macro_use: bool,
153 pub(super) visibility: RawVisibility,
141} 154}
142 155
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -148,6 +161,7 @@ impl_arena_id!(Def);
148pub(super) struct DefData { 161pub(super) struct DefData {
149 pub(super) name: Name, 162 pub(super) name: Name,
150 pub(super) kind: DefKind, 163 pub(super) kind: DefKind,
164 pub(super) visibility: RawVisibility,
151} 165}
152 166
153#[derive(Debug, PartialEq, Eq, Clone, Copy)] 167#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -218,6 +232,7 @@ impl RawItemsCollector {
218 232
219 fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { 233 fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) {
220 let attrs = self.parse_attrs(&item); 234 let attrs = self.parse_attrs(&item);
235 let visibility = RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene);
221 let (kind, name) = match item { 236 let (kind, name) = match item {
222 ast::ModuleItem::Module(module) => { 237 ast::ModuleItem::Module(module) => {
223 self.add_module(current_module, module); 238 self.add_module(current_module, module);
@@ -266,7 +281,7 @@ impl RawItemsCollector {
266 }; 281 };
267 if let Some(name) = name { 282 if let Some(name) = name {
268 let name = name.as_name(); 283 let name = name.as_name();
269 let def = self.raw_items.defs.alloc(DefData { name, kind }); 284 let def = self.raw_items.defs.alloc(DefData { name, kind, visibility });
270 self.push_item(current_module, attrs, RawItemKind::Def(def)); 285 self.push_item(current_module, attrs, RawItemKind::Def(def));
271 } 286 }
272 } 287 }
@@ -277,10 +292,12 @@ impl RawItemsCollector {
277 None => return, 292 None => return,
278 }; 293 };
279 let attrs = self.parse_attrs(&module); 294 let attrs = self.parse_attrs(&module);
295 let visibility = RawVisibility::from_ast_with_hygiene(module.visibility(), &self.hygiene);
280 296
281 let ast_id = self.source_ast_id_map.ast_id(&module); 297 let ast_id = self.source_ast_id_map.ast_id(&module);
282 if module.has_semi() { 298 if module.has_semi() {
283 let item = self.raw_items.modules.alloc(ModuleData::Declaration { name, ast_id }); 299 let item =
300 self.raw_items.modules.alloc(ModuleData::Declaration { name, visibility, ast_id });
284 self.push_item(current_module, attrs, RawItemKind::Module(item)); 301 self.push_item(current_module, attrs, RawItemKind::Module(item));
285 return; 302 return;
286 } 303 }
@@ -288,6 +305,7 @@ impl RawItemsCollector {
288 if let Some(item_list) = module.item_list() { 305 if let Some(item_list) = module.item_list() {
289 let item = self.raw_items.modules.alloc(ModuleData::Definition { 306 let item = self.raw_items.modules.alloc(ModuleData::Definition {
290 name, 307 name,
308 visibility,
291 ast_id, 309 ast_id,
292 items: Vec::new(), 310 items: Vec::new(),
293 }); 311 });
@@ -302,6 +320,7 @@ impl RawItemsCollector {
302 // FIXME: cfg_attr 320 // FIXME: cfg_attr
303 let is_prelude = use_item.has_atom_attr("prelude_import"); 321 let is_prelude = use_item.has_atom_attr("prelude_import");
304 let attrs = self.parse_attrs(&use_item); 322 let attrs = self.parse_attrs(&use_item);
323 let visibility = RawVisibility::from_ast_with_hygiene(use_item.visibility(), &self.hygiene);
305 324
306 let mut buf = Vec::new(); 325 let mut buf = Vec::new();
307 ModPath::expand_use_item( 326 ModPath::expand_use_item(
@@ -315,6 +334,7 @@ impl RawItemsCollector {
315 is_prelude, 334 is_prelude,
316 is_extern_crate: false, 335 is_extern_crate: false,
317 is_macro_use: false, 336 is_macro_use: false,
337 visibility: visibility.clone(),
318 }; 338 };
319 buf.push(import_data); 339 buf.push(import_data);
320 }, 340 },
@@ -331,6 +351,8 @@ impl RawItemsCollector {
331 ) { 351 ) {
332 if let Some(name_ref) = extern_crate.name_ref() { 352 if let Some(name_ref) = extern_crate.name_ref() {
333 let path = ModPath::from_name_ref(&name_ref); 353 let path = ModPath::from_name_ref(&name_ref);
354 let visibility =
355 RawVisibility::from_ast_with_hygiene(extern_crate.visibility(), &self.hygiene);
334 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); 356 let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name());
335 let attrs = self.parse_attrs(&extern_crate); 357 let attrs = self.parse_attrs(&extern_crate);
336 // FIXME: cfg_attr 358 // FIXME: cfg_attr
@@ -342,6 +364,7 @@ impl RawItemsCollector {
342 is_prelude: false, 364 is_prelude: false,
343 is_extern_crate: true, 365 is_extern_crate: true,
344 is_macro_use, 366 is_macro_use,
367 visibility,
345 }; 368 };
346 self.push_import(current_module, attrs, import_data); 369 self.push_import(current_module, attrs, import_data);
347 } 370 }
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs
index ff474b53b..78bcdc850 100644
--- a/crates/ra_hir_def/src/nameres/tests.rs
+++ b/crates/ra_hir_def/src/nameres/tests.rs
@@ -12,8 +12,8 @@ use test_utils::covers;
12 12
13use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId}; 13use crate::{db::DefDatabase, nameres::*, test_db::TestDB, LocalModuleId};
14 14
15fn def_map(fixtute: &str) -> String { 15fn def_map(fixture: &str) -> String {
16 let dm = compute_crate_def_map(fixtute); 16 let dm = compute_crate_def_map(fixture);
17 render_crate_def_map(&dm) 17 render_crate_def_map(&dm)
18} 18}
19 19
@@ -32,7 +32,7 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
32 *buf += path; 32 *buf += path;
33 *buf += "\n"; 33 *buf += "\n";
34 34
35 let mut entries = map.modules[module].scope.collect_resolutions(); 35 let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect();
36 entries.sort_by_key(|(name, _)| name.clone()); 36 entries.sort_by_key(|(name, _)| name.clone());
37 37
38 for (name, def) in entries { 38 for (name, def) in entries {
diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs
index 5e24cb94d..71fa0abe8 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -74,6 +74,83 @@ fn glob_2() {
74} 74}
75 75
76#[test] 76#[test]
77fn glob_privacy_1() {
78 let map = def_map(
79 "
80 //- /lib.rs
81 mod foo;
82 use foo::*;
83
84 //- /foo/mod.rs
85 pub mod bar;
86 pub use self::bar::*;
87 struct PrivateStructFoo;
88
89 //- /foo/bar.rs
90 pub struct Baz;
91 struct PrivateStructBar;
92 pub use super::*;
93 ",
94 );
95 assert_snapshot!(map, @r###"
96 crate
97 Baz: t v
98 bar: t
99 foo: t
100
101 crate::foo
102 Baz: t v
103 PrivateStructFoo: t v
104 bar: t
105
106 crate::foo::bar
107 Baz: t v
108 PrivateStructBar: t v
109 PrivateStructFoo: t v
110 bar: t
111 "###
112 );
113}
114
115#[test]
116fn glob_privacy_2() {
117 let map = def_map(
118 "
119 //- /lib.rs
120 mod foo;
121 use foo::*;
122 use foo::bar::*;
123
124 //- /foo/mod.rs
125 mod bar;
126 fn Foo() {};
127 pub struct Foo {};
128
129 //- /foo/bar.rs
130 pub(super) struct PrivateBaz;
131 struct PrivateBar;
132 pub(crate) struct PubCrateStruct;
133 ",
134 );
135 assert_snapshot!(map, @r###"
136 crate
137 Foo: t
138 PubCrateStruct: t v
139 foo: t
140
141 crate::foo
142 Foo: t v
143 bar: t
144
145 crate::foo::bar
146 PrivateBar: t v
147 PrivateBaz: t v
148 PubCrateStruct: t v
149 "###
150 );
151}
152
153#[test]
77fn glob_across_crates() { 154fn glob_across_crates() {
78 covers!(glob_across_crates); 155 covers!(glob_across_crates);
79 let map = def_map( 156 let map = def_map(
@@ -93,6 +170,26 @@ fn glob_across_crates() {
93} 170}
94 171
95#[test] 172#[test]
173fn glob_privacy_across_crates() {
174 covers!(glob_across_crates);
175 let map = def_map(
176 "
177 //- /main.rs crate:main deps:test_crate
178 use test_crate::*;
179
180 //- /lib.rs crate:test_crate
181 pub struct Baz;
182 struct Foo;
183 ",
184 );
185 assert_snapshot!(map, @r###"
186 ⋮crate
187 ⋮Baz: t v
188 "###
189 );
190}
191
192#[test]
96fn glob_enum() { 193fn glob_enum() {
97 covers!(glob_enum); 194 covers!(glob_enum);
98 let map = def_map( 195 let map = def_map(
diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs
index ef2e9435c..faeb7aa4d 100644
--- a/crates/ra_hir_def/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs
@@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
116 let events = db.log_executed(|| { 116 let events = db.log_executed(|| {
117 let crate_def_map = db.crate_def_map(krate); 117 let crate_def_map = db.crate_def_map(krate);
118 let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); 118 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
119 assert_eq!(module_data.scope.collect_resolutions().len(), 1); 119 assert_eq!(module_data.scope.resolutions().collect::<Vec<_>>().len(), 1);
120 }); 120 });
121 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) 121 assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
122 } 122 }
@@ -126,7 +126,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
126 let events = db.log_executed(|| { 126 let events = db.log_executed(|| {
127 let crate_def_map = db.crate_def_map(krate); 127 let crate_def_map = db.crate_def_map(krate);
128 let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); 128 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
129 assert_eq!(module_data.scope.collect_resolutions().len(), 1); 129 assert_eq!(module_data.scope.resolutions().collect::<Vec<_>>().len(), 1);
130 }); 130 });
131 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) 131 assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
132 } 132 }