Skip to content

Commit 30062da

Browse files
Merge #3516
3516: Handle visibility in more cases in completion r=matklad a=flodiebold This means we don't show private items when completing paths or method calls. We might want to show private items if we can edit their definition and provide a "make public" assist, but I feel like we'd need better sorting of completion items for that, so they can be not shown or sorted to the bottom by default. Until then, they're usually more of a distraction to me. Co-authored-by: Florian Diebold <flodiebold@gmail.com>
2 parents 0363c94 + 05e1c7b commit 30062da

File tree

4 files changed

+217
-19
lines changed

4 files changed

+217
-19
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,26 @@ impl Module {
204204
}
205205

206206
/// 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(
208+
self,
209+
db: &impl HirDatabase,
210+
visible_from: Option<Module>,
211+
) -> Vec<(Name, ScopeDef)> {
208212
db.crate_def_map(self.id.krate)[self.id.local_id]
209213
.scope
210214
.entries()
215+
.filter_map(|(name, def)| {
216+
if let Some(m) = visible_from {
217+
let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id));
218+
if filtered.is_none() && !def.is_none() {
219+
None
220+
} else {
221+
Some((name, filtered))
222+
}
223+
} else {
224+
Some((name, def))
225+
}
226+
})
211227
.map(|(name, def)| (name.clone(), def.into()))
212228
.collect()
213229
}
@@ -571,6 +587,14 @@ impl Function {
571587
}
572588
}
573589

590+
impl HasVisibility for Function {
591+
fn visibility(&self, db: &impl HirDatabase) -> Visibility {
592+
let function_data = db.function_data(self.id);
593+
let visibility = &function_data.visibility;
594+
visibility.resolve(db, &self.id.resolver(db))
595+
}
596+
}
597+
574598
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
575599
pub struct Const {
576600
pub(crate) id: ConstId,
@@ -590,6 +614,14 @@ impl Const {
590614
}
591615
}
592616

617+
impl HasVisibility for Const {
618+
fn visibility(&self, db: &impl HirDatabase) -> Visibility {
619+
let function_data = db.const_data(self.id);
620+
let visibility = &function_data.visibility;
621+
visibility.resolve(db, &self.id.resolver(db))
622+
}
623+
}
624+
593625
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
594626
pub struct Static {
595627
pub(crate) id: StaticId,
@@ -664,6 +696,14 @@ impl TypeAlias {
664696
}
665697
}
666698

699+
impl HasVisibility for TypeAlias {
700+
fn visibility(&self, db: &impl HirDatabase) -> Visibility {
701+
let function_data = db.type_alias_data(self.id);
702+
let visibility = &function_data.visibility;
703+
visibility.resolve(db, &self.id.resolver(db))
704+
}
705+
}
706+
667707
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
668708
pub struct MacroDef {
669709
pub(crate) id: MacroDefId,
@@ -751,6 +791,16 @@ impl AssocItem {
751791
}
752792
}
753793

794+
impl HasVisibility for AssocItem {
795+
fn visibility(&self, db: &impl HirDatabase) -> Visibility {
796+
match self {
797+
AssocItem::Function(f) => f.visibility(db),
798+
AssocItem::Const(c) => c.visibility(db),
799+
AssocItem::TypeAlias(t) => t.visibility(db),
800+
}
801+
}
802+
}
803+
754804
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
755805
pub enum GenericDef {
756806
Function(Function),

crates/ra_hir_def/src/data.rs

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ use hir_expand::{
77
AstId, InFile,
88
};
99
use ra_prof::profile;
10-
use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner};
10+
use ra_syntax::ast::{
11+
self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, VisibilityOwner,
12+
};
1113

1214
use crate::{
1315
db::DefDatabase,
1416
path::{path, GenericArgs, Path},
1517
src::HasSource,
1618
type_ref::{Mutability, TypeBound, TypeRef},
19+
visibility::RawVisibility,
1720
AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
1821
ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
1922
};
@@ -26,6 +29,7 @@ pub struct FunctionData {
2629
/// True if the first param is `self`. This is relevant to decide whether this
2730
/// can be called as a method.
2831
pub has_self_param: bool,
32+
pub visibility: RawVisibility,
2933
}
3034

