diff options
| author | Florian Diebold <[email protected]> | 2020-03-08 09:51:40 +0000 |
|---|---|---|
| committer | Florian Diebold <[email protected]> | 2020-03-08 09:51:40 +0000 |
| commit | d9c77c54534fcde7c432c6e11746d636d972a20b (patch) | |
| tree | cdf44c613f55bdd99ab08490b32c185e9915c7bd /crates | |
| parent | 734e68da4ceb1b15b3430302f233d4700d694728 (diff) | |
Handle visibility for path completion (not in all cases yet)
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 | ), |
