@@ -3,6 +3,7 @@ use ra_db::FileId;
3
3
use ra_syntax:: { ast, AstNode , TextRange , TextSize } ;
4
4
5
5
use crate :: { utils:: vis_offset, AssistContext , AssistId , AssistKind , Assists } ;
6
+ use ast:: VisibilityOwner ;
6
7
7
8
// FIXME: this really should be a fix for diagnostic, rather than an assist.
8
9
@@ -48,7 +49,8 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O
48
49
return None ;
49
50
} ;
50
51
51
- let ( offset, target, target_file, target_name) = target_data_for_def ( ctx. db ( ) , def) ?;
52
+ let ( offset, current_visibility, target, target_file, target_name) =
53
+ target_data_for_def ( ctx. db ( ) , def) ?;
52
54
53
55
let missing_visibility =
54
56
if current_module. krate ( ) == target_module. krate ( ) { "pub(crate)" } else { "pub" } ;
@@ -61,8 +63,20 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext) -> O
61
63
acc. add ( AssistId ( "fix_visibility" , AssistKind :: QuickFix ) , assist_label, target, |builder| {
62
64
builder. edit_file ( target_file) ;
63
65
match ctx. config . snippet_cap {
64
- Some ( cap) => builder. insert_snippet ( cap, offset, format ! ( "$0{} " , missing_visibility) ) ,
65
- None => builder. insert ( offset, format ! ( "{} " , missing_visibility) ) ,
66
+ Some ( cap) => match current_visibility {
67
+ Some ( current_visibility) => builder. replace_snippet (
68
+ cap,
69
+ current_visibility. syntax ( ) . text_range ( ) ,
70
+ format ! ( "$0{}" , missing_visibility) ,
71
+ ) ,
72
+ None => builder. insert_snippet ( cap, offset, format ! ( "$0{} " , missing_visibility) ) ,
73
+ } ,
74
+ None => match current_visibility {
75
+ Some ( current_visibility) => {
76
+ builder. replace ( current_visibility. syntax ( ) . text_range ( ) , missing_visibility)
77
+ }
78
+ None => builder. insert ( offset, format ! ( "{} " , missing_visibility) ) ,
79
+ } ,
66
80
}
67
81
} )
68
82
}
@@ -82,14 +96,14 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) ->
82
96
let target_module = parent. module ( ctx. db ( ) ) ;
83
97
84
98
let in_file_source = record_field_def. source ( ctx. db ( ) ) ;
85
- let ( offset, target) = match in_file_source. value {
99
+ let ( offset, current_visibility , target) = match in_file_source. value {
86
100
hir:: FieldSource :: Named ( it) => {
87
101
let s = it. syntax ( ) ;
88
- ( vis_offset ( s) , s. text_range ( ) )
102
+ ( vis_offset ( s) , it . visibility ( ) , s. text_range ( ) )
89
103
}
90
104
hir:: FieldSource :: Pos ( it) => {
91
105
let s = it. syntax ( ) ;
92
- ( vis_offset ( s) , s. text_range ( ) )
106
+ ( vis_offset ( s) , it . visibility ( ) , s. text_range ( ) )
93
107
}
94
108
} ;
95
109
@@ -104,33 +118,51 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) ->
104
118
acc. add ( AssistId ( "fix_visibility" , AssistKind :: QuickFix ) , assist_label, target, |builder| {
105
119
builder. edit_file ( target_file) ;
106
120
match ctx. config . snippet_cap {
107
- Some ( cap) => builder. insert_snippet ( cap, offset, format ! ( "$0{} " , missing_visibility) ) ,
108
- None => builder. insert ( offset, format ! ( "{} " , missing_visibility) ) ,
121
+ Some ( cap) => match current_visibility {
122
+ Some ( current_visibility) => builder. replace_snippet (
123
+ cap,
124
+ dbg ! ( current_visibility. syntax( ) ) . text_range ( ) ,
125
+ format ! ( "$0{}" , missing_visibility) ,
126
+ ) ,
127
+ None => builder. insert_snippet ( cap, offset, format ! ( "$0{} " , missing_visibility) ) ,
128
+ } ,
129
+ None => match current_visibility {
130
+ Some ( current_visibility) => {
131
+ builder. replace ( current_visibility. syntax ( ) . text_range ( ) , missing_visibility)
132
+ }
133
+ None => builder. insert ( offset, format ! ( "{} " , missing_visibility) ) ,
134
+ } ,
109
135
}
110
136
} )
111
137
}
112
138
113
139
fn target_data_for_def (
114
140
db : & dyn HirDatabase ,
115
141
def : hir:: ModuleDef ,
116
- ) -> Option < ( TextSize , TextRange , FileId , Option < hir:: Name > ) > {
142
+ ) -> Option < ( TextSize , Option < ast :: Visibility > , TextRange , FileId , Option < hir:: Name > ) > {
117
143
fn offset_target_and_file_id < S , Ast > (
118
144
db : & dyn HirDatabase ,
119
145
x : S ,
120
- ) -> ( TextSize , TextRange , FileId )
146
+ ) -> ( TextSize , Option < ast :: Visibility > , TextRange , FileId )
121
147
where
122
148
S : HasSource < Ast = Ast > ,
123
- Ast : AstNode ,
149
+ Ast : AstNode + ast :: VisibilityOwner ,
124
150
{
125
151
let source = x. source ( db) ;
126
152
let in_file_syntax = source. syntax ( ) ;
127
153
let file_id = in_file_syntax. file_id ;
128
154
let syntax = in_file_syntax. value ;
129
- ( vis_offset ( syntax) , syntax. text_range ( ) , file_id. original_file ( db. upcast ( ) ) )
155
+ let current_visibility = source. value . visibility ( ) ;
156
+ (
157
+ vis_offset ( syntax) ,
158
+ current_visibility,
159
+ syntax. text_range ( ) ,
160
+ file_id. original_file ( db. upcast ( ) ) ,
161
+ )
130
162
}
131
163
132
164
let target_name;
133
- let ( offset, target, target_file) = match def {
165
+ let ( offset, current_visibility , target, target_file) = match def {
134
166
hir:: ModuleDef :: Function ( f) => {
135
167
target_name = Some ( f. name ( db) ) ;
136
168
offset_target_and_file_id ( db, f)
@@ -164,13 +196,13 @@ fn target_data_for_def(
164
196
let in_file_source = m. declaration_source ( db) ?;
165
197
let file_id = in_file_source. file_id . original_file ( db. upcast ( ) ) ;
166
198
let syntax = in_file_source. value . syntax ( ) ;
167
- ( vis_offset ( syntax) , syntax. text_range ( ) , file_id)
199
+ ( vis_offset ( syntax) , in_file_source . value . visibility ( ) , syntax. text_range ( ) , file_id)
168
200
}
169
201
// Enum variants can't be private, we can't modify builtin types
170
202
hir:: ModuleDef :: EnumVariant ( _) | hir:: ModuleDef :: BuiltinType ( _) => return None ,
171
203
} ;
172
204
173
- Some ( ( offset, target, target_file, target_name) )
205
+ Some ( ( offset, current_visibility , target, target_file, target_name) )
174
206
}
175
207
176
208
#[ cfg( test) ]
@@ -522,6 +554,34 @@ struct Bar;
522
554
)
523
555
}
524
556
557
+ #[ test]
558
+ fn replaces_pub_crate_with_pub ( ) {
559
+ check_assist (
560
+ fix_visibility,
561
+ r"
562
+ //- /main.rs crate:a deps:foo
563
+ foo::Bar<|>
564
+ //- /lib.rs crate:foo
565
+ pub(crate) struct Bar;
566
+ " ,
567
+ r"$0pub struct Bar;
568
+ " ,
569
+ ) ;
570
+ check_assist (
571
+ fix_visibility,
572
+ r"
573
+ //- /main.rs crate:a deps:foo
574
+ fn main() {
575
+ foo::Foo { <|>bar: () };
576
+ }
577
+ //- /lib.rs crate:foo
578
+ pub struct Foo { pub(crate) bar: () }
579
+ " ,
580
+ r"pub struct Foo { $0pub bar: () }
581
+ " ,
582
+ ) ;
583
+ }
584
+
525
585
#[ test]
526
586
#[ ignore]
527
587
// FIXME handle reexports properly
0 commit comments