Skip to content

Commit 05e1c7b

Browse files
committed
Handle visibility for assoc item path completion as well
1 parent d9c77c5 commit 05e1c7b

File tree

3 files changed

+124
-22
lines changed

3 files changed

+124
-22
lines changed

crates/ra_hir/src/code_model.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,19 +204,25 @@ impl Module {
204204
}
205205

206206
/// Returns a `ModuleScope`: a set of items, visible in this module.
207-
pub fn scope(self, db: &impl HirDatabase, visible_from: Option<Module>) -> 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()
211-
.filter_map(|(name, def)| if let Some(m) = visible_from {
212-
let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id));
213-
if filtered.is_none() && !def.is_none() {
214-
None
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+
}
215223
} else {
216-
Some((name, filtered))
224+
Some((name, def))
217225
}
218-
} else {
219-
Some((name, def))
220226
})
221227
.map(|(name, def)| (name.clone(), def.into()))
222228
.collect()
@@ -608,6 +614,14 @@ impl Const {
608614
}
609615
}
610616

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+
611625
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
612626
pub struct Static {
613627
pub(crate) id: StaticId,
@@ -682,6 +696,14 @@ impl TypeAlias {
682696
}
683697
}
684698

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+
685707
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
686708
pub struct MacroDef {
687709
pub(crate) id: MacroDefId,
@@ -769,6 +791,16 @@ impl AssocItem {
769791
}
770792
}
771793

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+
772804
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
773805
pub enum GenericDef {
774806
Function(Function),

crates/ra_hir_def/src/data.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,19 @@ fn desugar_future_path(orig: TypeRef) -> Path {
9797
pub struct TypeAliasData {
9898
pub name: Name,
9999
pub type_ref: Option<TypeRef>,
100+
pub visibility: RawVisibility,
100101
}
101102

102103
impl TypeAliasData {
103104
pub(crate) fn type_alias_data_query(
104105
db: &impl DefDatabase,
105106
typ: TypeAliasId,
106107
) -> Arc<TypeAliasData> {
107-
let node = typ.lookup(db).source(db).value;
108-
let name = node.name().map_or_else(Name::missing, |n| n.as_name());
109-
let type_ref = node.type_ref().map(TypeRef::from_ast);
110-
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 })
111113
}
112114
}
113115

@@ -223,23 +225,28 @@ pub struct ConstData {
223225
/// const _: () = ();
224226
pub name: Option<Name>,
225227
pub type_ref: TypeRef,
228+
pub visibility: RawVisibility,
226229
}
227230

228231
impl ConstData {
229232
pub(crate) fn const_data_query(db: &impl DefDatabase, konst: ConstId) -> Arc<ConstData> {
230-
let node = konst.lookup(db).source(db).value;
231-
Arc::new(ConstData::new(&node))
233+
let node = konst.lookup(db).source(db);
234+
Arc::new(ConstData::new(db, node))
232235
}
233236

234237
pub(crate) fn static_data_query(db: &impl DefDatabase, konst: StaticId) -> Arc<ConstData> {
235-
let node = konst.lookup(db).source(db).value;
236-
Arc::new(ConstData::new(&node))
238+
let node = konst.lookup(db).source(db);
239+
Arc::new(ConstData::new(db, node))
237240
}
238241

239-
fn new<N: NameOwner + TypeAscriptionOwner + VisibilityOwner>(node: &N) -> ConstData {
240-
let name = node.name().map(|n| n.as_name());
241-
let type_ref = TypeRef::from_ast_opt(node.ascribed_type());
242-
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 }
243250
}
244251
}
245252

crates/ra_ide/src/completion/complete_path.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Completion of paths, including when writing a single name.
22
3-
use hir::{Adt, PathResolution, ScopeDef, HasVisibility};
3+
use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
44
use ra_syntax::AstNode;
55
use test_utils::tested_by;
66

@@ -52,9 +52,12 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
5252
if let Some(krate) = krate {
5353
let traits_in_scope = ctx.scope().traits_in_scope();
5454
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
55+
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
56+
return None;
57+
}
5558
match item {
5659
hir::AssocItem::Function(func) => {
57-
if !func.has_self_param(ctx.db) && context_module.map_or(true, |m| func.is_visible_from(ctx.db, m)) {
60+
if !func.has_self_param(ctx.db) {
5861
acc.add_function(ctx, func);
5962
}
6063
}
@@ -65,6 +68,9 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
6568
});
6669

6770
ty.iterate_impl_items(ctx.db, krate, |item| {
71+
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
72+
return None;
73+
}
6874
match item {
6975
hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => {}
7076
hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
@@ -75,6 +81,9 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
7581
}
7682
hir::ModuleDef::Trait(t) => {
7783
for item in t.items(ctx.db) {
84+
if context_module.map_or(false, |m| !item.is_visible_from(ctx.db, m)) {
85+
continue;
86+
}
7887
match item {
7988
hir::AssocItem::Function(func) => {
8089
if !func.has_self_param(ctx.db) {
@@ -537,6 +546,60 @@ mod tests {
537546
);
538547
}
539548

549+
#[test]
550+
fn associated_item_visibility() {
551+
assert_debug_snapshot!(
552+
do_reference_completion(
553+
"
554+
//- /lib.rs
555+
struct S;
556+
557+
mod m {
558+
impl super::S {
559+
pub(super) fn public_method() { }
560+
fn private_method() { }
561+
pub(super) type PublicType = u32;
562+
type PrivateType = u32;
563+
pub(super) const PUBLIC_CONST: u32 = 1;
564+
const PRIVATE_CONST: u32 = 1;
565+
}
566+
}
567+
568+
fn foo() { let _ = S::<|> }
569+
"
570+
),
571+
@r###"
572+
[
573+
CompletionItem {
574+
label: "PUBLIC_CONST",
575+
source_range: [302; 302),
576+
delete: [302; 302),
577+
insert: "PUBLIC_CONST",
578+
kind: Const,
579+
detail: "pub(super) const PUBLIC_CONST: u32 = 1;",
580+
},
581+
CompletionItem {
582+
label: "PublicType",
583+
source_range: [302; 302),
584+
delete: [302; 302),
585+
insert: "PublicType",
586+
kind: TypeAlias,
587+
detail: "pub(super) type PublicType = u32;",
588+
},
589+
CompletionItem {
590+
label: "public_method()",
591+
source_range: [302; 302),
592+
delete: [302; 302),
593+
insert: "public_method()$0",
594+
kind: Function,
595+
lookup: "public_method",
596+
detail: "pub(super) fn public_method()",
597+
},
598+
]
599+
"###
600+
);
601+
}
602+
540603
#[test]
541604
fn completes_enum_associated_method() {
542605
assert_debug_snapshot!(

0 commit comments

Comments
 (0)