aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-12-25 17:05:16 +0000
committerFlorian Diebold <[email protected]>2019-12-26 15:23:40 +0000
commit21359c3ab5fc497d11b2c0f0435c7635336a726e (patch)
treead438e045f50be776a9245ceb367598e7b60f8f9
parent8ac25f119eb45d425370d9f7f093bc206e6c4a9f (diff)
Take visibility into account for glob imports
-rw-r--r--crates/ra_hir_def/src/item_scope.rs12
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs80
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs6
-rw-r--r--crates/ra_hir_def/src/nameres/tests/globs.rs78
-rw-r--r--crates/ra_hir_def/src/nameres/tests/incremental.rs4
-rw-r--r--crates/ra_hir_def/src/per_ns.rs8
-rw-r--r--crates/ra_hir_def/src/visibility.rs20
7 files changed, 165 insertions, 43 deletions
diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs
index d77f37f67..db5f469c7 100644
--- a/crates/ra_hir_def/src/item_scope.rs
+++ b/crates/ra_hir_def/src/item_scope.rs
@@ -149,16 +149,8 @@ impl ItemScope {
149 changed 149 changed
150 } 150 }
151 151
152 #[cfg(test)] 152 pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Name, PerNs)> + 'a {
153 pub(crate) fn collect_resolutions(&self) -> Vec<(Name, PerNs)> { 153 self.visible.iter().map(|(name, res)| (name.clone(), res.clone()))
154 self.visible.iter().map(|(name, res)| (name.clone(), res.clone())).collect()
155 }
156
157 pub(crate) fn collect_resolutions_with_vis(
158 &self,
159 vis: ResolvedVisibility,
160 ) -> Vec<(Name, PerNs)> {
161 self.visible.iter().map(|(name, res)| (name.clone(), res.with_visibility(vis))).collect()
162 } 154 }
163 155
164 pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> { 156 pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 5b8478037..51df44d2f 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -109,7 +109,7 @@ struct MacroDirective {
109struct DefCollector<'a, DB> { 109struct DefCollector<'a, DB> {
110 db: &'a DB, 110 db: &'a DB,
111 def_map: CrateDefMap, 111 def_map: CrateDefMap,
112 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, raw::Import)>>, 112 glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, ResolvedVisibility)>>,
113 unresolved_imports: Vec<ImportDirective>, 113 unresolved_imports: Vec<ImportDirective>,
114 resolved_imports: Vec<ImportDirective>, 114 resolved_imports: Vec<ImportDirective>,
115 unexpanded_macros: Vec<MacroDirective>, 115 unexpanded_macros: Vec<MacroDirective>,
@@ -218,6 +218,7 @@ where
218 self.update( 218 self.update(
219 self.def_map.root, 219 self.def_map.root,
220 &[(name, PerNs::macros(macro_, ResolvedVisibility::Public))], 220 &[(name, PerNs::macros(macro_, ResolvedVisibility::Public))],
221 ResolvedVisibility::Public,
221 ); 222 );
222 } 223 }
223 } 224 }
@@ -352,7 +353,6 @@ where
352 353
353 fn record_resolved_import(&mut self, directive: &ImportDirective) { 354 fn record_resolved_import(&mut self, directive: &ImportDirective) {
354 let module_id = directive.module_id; 355 let module_id = directive.module_id;
355 let import_id = directive.import_id;
356 let import = &directive.import; 356 let import = &directive.import;
357 let def = directive.status.namespaces(); 357 let def = directive.status.namespaces();
358 let vis = self 358 let vis = self
@@ -373,28 +373,48 @@ where
373 let item_map = self.db.crate_def_map(m.krate); 373 let item_map = self.db.crate_def_map(m.krate);
374 let scope = &item_map[m.local_id].scope; 374 let scope = &item_map[m.local_id].scope;
375 375
376 // TODO: only use names we can see
377
378 // Module scoped macros is included 376 // Module scoped macros is included
379 let items = scope.collect_resolutions_with_vis(vis); 377 let items = scope
380 378 .resolutions()
381 self.update(module_id, &items); 379 // only keep visible names...
380 .map(|(n, res)| {
381 (
382 n,
383 res.filter_visibility(|v| {
384 v.visible_from_def_map(&self.def_map, module_id)
385 }),
386 )
387 })
388 .filter(|(_, res)| !res.is_none())
389 .collect::<Vec<_>>();
390
391 self.update(module_id, &items, vis);
382 } else { 392 } else {
383 // glob import from same crate => we do an initial 393 // glob import from same crate => we do an initial
384 // import, and then need to propagate any further 394 // import, and then need to propagate any further
385 // additions 395 // additions
386 let scope = &self.def_map[m.local_id].scope; 396 let scope = &self.def_map[m.local_id].scope;
387 397
388 // TODO: only use names we can see
389
390 // Module scoped macros is included 398 // Module scoped macros is included
391 let items = scope.collect_resolutions_with_vis(vis); 399 let items = scope
392 400 .resolutions()
393 self.update(module_id, &items); 401 // only keep visible names...
402 .map(|(n, res)| {
403 (
404 n,
405 res.filter_visibility(|v| {
406 v.visible_from_def_map(&self.def_map, module_id)
407 }),
408 )
409 })
410 .filter(|(_, res)| !res.is_none())
411 .collect::<Vec<_>>();
412
413 self.update(module_id, &items, vis);
394 // record the glob import in case we add further items 414 // record the glob import in case we add further items
395 let glob = self.glob_imports.entry(m.local_id).or_default(); 415 let glob = self.glob_imports.entry(m.local_id).or_default();
396 if !glob.iter().any(|it| *it == (module_id, import_id)) { 416 if !glob.iter().any(|(mid, _)| *mid == module_id) {
397 glob.push((module_id, import_id)); 417 glob.push((module_id, vis));
398 } 418 }
399 } 419 }
400 } 420 }
@@ -412,7 +432,7 @@ where
412 (name, res) 432 (name, res)
413 }) 433 })
414 .collect::<Vec<_>>(); 434 .collect::<Vec<_>>();
415 self.update(module_id, &resolutions); 435 self.update(module_id, &resolutions, vis);
416 } 436 }
417 Some(d) => { 437 Some(d) => {
418 log::debug!("glob import {:?} from non-module/enum {:?}", import, d); 438 log::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -434,21 +454,29 @@ where
434 } 454 }
435 } 455 }
436 456
437 self.update(module_id, &[(name, def.with_visibility(vis))]); 457 self.update(module_id, &[(name, def)], vis);
438 } 458 }
439 None => tested_by!(bogus_paths), 459 None => tested_by!(bogus_paths),
440 } 460 }
441 } 461 }
442 } 462 }
443 463
444 fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)]) { 464 fn update(
445 self.update_recursive(module_id, resolutions, 0) 465 &mut self,
466 module_id: LocalModuleId,
467 resolutions: &[(Name, PerNs)],
468 vis: ResolvedVisibility,
469 ) {
470 self.update_recursive(module_id, resolutions, vis, 0)
446 } 471 }
447 472
448 fn update_recursive( 473 fn update_recursive(
449 &mut self, 474 &mut self,
450 module_id: LocalModuleId, 475 module_id: LocalModuleId,
451 resolutions: &[(Name, PerNs)], 476 resolutions: &[(Name, PerNs)],
477 // All resolutions are imported with this visibility; the visibilies in
478 // the `PerNs` values are ignored and overwritten
479 vis: ResolvedVisibility,
452 depth: usize, 480 depth: usize,
453 ) { 481 ) {
454 if depth > 100 { 482 if depth > 100 {
@@ -458,7 +486,7 @@ where
458 let scope = &mut self.def_map.modules[module_id].scope; 486 let scope = &mut self.def_map.modules[module_id].scope;
459 let mut changed = false; 487 let mut changed = false;
460 for (name, res) in resolutions { 488 for (name, res) in resolutions {
461 changed |= scope.push_res(name.clone(), *res); 489 changed |= scope.push_res(name.clone(), res.with_visibility(vis));
462 } 490 }
463 491
464 if !changed { 492 if !changed {
@@ -471,9 +499,13 @@ where
471 .flat_map(|v| v.iter()) 499 .flat_map(|v| v.iter())
472 .cloned() 500 .cloned()
473 .collect::<Vec<_>>(); 501 .collect::<Vec<_>>();
474 for (glob_importing_module, _glob_import) in glob_imports { 502 for (glob_importing_module, glob_import_vis) in glob_imports {
475 // We pass the glob import so that the tracked import in those modules is that glob import 503 // we know all resolutions have the same visibility (`vis`), so we
476 self.update_recursive(glob_importing_module, resolutions, depth + 1); 504 // just need to check that once
505 if !vis.visible_from_def_map(&self.def_map, glob_importing_module) {
506 continue;
507 }
508 self.update_recursive(glob_importing_module, resolutions, glob_import_vis, depth + 1);
477 } 509 }
478 } 510 }
479 511
@@ -715,7 +747,7 @@ where
715 let def: ModuleDefId = module.into(); 747 let def: ModuleDefId = module.into();
716 let vis = ResolvedVisibility::Public; // TODO handle module visibility 748 let vis = ResolvedVisibility::Public; // TODO handle module visibility
717 self.def_collector.def_map.modules[self.module_id].scope.define_def(def); 749 self.def_collector.def_map.modules[self.module_id].scope.define_def(def);
718 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))]); 750 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis);
719 res 751 res
720 } 752 }
721 753
@@ -780,7 +812,7 @@ where
780 .def_map 812 .def_map
781 .resolve_visibility(self.def_collector.db, self.module_id, vis) 813 .resolve_visibility(self.def_collector.db, self.module_id, vis)
782 .unwrap_or(ResolvedVisibility::Public); 814 .unwrap_or(ResolvedVisibility::Public);
783 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))]) 815 self.def_collector.update(self.module_id, &[(name, PerNs::from_def(def, vis))], vis)
784 } 816 }
785 817
786 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { 818 fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) {
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..5f137d3a6 100644
--- a/crates/ra_hir_def/src/nameres/tests/globs.rs
+++ b/crates/ra_hir_def/src/nameres/tests/globs.rs
@@ -74,6 +74,84 @@ 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 pub 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 bar: t
140 foo: t
141
142 crate::foo
143 Foo: t v
144 bar: t
145
146 crate::foo::bar
147 PrivateBar: t v
148 PrivateBaz: t v
149 PubCrateStruct: t v
150 "###
151 );
152}
153
154#[test]
77fn glob_across_crates() { 155fn glob_across_crates() {
78 covers!(glob_across_crates); 156 covers!(glob_across_crates);
79 let map = def_map( 157 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 }
diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs
index 16e61a6a5..7637d8a37 100644
--- a/crates/ra_hir_def/src/per_ns.rs
+++ b/crates/ra_hir_def/src/per_ns.rs
@@ -61,6 +61,14 @@ impl PerNs {
61 self.macros.map(|it| it.0) 61 self.macros.map(|it| it.0)
62 } 62 }
63 63
64 pub fn filter_visibility(self, mut f: impl FnMut(ResolvedVisibility) -> bool) -> PerNs {
65 PerNs {
66 types: self.types.filter(|(_, v)| f(*v)),
67 values: self.values.filter(|(_, v)| f(*v)),
68 macros: self.macros.filter(|(_, v)| f(*v)),
69 }
70 }
71
64 pub fn with_visibility(self, vis: ResolvedVisibility) -> PerNs { 72 pub fn with_visibility(self, vis: ResolvedVisibility) -> PerNs {
65 PerNs { 73 PerNs {
66 types: self.types.map(|(it, _)| (it, vis)), 74 types: self.types.map(|(it, _)| (it, vis)),
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs
index 8cac52630..990b2975c 100644
--- a/crates/ra_hir_def/src/visibility.rs
+++ b/crates/ra_hir_def/src/visibility.rs
@@ -134,13 +134,25 @@ impl ResolvedVisibility {
134 if from_module.krate != to_module.krate { 134 if from_module.krate != to_module.krate {
135 return false; 135 return false;
136 } 136 }
137 // from_module needs to be a descendant of to_module
138 let def_map = db.crate_def_map(from_module.krate); 137 let def_map = db.crate_def_map(from_module.krate);
138 self.visible_from_def_map(&def_map, from_module.local_id)
139 }
140
141 pub(crate) fn visible_from_def_map(
142 self,
143 def_map: &crate::nameres::CrateDefMap,
144 from_module: crate::LocalModuleId,
145 ) -> bool {
146 let to_module = match self {
147 ResolvedVisibility::Module(m) => m,
148 ResolvedVisibility::Public => return true,
149 };
150 // from_module needs to be a descendant of to_module
139 let mut ancestors = std::iter::successors(Some(from_module), |m| { 151 let mut ancestors = std::iter::successors(Some(from_module), |m| {
140 let parent_id = def_map[m.local_id].parent?; 152 let parent_id = def_map[*m].parent?;
141 Some(ModuleId { local_id: parent_id, ..*m }) 153 Some(parent_id)
142 }); 154 });
143 ancestors.any(|m| m == to_module) 155 ancestors.any(|m| m == to_module.local_id)
144 } 156 }
145} 157}
146 158