@@ -2,9 +2,10 @@ use syntax::{
2
2
ast:: { self , HasName , HasVisibility } ,
3
3
AstNode ,
4
4
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 ,
6
7
} ,
7
- T ,
8
+ SyntaxNode , T ,
8
9
} ;
9
10
10
11
use crate :: { utils:: vis_offset, AssistContext , AssistId , AssistKind , Assists } ;
@@ -46,13 +47,11 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
46
47
47
48
let ( offset, target) = if let Some ( keyword) = item_keyword {
48
49
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) {
53
52
return None ;
54
53
}
55
- // Already have visibility, do nothing
54
+ // Already has visibility, do nothing
56
55
if parent. children ( ) . any ( |child| child. kind ( ) == VISIBILITY ) {
57
56
return None ;
58
57
}
@@ -86,6 +85,29 @@ fn add_vis(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
86
85
)
87
86
}
88
87
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
+
89
111
fn change_vis ( acc : & mut Assists , vis : ast:: Visibility ) -> Option < ( ) > {
90
112
if vis. syntax ( ) . text ( ) == "pub" {
91
113
let target = vis. syntax ( ) . text_range ( ) ;
@@ -129,6 +151,16 @@ mod tests {
129
151
check_assist ( change_visibility, "unsafe f$0n foo() {}" , "pub(crate) unsafe fn foo() {}" ) ;
130
152
check_assist ( change_visibility, "$0macro foo() {}" , "pub(crate) macro foo() {}" ) ;
131
153
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
+ ) ;
132
164
}
133
165
134
166
#[ test]
@@ -213,4 +245,33 @@ mod tests {
213
245
check_assist_target ( change_visibility, "pub(crate)$0 fn foo() {}" , "pub(crate)" ) ;
214
246
check_assist_target ( change_visibility, "struct S { $0field: u32 }" , "field" ) ;
215
247
}
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
+ }
216
277
}
0 commit comments