diff options
Diffstat (limited to 'crates/ra_hir_def/src/visibility.rs')
-rw-r--r-- | crates/ra_hir_def/src/visibility.rs | 41 |
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 | ||
6 | use crate::{ | 6 | use 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 | } |