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)]
pub struct Const {
pub(crate) id: ConstId,

View file

@ -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<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 type_ref = TypeRef::from_ast_opt(node.ascribed_type());
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 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!(