Handle visibility in method call completion

This commit is contained in:
Florian Diebold 2020-03-07 23:03:56 +01:00
parent aff82cf7ac
commit 734e68da4c
3 changed files with 54 additions and 4 deletions

View file

@ -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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Const { pub struct Const {
pub(crate) id: ConstId, pub(crate) id: ConstId,

View file

@ -7,13 +7,16 @@ use hir_expand::{
AstId, InFile, AstId, InFile,
}; };
use ra_prof::profile; 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::{ use crate::{
db::DefDatabase, db::DefDatabase,
path::{path, GenericArgs, Path}, path::{path, GenericArgs, Path},
src::HasSource, src::HasSource,
type_ref::{Mutability, TypeBound, TypeRef}, type_ref::{Mutability, TypeBound, TypeRef},
visibility::RawVisibility,
AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 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 /// True if the first param is `self`. This is relevant to decide whether this
/// can be called as a method. /// can be called as a method.
pub has_self_param: bool, pub has_self_param: bool,
pub visibility: RawVisibility,
} }
impl FunctionData { impl FunctionData {
@ -72,7 +76,9 @@ impl FunctionData {
ret_type 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) Arc::new(sig)
} }
} }
@ -230,7 +236,7 @@ impl ConstData {
Arc::new(ConstData::new(&node)) Arc::new(ConstData::new(&node))
} }
fn new<N: NameOwner + TypeAscriptionOwner>(node: &N) -> ConstData { fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(node: &N) -> ConstData {
let name = node.name().map(|n| n.as_name()); let name = node.name().map(|n| n.as_name());
let type_ref = TypeRef::from_ast_opt(node.ascribed_type()); let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
ConstData { name, type_ref } ConstData { name, type_ref }

View file

@ -57,7 +57,10 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
let mut seen_methods = FxHashSet::default(); let mut seen_methods = FxHashSet::default();
let traits_in_scope = ctx.scope().traits_in_scope(); let traits_in_scope = ctx.scope().traits_in_scope();
receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { 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); acc.add_function(ctx, func);
} }
None::<()> 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] #[test]
fn test_trait_method_completion() { fn test_trait_method_completion() {
assert_debug_snapshot!( assert_debug_snapshot!(