mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 21:43:37 +00:00
Handle visibility in method call completion
This commit is contained in:
parent
aff82cf7ac
commit
734e68da4c
3 changed files with 54 additions and 4 deletions
|
@ -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,
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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!(
|
||||||
|
|
Loading…
Reference in a new issue