@@ -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
1011use 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+
89111fn 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