diff options
Diffstat (limited to 'crates/ra_hir_def/src/visibility.rs')
-rw-r--r-- | crates/ra_hir_def/src/visibility.rs | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs index 7d881911d..901bc7191 100644 --- a/crates/ra_hir_def/src/visibility.rs +++ b/crates/ra_hir_def/src/visibility.rs | |||
@@ -9,7 +9,7 @@ use crate::{ | |||
9 | db::DefDatabase, | 9 | db::DefDatabase, |
10 | path::{ModPath, PathKind}, | 10 | path::{ModPath, PathKind}, |
11 | src::{HasChildSource, HasSource}, | 11 | src::{HasChildSource, HasSource}, |
12 | AdtId, Lookup, VisibilityDefId, | 12 | AdtId, Lookup, ModuleId, VisibilityDefId, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | /// Visibility of an item, not yet resolved. | 15 | /// Visibility of an item, not yet resolved. |
@@ -89,6 +89,44 @@ impl Visibility { | |||
89 | ast::VisibilityKind::Pub => Visibility::Public, | 89 | ast::VisibilityKind::Pub => Visibility::Public, |
90 | } | 90 | } |
91 | } | 91 | } |
92 | |||
93 | pub fn resolve( | ||
94 | &self, | ||
95 | db: &impl DefDatabase, | ||
96 | resolver: &crate::resolver::Resolver, | ||
97 | ) -> ResolvedVisibility { | ||
98 | // we fall back to public visibility (i.e. fail open) if the path can't be resolved | ||
99 | resolver.resolve_visibility(db, self).unwrap_or(ResolvedVisibility::Public) | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /// Visibility of an item, with the path resolved. | ||
104 | #[derive(Debug, Copy, Clone, PartialEq, Eq)] | ||
105 | pub enum ResolvedVisibility { | ||
106 | /// Visibility is restricted to a certain module. | ||
107 | Module(ModuleId), | ||
108 | /// Visibility is unrestricted. | ||
109 | Public, | ||
110 | } | ||
111 | |||
112 | impl ResolvedVisibility { | ||
113 | pub fn visible_from(self, db: &impl DefDatabase, from_module: ModuleId) -> bool { | ||
114 | let to_module = match self { | ||
115 | ResolvedVisibility::Module(m) => m, | ||
116 | ResolvedVisibility::Public => return true, | ||
117 | }; | ||
118 | // if they're not in the same crate, it can't be visible | ||
119 | if from_module.krate != to_module.krate { | ||
120 | return false; | ||
121 | } | ||
122 | // from_module needs to be a descendant of to_module | ||
123 | let def_map = db.crate_def_map(from_module.krate); | ||
124 | let mut ancestors = std::iter::successors(Some(from_module), |m| { | ||
125 | let parent_id = def_map[m.local_id].parent?; | ||
126 | Some(ModuleId { local_id: parent_id, ..*m }) | ||
127 | }); | ||
128 | ancestors.any(|m| m == to_module) | ||
129 | } | ||
92 | } | 130 | } |
93 | 131 | ||
94 | fn visibility_from_loc<T>(node: T, db: &impl DefDatabase) -> Visibility | 132 | fn visibility_from_loc<T>(node: T, db: &impl DefDatabase) -> Visibility |