Skip to content

Commit 2d879e0

Browse files
petr-tikVeykril
authored andcommitted
Stop offering private functions in completions
Before Private functions have RawVisibility module, but were missed because take_types returned None early. After resolve_visibility returned None, Visibility::Public was set instead and private functions ended up being offered in autocompletion. Choosing such a function results in an immediate error diagnostic about using a private function. After Pattern match of take_types that returns None and query for Module-level visibility from the original_module Fix rust-lang#15134 - tested with a unit test and a manual end-to-end test of building rust-analyzer from my branch and opening the reproduction repository REVIEW Refactor to move scope_def_applicable and check function visibility from a module Please let me know what's the best way to add a unit tests to nameres, which is where the root cause was
1 parent bc9c952 commit 2d879e0

File tree

3 files changed

+53
-14
lines changed

3 files changed

+53
-14
lines changed

crates/hir-def/src/nameres/path_resolution.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,15 @@ impl DefMap {
9393
if remaining.is_some() {
9494
return None;
9595
}
96-
let types = result.take_types()?;
97-
match types {
98-
ModuleDefId::ModuleId(m) => Visibility::Module(m),
99-
_ => {
100-
// error: visibility needs to refer to module
96+
let types = result.take_types();
97+
98+
match (types, path.kind) {
99+
(Some(ModuleDefId::ModuleId(m)), _) => Visibility::Module(m),
100+
// resolve_path doesn't find any values for a plan pathkind of a private function
101+
(None, PathKind::Plain | PathKind::Crate) => {
102+
Visibility::Module(self.module_id(original_module))
103+
}
104+
(_, _) => {
101105
return None;
102106
}
103107
}

crates/ide-completion/src/completions/expr.rs

+20-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Completion of names from the current scope in expression position.
22
3-
use hir::ScopeDef;
3+
use hir::{HasVisibility, Module, ScopeDef};
44
use syntax::ast;
55

66
use crate::{
@@ -9,6 +9,23 @@ use crate::{
99
CompletionContext, Completions,
1010
};
1111

12+
fn scope_def_applicable(
13+
def: ScopeDef,
14+
ctx: &CompletionContext<'_>,
15+
module: Option<&Module>,
16+
) -> bool {
17+
match (def, module) {
18+
(ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_), _) => {
19+
false
20+
}
21+
(ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)), _) => mac.is_fn_like(ctx.db),
22+
(ScopeDef::ModuleDef(hir::ModuleDef::Function(f)), Some(m)) => {
23+
f.is_visible_from(ctx.db, *m)
24+
}
25+
_ => true,
26+
}
27+
}
28+
1229
pub(crate) fn complete_expr_path(
1330
acc: &mut Completions,
1431
ctx: &CompletionContext<'_>,
@@ -37,12 +54,6 @@ pub(crate) fn complete_expr_path(
3754
let wants_mut_token =
3855
ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
3956

40-
let scope_def_applicable = |def| match def {
41-
ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => false,
42-
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
43-
_ => true,
44-
};
45-
4657
let add_assoc_item = |acc: &mut Completions, item| match item {
4758
hir::AssocItem::Function(func) => acc.add_function(ctx, path_ctx, func, None),
4859
hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
@@ -87,7 +98,7 @@ pub(crate) fn complete_expr_path(
8798
hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
8899
let module_scope = module.scope(ctx.db, Some(ctx.module));
89100
for (name, def) in module_scope {
90-
if scope_def_applicable(def) {
101+
if scope_def_applicable(def, ctx, Some(module)) {
91102
acc.add_path_resolution(
92103
ctx,
93104
path_ctx,
@@ -233,7 +244,7 @@ pub(crate) fn complete_expr_path(
233244
[..] => acc.add_path_resolution(ctx, path_ctx, name, def, doc_aliases),
234245
}
235246
}
236-
_ if scope_def_applicable(def) => {
247+
_ if scope_def_applicable(def, ctx, None) => {
237248
acc.add_path_resolution(ctx, path_ctx, name, def, doc_aliases)
238249
}
239250
_ => (),

crates/ide-completion/src/tests/special.rs

+24
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,30 @@ fn here_we_go() {
12861286
);
12871287
}
12881288

1289+
#[test]
1290+
fn completes_only_public() {
1291+
check(
1292+
r#"
1293+
//- /e.rs
1294+
pub(self) fn i_should_be_hidden() {}
1295+
pub(in crate::krate) fn i_should_also_be_hidden() {}
1296+
pub fn i_am_public () {}
1297+
1298+
//- /lib.rs crate:krate
1299+
pub mod e;
1300+
1301+
//- /main.rs deps:krate crate:main
1302+
use krate::e;
1303+
fn main() {
1304+
e::$0
1305+
}"#,
1306+
expect![
1307+
"fn i_am_public() fn()
1308+
"
1309+
],
1310+
)
1311+
}
1312+
12891313
#[test]
12901314
fn completion_filtering_excludes_non_identifier_doc_aliases() {
12911315
check_edit(

0 commit comments

Comments
 (0)