From 734e68da4ceb1b15b3430302f233d4700d694728 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 7 Mar 2020 23:03:56 +0100 Subject: Handle visibility in method call completion --- crates/ra_hir/src/code_model.rs | 8 ++++++ crates/ra_hir_def/src/data.rs | 12 ++++++--- crates/ra_ide/src/completion/complete_dot.rs | 38 +++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 2944926e6..f93b43fb6 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -571,6 +571,14 @@ impl Function { } } +impl HasVisibility for Function { + fn visibility(&self, db: &impl HirDatabase) -> Visibility { + let function_data = db.function_data(self.id); + let visibility = &function_data.visibility; + visibility.resolve(db, &self.id.resolver(db)) + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Const { pub(crate) id: ConstId, diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 9fc43f3fb..8b343af9d 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -7,13 +7,16 @@ use hir_expand::{ AstId, InFile, }; use ra_prof::profile; -use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner}; +use ra_syntax::ast::{ + self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner, +}; use crate::{ db::DefDatabase, path::{path, GenericArgs, Path}, src::HasSource, type_ref::{Mutability, TypeBound, TypeRef}, + visibility::RawVisibility, AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, }; @@ -26,6 +29,7 @@ pub struct FunctionData { /// True if the first param is `self`. This is relevant to decide whether this /// can be called as a method. pub has_self_param: bool, + pub visibility: RawVisibility, } impl FunctionData { @@ -72,7 +76,9 @@ impl FunctionData { ret_type }; - let sig = FunctionData { name, params, ret_type, has_self_param }; + let visibility = RawVisibility::from_ast(db, src.map(|s| s.visibility())); + + let sig = FunctionData { name, params, ret_type, has_self_param, visibility }; Arc::new(sig) } } @@ -230,7 +236,7 @@ impl ConstData { Arc::new(ConstData::new(&node)) } - fn new(node: &N) -> ConstData { + fn new(node: &N) -> ConstData { let name = node.name().map(|n| n.as_name()); let type_ref = TypeRef::from_ast_opt(node.ascribed_type()); ConstData { name, type_ref } diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index 9145aa183..acada48ae 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs @@ -57,7 +57,10 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T let mut seen_methods = FxHashSet::default(); let traits_in_scope = ctx.scope().traits_in_scope(); receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { - if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { + if func.has_self_param(ctx.db) + && ctx.scope().module().map_or(true, |m| func.is_visible_from(ctx.db, m)) + && seen_methods.insert(func.name(ctx.db)) + { acc.add_function(ctx, func); } None::<()> @@ -307,6 +310,39 @@ mod tests { ); } + #[test] + fn test_method_completion_private() { + assert_debug_snapshot!( + do_ref_completion( + r" + struct A {} + mod m { + impl super::A { + fn private_method(&self) {} + pub(super) fn the_method(&self) {} + } + } + fn foo(a: A) { + a.<|> + } + ", + ), + @r###" + [ + CompletionItem { + label: "the_method()", + source_range: [256; 256), + delete: [256; 256), + insert: "the_method()$0", + kind: Method, + lookup: "the_method", + detail: "pub(super) fn the_method(&self)", + }, + ] + "### + ); + } + #[test] fn test_trait_method_completion() { assert_debug_snapshot!( -- cgit v1.2.3