aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-12-24 20:23:22 +0000
committerFlorian Diebold <[email protected]>2019-12-26 15:23:40 +0000
commit1ce809d0fa59ade71b13c200870b1fd5f74ceff4 (patch)
tree4ba1954121fcf4145b4b0deea16456d9f19754e8 /crates
parent069bf55cca1e1be1f6cdd28b638f691e059858dc (diff)
Add logic for resolving and checking visibility
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/resolver.rs21
-rw-r--r--crates/ra_hir_def/src/visibility.rs40
2 files changed, 60 insertions, 1 deletions
diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs
index cf3c33d78..d509dc3dd 100644
--- a/crates/ra_hir_def/src/resolver.rs
+++ b/crates/ra_hir_def/src/resolver.rs
@@ -19,6 +19,7 @@ use crate::{
19 nameres::CrateDefMap, 19 nameres::CrateDefMap,
20 path::{ModPath, PathKind}, 20 path::{ModPath, PathKind},
21 per_ns::PerNs, 21 per_ns::PerNs,
22 visibility::{ResolvedVisibility, Visibility},
22 AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, 23 AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
23 FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, 24 FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
24 StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, 25 StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId,
@@ -231,6 +232,26 @@ impl Resolver {
231 Some(res) 232 Some(res)
232 } 233 }
233 234
235 pub fn resolve_visibility(
236 &self,
237 db: &impl DefDatabase,
238 visibility: &Visibility,
239 ) -> Option<ResolvedVisibility> {
240 match visibility {
241 Visibility::Module(mod_path) => {
242 let resolved = self.resolve_module_path_in_items(db, &mod_path).take_types()?;
243 match resolved {
244 ModuleDefId::ModuleId(m) => Some(ResolvedVisibility::Module(m)),
245 _ => {
246 // error: visibility needs to refer to module
247 None
248 }
249 }
250 }
251 Visibility::Public => Some(ResolvedVisibility::Public),
252 }
253 }
254
234 pub fn resolve_path_in_value_ns( 255 pub fn resolve_path_in_value_ns(
235 &self, 256 &self,
236 db: &impl DefDatabase, 257 db: &impl DefDatabase,
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)]
105pub enum ResolvedVisibility {
106 /// Visibility is restricted to a certain module.
107 Module(ModuleId),
108 /// Visibility is unrestricted.
109 Public,
110}
111
112impl 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
94fn visibility_from_loc<T>(node: T, db: &impl DefDatabase) -> Visibility 132fn visibility_from_loc<T>(node: T, db: &impl DefDatabase) -> Visibility