diff options
author | Florian Diebold <[email protected]> | 2019-12-24 20:23:22 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-12-26 15:23:40 +0000 |
commit | 1ce809d0fa59ade71b13c200870b1fd5f74ceff4 (patch) | |
tree | 4ba1954121fcf4145b4b0deea16456d9f19754e8 /crates | |
parent | 069bf55cca1e1be1f6cdd28b638f691e059858dc (diff) |
Add logic for resolving and checking visibility
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_def/src/resolver.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir_def/src/visibility.rs | 40 |
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)] | ||
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 |