aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/visibility.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src/visibility.rs')
-rw-r--r--crates/ra_hir_def/src/visibility.rs41
1 files changed, 40 insertions, 1 deletions
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs
index 8136cb50c..1abffb4c3 100644
--- a/crates/ra_hir_def/src/visibility.rs
+++ b/crates/ra_hir_def/src/visibility.rs
@@ -5,6 +5,7 @@ use ra_syntax::ast;
5 5
6use crate::{ 6use crate::{
7 db::DefDatabase, 7 db::DefDatabase,
8 nameres::CrateDefMap,
8 path::{ModPath, PathKind}, 9 path::{ModPath, PathKind},
9 ModuleId, 10 ModuleId,
10}; 11};
@@ -115,7 +116,7 @@ impl Visibility {
115 116
116 pub(crate) fn is_visible_from_def_map( 117 pub(crate) fn is_visible_from_def_map(
117 self, 118 self,
118 def_map: &crate::nameres::CrateDefMap, 119 def_map: &CrateDefMap,
119 from_module: crate::LocalModuleId, 120 from_module: crate::LocalModuleId,
120 ) -> bool { 121 ) -> bool {
121 let to_module = match self { 122 let to_module = match self {
@@ -129,4 +130,42 @@ impl Visibility {
129 }); 130 });
130 ancestors.any(|m| m == to_module.local_id) 131 ancestors.any(|m| m == to_module.local_id)
131 } 132 }
133
134 /// Returns the most permissive visibility of `self` and `other`.
135 ///
136 /// If there is no subset relation between `self` and `other`, returns `None` (ie. they're only
137 /// visible in unrelated modules).
138 pub(crate) fn max(self, other: Visibility, def_map: &CrateDefMap) -> Option<Visibility> {
139 match (self, other) {
140 (Visibility::Module(_), Visibility::Public)
141 | (Visibility::Public, Visibility::Module(_))
142 | (Visibility::Public, Visibility::Public) => Some(Visibility::Public),
143 (Visibility::Module(mod_a), Visibility::Module(mod_b)) => {
144 if mod_a.krate != mod_b.krate {
145 return None;
146 }
147
148 let mut a_ancestors = std::iter::successors(Some(mod_a.local_id), |m| {
149 let parent_id = def_map[*m].parent?;
150 Some(parent_id)
151 });
152 let mut b_ancestors = std::iter::successors(Some(mod_b.local_id), |m| {
153 let parent_id = def_map[*m].parent?;
154 Some(parent_id)
155 });
156
157 if a_ancestors.any(|m| m == mod_b.local_id) {
158 // B is above A
159 return Some(Visibility::Module(mod_b));
160 }
161
162 if b_ancestors.any(|m| m == mod_a.local_id) {
163 // A is above B
164 return Some(Visibility::Module(mod_a));
165 }
166
167 None
168 }
169 }
170 }
132} 171}