Handle visibility for path completion (not in all cases yet)

This commit is contained in:
Florian Diebold 2020-03-08 10:51:40 +01:00
parent 734e68da4c
commit d9c77c5453
2 changed files with 51 additions and 5 deletions

View file

@ -204,10 +204,20 @@ impl Module {
}
/// Returns a `ModuleScope`: a set of items, visible in this module.
pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef)> {
pub fn scope(self, db: &impl HirDatabase, visible_from: Option<Module>) -> Vec<(Name, ScopeDef)> {
db.crate_def_map(self.id.krate)[self.id.local_id]
.scope
.entries()
.filter_map(|(name, def)| if let Some(m) = visible_from {
let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id));
if filtered.is_none() && !def.is_none() {
None
} else {
Some((name, filtered))
}
} else {
Some((name, def))
})
.map(|(name, def)| (name.clone(), def.into()))
.collect()
}

View file

@ -1,6 +1,6 @@
//! Completion of paths, including when writing a single name.
use hir::{Adt, PathResolution, ScopeDef};
use hir::{Adt, PathResolution, ScopeDef, HasVisibility};
use ra_syntax::AstNode;
use test_utils::tested_by;
@ -15,9 +15,10 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
Some(PathResolution::Def(def)) => def,
_ => return,
};
let context_module = ctx.scope().module();
match def {
hir::ModuleDef::Module(module) => {
let module_scope = module.scope(ctx.db);
let module_scope = module.scope(ctx.db, context_module);
for (name, def) in module_scope {
if ctx.use_item_syntax.is_some() {
if let ScopeDef::Unknown = def {
@ -53,7 +54,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
ty.iterate_path_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, item| {
match item {
hir::AssocItem::Function(func) => {
if !func.has_self_param(ctx.db) {
if !func.has_self_param(ctx.db) && context_module.map_or(true, |m| func.is_visible_from(ctx.db, m)) {
acc.add_function(ctx, func);
}
}
@ -169,6 +170,41 @@ mod tests {
);
}
#[test]
fn path_visibility() {
assert_debug_snapshot!(
do_reference_completion(
r"
use self::my::<|>;
mod my {
struct Bar;
pub struct Foo;
pub use Bar as PublicBar;
}
"
),
@r###"
[
CompletionItem {
label: "Foo",
source_range: [31; 31),
delete: [31; 31),
insert: "Foo",
kind: Struct,
},
CompletionItem {
label: "PublicBar",
source_range: [31; 31),
delete: [31; 31),
insert: "PublicBar",
kind: Struct,
},
]
"###
);
}
#[test]
fn completes_use_item_starting_with_self() {
assert_debug_snapshot!(
@ -177,7 +213,7 @@ mod tests {
use self::m::<|>;
mod m {
struct Bar;
pub struct Bar;
}
"
),