3135
impl FunctionData {
@@ -72,7 +76,9 @@ impl FunctionData {
7276
ret_type
7377
};
7478

75-
let sig = FunctionData { name, params, ret_type, has_self_param };
79+
let visibility = RawVisibility::from_ast(db, src.map(|s| s.visibility()));
80+
81+
let sig = FunctionData { name, params, ret_type, has_self_param, visibility };
7682
Arc::new(sig)
7783
}
7884
}
@@ -91,17 +97,19 @@ fn desugar_future_path(orig: TypeRef) -> Path {
9197
pub struct TypeAliasData {
9298
pub name: Name,
9399
pub type_ref: Option<TypeRef>,
100+
pub visibility: RawVisibility,
94101
}
95102

96103
impl TypeAliasData {
97104
pub(crate) fn type_alias_data_query(
98105
db: &impl DefDatabase,
99106
typ: TypeAliasId,
100107
) -> Arc<TypeAliasData> {
101-
let node = typ.lookup(db).source(db).value;
102-
let name = node.name().map_or_else(Name::missing, |n| n.as_name());
103-
let type_ref = node.type_ref().map(TypeRef::from_ast);
104-
Arc::new(TypeAliasData { name, type_ref })
108+
let node = typ.lookup(db).source(db);
109+
let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
110+
let type_ref = node.value.type_ref().map(TypeRef::from_ast);
111+
let visibility = RawVisibility::from_ast(db, node.map(|n| n.visibility()));
112+
Arc::new(TypeAliasData { name, type_ref, visibility })
105113
}
106114
}
107115

@@ -217,23 +225,28 @@ pub struct ConstData {
217225
/// const _: () = ();
218226
pub name: Option<Name>,
219227
pub type_ref: TypeRef,
228+
pub visibility: RawVisibility,
220229
}
221230

222231
impl ConstData {
223232
pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> {
224-
let node = konst.lookup(db).source(db).value;
225-
Arc::new(ConstData::new(&node))
233+
let node = konst.lookup(db).source(db);
234+
Arc::new(ConstData::new(db, node))
226235
}
227236

228237
pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
229-
let node = konst.lookup(db).source(db).value;
230-
Arc::new(ConstData::new(&node))
238+
let node = konst.lookup(db).source(db);
239+
Arc::new(ConstData::new(db, node))
231240
}
232241

233-
fn new<N: NameOwner + TypeAscriptionOwner>(node: &N) -> ConstData {
234-
let name = node.name().map(|n| n.as_name());
235-
let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
236-
ConstData { name, type_ref }
242+
fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(
243+
db: &impl DefDatabase,
244+
node: InFile<N>,
245+
) -> ConstData {
246+
let name = node.value.name().map(|n| n.as_name());
247+
let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type());
248+
let visibility = RawVisibility::from_ast(db, node.map(|n| n.visibility()));
249+
ConstData { name, type_ref, visibility }
237250
}
238251
}
239252

crates/ra_ide/src/completion/complete_dot.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
5757
let mut seen_methods = FxHashSet::default();
5858
let traits_in_scope = ctx.scope().traits_in_scope();
5959
receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| {
60-
if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) {
60+
if func.has_self_param(ctx.db)
61+
&& ctx.scope().module().map_or(true, |m| func.is_visible_from(ctx.db, m))
62+
&& seen_methods.insert(func.name(ctx.db))
63+
{
6164
acc.add_function(ctx, func);
6265
}
6366
None::<()>
@@ -307,6 +310,39 @@ mod tests {
307310
);
308311
}
309312

313+
#[test]
314+
fn test_method_completion_private() {
315+
assert_debug_snapshot!(
316+
do_ref_completion(
317+
r"
318+
struct A {}
319+
mod m {
320+
impl super::A {
321+
fn private_method(&self) {}
322+
pub(super) fn the_method(&self) {}
323+
}
324+
}
325+
fn foo(a: A) {
326+
a.<|>
327+
}
328+
",
329+
),
330+
@r###"
331+
[
332+
CompletionItem {
333+
label: "the_method()",
334+
source_range: [256; 256),
335+
delete: [256; 256),
336+
insert: "the_method()$0",
337+
kind: Method,
338+
lookup: "the_method",
339+
detail: "pub(super) fn the_method(&self)",
340+
},
341+
]
342+
"###
343+
);
344+
}
345+
310346
#[test]
311347
fn test_trait_method_completion() {
312348
assert_debug_snapshot!(

0 commit comments

Comments
 (0)