diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 12 | ||||
-rw-r--r-- | crates/ra_ide/src/completion/complete_path.rs | 44 |
2 files changed, 51 insertions, 5 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index f93b43fb6..4d1e8f921 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -204,10 +204,20 @@ impl Module { | |||
204 | } | 204 | } |
205 | 205 | ||
206 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 206 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
207 | pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef)> { | 207 | pub fn scope(self, db: &impl HirDatabase, visible_from: Option<Module>) -> Vec<(Name, ScopeDef)> { |
208 | db.crate_def_map(self.id.krate)[self.id.local_id] | 208 | db.crate_def_map(self.id.krate)[self.id.local_id] |
209 | .scope | 209 | .scope |
210 | .entries() | 210 | .entries() |
211 | .filter_map(|(name, def)| if let Some(m) = visible_from { | ||
212 | let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id)); | ||
213 | if filtered.is_none() && !def.is_none() { | ||
214 | None | ||
215 | } else { | ||
216 | Some((name, filtered)) | ||
217 | } | ||
218 | } else { | ||
219 | Some((name, def)) | ||
220 | }) | ||
211 | .map(|(name, def)| (name.clone(), def.into())) | 221 | .map(|(name, def)| (name.clone(), def.into())) |
212 | .collect() | 222 | .collect() |
213 | } | 223 | } |
diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 1a9699466..f99b1c2c4 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Completion of paths, including when writing a single name. | 1 | //! Completion of paths, including when writing a single name. |
2 | 2 | ||
3 | use hir::{Adt, PathResolution, ScopeDef}; | 3 | use hir::{Adt, PathResolution, ScopeDef, HasVisibility}; |
4 | use ra_syntax::AstNode; | 4 | use ra_syntax::AstNode; |
5 | use test_utils::tested_by; | 5 | use test_utils::tested_by; |
6 | 6 | ||
@@ -15,9 +15,10 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
15 | Some(PathResolution::Def(def)) => def, | 15 | Some(PathResolution::Def(def)) => def, |
16 | _ => return, | 16 | _ => return, |
17 | }; | 17 | }; |
18 | let context_module = ctx.scope().module(); | ||
18 | match def { | 19 | match def { |
19 | hir::ModuleDef::Module(module) => { | 20 | hir::ModuleDef::Module(module) => { |
20 | let module_scope = module.scope(ctx.db); | 21 | let module_scope = module.scope(ctx.db, context_module); |
21 | for (name, def) in module_scope { | 22 | for (name, def) in module_scope { |
22 | if ctx.use_item_syntax.is_some() { | 23 | if ctx.use_item_syntax.is_some() { |
23 | if let ScopeDef::Unknown = def { | 24 | if let ScopeDef::Unknown = def { |
@@ -53,7 +54,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
53 | ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { | 54 | ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| { |
54 | match item { | 55 | match item { |
55 | hir::AssocItem::Function(func) => { | 56 | hir::AssocItem::Function(func) => { |
56 | if !func.has_self_param(ctx.db) { | 57 | if !func.has_self_param(ctx.db) && context_module.map_or(true, |m| func.is_visible_from(ctx.db, m)) { |
57 | acc.add_function(ctx, func); | 58 | acc.add_function(ctx, func); |
58 | } | 59 | } |
59 | } | 60 | } |
@@ -170,6 +171,41 @@ mod tests { | |||
170 | } | 171 | } |
171 | 172 | ||
172 | #[test] | 173 | #[test] |
174 | fn path_visibility() { | ||
175 | assert_debug_snapshot!( | ||
176 | do_reference_completion( | ||
177 | r" | ||
178 | use self::my::<|>; | ||
179 | |||
180 | mod my { | ||
181 | struct Bar; | ||
182 | pub struct Foo; | ||
183 | pub use Bar as PublicBar; | ||
184 | } | ||
185 | " | ||
186 | ), | ||
187 | @r###" | ||
188 | [ | ||
189 | CompletionItem { | ||
190 | label: "Foo", | ||
191 | source_range: [31; 31), | ||
192 | delete: [31; 31), | ||
193 | insert: "Foo", | ||
194 | kind: Struct, | ||
195 | }, | ||
196 | CompletionItem { | ||
197 | label: "PublicBar", | ||
198 | source_range: [31; 31), | ||
199 | delete: [31; 31), | ||
200 | insert: "PublicBar", | ||
201 | kind: Struct, | ||
202 | }, | ||
203 | ] | ||
204 | "### | ||
205 | ); | ||
206 | } | ||
207 | |||
208 | #[test] | ||
173 | fn completes_use_item_starting_with_self() { | 209 | fn completes_use_item_starting_with_self() { |
174 | assert_debug_snapshot!( | 210 | assert_debug_snapshot!( |
175 | do_reference_completion( | 211 | do_reference_completion( |
@@ -177,7 +213,7 @@ mod tests { | |||
177 | use self::m::<|>; | 213 | use self::m::<|>; |
178 | 214 | ||
179 | mod m { | 215 | mod m { |
180 | struct Bar; | 216 | pub struct Bar; |
181 | } | 217 | } |
182 | " | 218 | " |
183 | ), | 219 | ), |