Skip to content

Commit b17be27

Browse files
committed
Auto merge of #15277 - 1Kinoti:pub-assist, r=lowr
limit `change_visibility` assist to applicable items this pr limits the `change_visibility` assist to applicable items. top level items in this context means items that are not nested within `fn`s or `trait`s. now ```rs fn foo { // assists on this `struct` keyword won't include `change_visibility` struct Bar {} } trait Foo { // same with the `fn` here fn bar(); } ```
2 parents a317fa8 + 65823b0 commit b17be27

File tree

1 file changed

+68
-7
lines changed

1 file changed

+68
-7
lines changed

crates/ide-assists/src/handlers/change_visibility.rs

+68-7
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use syntax::{
22
ast::{self, HasName, HasVisibility},
33
AstNode,
44
SyntaxKind::{
5-
CONST, ENUM, FN, MACRO_DEF, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, USE, VISIBILITY,
5+
self, ASSOC_ITEM_LIST, CONST, ENUM, FN, MACRO_DEF, MODULE, SOURCE_FILE, STATIC, STRUCT,
6+
TRAIT, TYPE_ALIAS, USE, VISIBILITY,
67
},
7-
T,
8+
SyntaxNode, T,
89
};
910

1011
use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
@@ -46,13 +47,11 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
4647

4748
let (offset, target) = if let Some(keyword) = item_keyword {
4849
let parent = keyword.parent()?;
49-
let def_kws =
50-
vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF];
51-
// Parent is not a definition, can't add visibility
52-
if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
50+
51+
if !can_add(&parent) {
5352
return None;
5453
}
55-
// Already have visibility, do nothing
54+
// Already has visibility, do nothing
5655
if parent.children().any(|child| child.kind() == VISIBILITY) {
5756
return None;
5857
}
@@ -86,6 +85,29 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
8685
)
8786
}
8887

88+
fn can_add(node: &SyntaxNode) -> bool {
89+
const LEGAL: &[SyntaxKind] =
90+
&[CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF];
91+
92+
LEGAL.contains(&node.kind()) && {
93+
let Some(p) = node.parent() else {
94+
return false;
95+
};
96+
97+
if p.kind() == ASSOC_ITEM_LIST {
98+
p.parent()
99+
.and_then(|it| ast::Impl::cast(it))
100+
// inherent impls i.e 'non-trait impls' have a non-local
101+
// effect, thus can have visibility even when nested.
102+
// so filter them out
103+
.filter(|imp| imp.for_token().is_none())
104+
.is_some()
105+
} else {
106+
matches!(p.kind(), SOURCE_FILE | MODULE)
107+
}
108+
}
109+
}
110+
89111
fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> {
90112
if vis.syntax().text() == "pub" {
91113
let target = vis.syntax().text_range();
@@ -129,6 +151,16 @@ mod tests {
129151
check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}");
130152
check_assist(change_visibility, "$0macro foo() {}", "pub(crate) macro foo() {}");
131153
check_assist(change_visibility, "$0use foo;", "pub(crate) use foo;");
154+
check_assist(
155+
change_visibility,
156+
"impl Foo { f$0n foo() {} }",
157+
"impl Foo { pub(crate) fn foo() {} }",
158+
);
159+
check_assist(
160+
change_visibility,
161+
"fn bar() { impl Foo { f$0n foo() {} } }",
162+
"fn bar() { impl Foo { pub(crate) fn foo() {} } }",
163+
);
132164
}
133165

134166
#[test]
@@ -213,4 +245,33 @@ mod tests {
213245
check_assist_target(change_visibility, "pub(crate)$0 fn foo() {}", "pub(crate)");
214246
check_assist_target(change_visibility, "struct S { $0field: u32 }", "field");
215247
}
248+
249+
#[test]
250+
fn not_applicable_for_items_within_traits() {
251+
check_assist_not_applicable(change_visibility, "trait Foo { f$0n run() {} }");
252+
check_assist_not_applicable(change_visibility, "trait Foo { con$0st FOO: u8 = 69; }");
253+
check_assist_not_applicable(change_visibility, "impl Foo for Bar { f$0n quox() {} }");
254+
}
255+
256+
#[test]
257+
fn not_applicable_for_items_within_fns() {
258+
check_assist_not_applicable(change_visibility, "fn foo() { f$0n inner() {} }");
259+
check_assist_not_applicable(change_visibility, "fn foo() { unsafe f$0n inner() {} }");
260+
check_assist_not_applicable(change_visibility, "fn foo() { const f$0n inner() {} }");
261+
check_assist_not_applicable(change_visibility, "fn foo() { con$0st FOO: u8 = 69; }");
262+
check_assist_not_applicable(change_visibility, "fn foo() { en$0um Foo {} }");
263+
check_assist_not_applicable(change_visibility, "fn foo() { stru$0ct Foo {} }");
264+
check_assist_not_applicable(change_visibility, "fn foo() { mo$0d foo {} }");
265+
check_assist_not_applicable(change_visibility, "fn foo() { $0use foo; }");
266+
check_assist_not_applicable(change_visibility, "fn foo() { $0type Foo = Bar<T>; }");
267+
check_assist_not_applicable(change_visibility, "fn foo() { tr$0ait Foo {} }");
268+
check_assist_not_applicable(
269+
change_visibility,
270+
"fn foo() { impl Trait for Bar { f$0n bar() {} } }",
271+
);
272+
check_assist_not_applicable(
273+
change_visibility,
274+
"fn foo() { impl Trait for Bar { con$0st FOO: u8 = 69; } }",
275+
);
276+
}
216277
}

0 commit comments

Comments
 (0)