1
1
use hir:: { db:: HirDatabase , HasSource , HasVisibility , ModuleDef , PathResolution , ScopeDef } ;
2
2
use ide_db:: base_db:: FileId ;
3
3
use syntax:: {
4
- ast:: { self , HasVisibility as _} ,
5
- AstNode , TextRange , TextSize ,
4
+ ast:: { self , edit_in_place :: HasVisibilityEdit , make , HasVisibility as _} ,
5
+ AstNode , TextRange ,
6
6
} ;
7
7
8
- use crate :: { utils :: vis_offset , AssistContext , AssistId , AssistKind , Assists } ;
8
+ use crate :: { AssistContext , AssistId , AssistKind , Assists } ;
9
9
10
10
// FIXME: this really should be a fix for diagnostic, rather than an assist.
11
11
@@ -58,11 +58,13 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
58
58
return None ;
59
59
} ;
60
60
61
- let ( offset, current_visibility, target, target_file, target_name) =
62
- target_data_for_def ( ctx. db ( ) , def) ?;
61
+ let ( vis_owner, target, target_file, target_name) = target_data_for_def ( ctx. db ( ) , def) ?;
63
62
64
- let missing_visibility =
65
- if current_module. krate ( ) == target_module. krate ( ) { "pub(crate)" } else { "pub" } ;
63
+ let missing_visibility = if current_module. krate ( ) == target_module. krate ( ) {
64
+ make:: visibility_pub_crate ( )
65
+ } else {
66
+ make:: visibility_pub ( )
67
+ } ;
66
68
67
69
let assist_label = match target_name {
68
70
None => format ! ( "Change visibility to {missing_visibility}" ) ,
@@ -71,23 +73,14 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
71
73
}
72
74
} ;
73
75
74
- acc. add ( AssistId ( "fix_visibility" , AssistKind :: QuickFix ) , assist_label, target, |builder| {
75
- builder. edit_file ( target_file) ;
76
- match ctx. config . snippet_cap {
77
- Some ( cap) => match current_visibility {
78
- Some ( current_visibility) => builder. replace_snippet (
79
- cap,
80
- current_visibility. syntax ( ) . text_range ( ) ,
81
- format ! ( "$0{missing_visibility}" ) ,
82
- ) ,
83
- None => builder. insert_snippet ( cap, offset, format ! ( "$0{missing_visibility} " ) ) ,
84
- } ,
85
- None => match current_visibility {
86
- Some ( current_visibility) => {
87
- builder. replace ( current_visibility. syntax ( ) . text_range ( ) , missing_visibility)
88
- }
89
- None => builder. insert ( offset, format ! ( "{missing_visibility} " ) ) ,
90
- } ,
76
+ acc. add ( AssistId ( "fix_visibility" , AssistKind :: QuickFix ) , assist_label, target, |edit| {
77
+ edit. edit_file ( target_file) ;
78
+
79
+ let vis_owner = edit. make_mut ( vis_owner) ;
80
+ vis_owner. set_visibility ( missing_visibility. clone_for_update ( ) ) ;
81
+
82
+ if let Some ( ( cap, vis) ) = ctx. config . snippet_cap . zip ( vis_owner. visibility ( ) ) {
83
+ edit. add_tabstop_before ( cap, vis) ;
91
84
}
92
85
} )
93
86
}
@@ -107,19 +100,22 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
107
100
let target_module = parent. module ( ctx. db ( ) ) ;
108
101
109
102
let in_file_source = record_field_def. source ( ctx. db ( ) ) ?;
110
- let ( offset , current_visibility , target ) = match in_file_source. value {
103
+ let ( vis_owner , target ) : ( ast :: AnyHasVisibility , TextRange ) = match in_file_source. value {
111
104
hir:: FieldSource :: Named ( it) => {
112
105
let s = it. syntax ( ) ;
113
- ( vis_offset ( s ) , it . visibility ( ) , s. text_range ( ) )
106
+ ( ast :: AnyHasVisibility :: cast ( s . clone ( ) ) . unwrap ( ) , s. text_range ( ) )
114
107
}
115
108
hir:: FieldSource :: Pos ( it) => {
116
109
let s = it. syntax ( ) ;
117
- ( vis_offset ( s ) , it . visibility ( ) , s. text_range ( ) )
110
+ ( ast :: AnyHasVisibility :: cast ( s . clone ( ) ) . unwrap ( ) , s. text_range ( ) )
118
111
}
119
112
} ;
120
113
121
- let missing_visibility =
122
- if current_module. krate ( ) == target_module. krate ( ) { "pub(crate)" } else { "pub" } ;
114
+ let missing_visibility = if current_module. krate ( ) == target_module. krate ( ) {
115
+ make:: visibility_pub_crate ( )
116
+ } else {
117
+ make:: visibility_pub ( )
118
+ } ;
123
119
let target_file = in_file_source. file_id . original_file ( ctx. db ( ) ) ;
124
120
125
121
let target_name = record_field_def. name ( ctx. db ( ) ) ;
@@ -129,35 +125,26 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
129
125
target_name. display( ctx. db( ) )
130
126
) ;
131
127
132
- acc. add ( AssistId ( "fix_visibility" , AssistKind :: QuickFix ) , assist_label, target, |builder| {
133
- builder. edit_file ( target_file) ;
134
- match ctx. config . snippet_cap {
135
- Some ( cap) => match current_visibility {
136
- Some ( current_visibility) => builder. replace_snippet (
137
- cap,
138
- current_visibility. syntax ( ) . text_range ( ) ,
139
- format ! ( "$0{missing_visibility}" ) ,
140
- ) ,
141
- None => builder. insert_snippet ( cap, offset, format ! ( "$0{missing_visibility} " ) ) ,
142
- } ,
143
- None => match current_visibility {
144
- Some ( current_visibility) => {
145
- builder. replace ( current_visibility. syntax ( ) . text_range ( ) , missing_visibility)
146
- }
147
- None => builder. insert ( offset, format ! ( "{missing_visibility} " ) ) ,
148
- } ,
128
+ acc. add ( AssistId ( "fix_visibility" , AssistKind :: QuickFix ) , assist_label, target, |edit| {
129
+ edit. edit_file ( target_file) ;
130
+
131
+ let vis_owner = edit. make_mut ( vis_owner) ;
132
+ vis_owner. set_visibility ( missing_visibility. clone_for_update ( ) ) ;
133
+
134
+ if let Some ( ( cap, vis) ) = ctx. config . snippet_cap . zip ( vis_owner. visibility ( ) ) {
135
+ edit. add_tabstop_before ( cap, vis) ;
149
136
}
150
137
} )
151
138
}
152
139
153
140
fn target_data_for_def (
154
141
db : & dyn HirDatabase ,
155
142
def : hir:: ModuleDef ,
156
- ) -> Option < ( TextSize , Option < ast:: Visibility > , TextRange , FileId , Option < hir:: Name > ) > {
143
+ ) -> Option < ( ast:: AnyHasVisibility , TextRange , FileId , Option < hir:: Name > ) > {
157
144
fn offset_target_and_file_id < S , Ast > (
158
145
db : & dyn HirDatabase ,
159
146
x : S ,
160
- ) -> Option < ( TextSize , Option < ast:: Visibility > , TextRange , FileId ) >
147
+ ) -> Option < ( ast:: AnyHasVisibility , TextRange , FileId ) >
161
148
where
162
149
S : HasSource < Ast = Ast > ,
163
150
Ast : AstNode + ast:: HasVisibility ,
@@ -166,17 +153,15 @@ fn target_data_for_def(
166
153
let in_file_syntax = source. syntax ( ) ;
167
154
let file_id = in_file_syntax. file_id ;
168
155
let syntax = in_file_syntax. value ;
169
- let current_visibility = source. value . visibility ( ) ;
170
156
Some ( (
171
- vis_offset ( syntax) ,
172
- current_visibility,
157
+ ast:: AnyHasVisibility :: cast ( syntax. clone ( ) ) . unwrap ( ) ,
173
158
syntax. text_range ( ) ,
174
159
file_id. original_file ( db. upcast ( ) ) ,
175
160
) )
176
161
}
177
162
178
163
let target_name;
179
- let ( offset, current_visibility , target, target_file) = match def {
164
+ let ( offset, target, target_file) = match def {
180
165
hir:: ModuleDef :: Function ( f) => {
181
166
target_name = Some ( f. name ( db) ) ;
182
167
offset_target_and_file_id ( db, f) ?
@@ -214,15 +199,15 @@ fn target_data_for_def(
214
199
let in_file_source = m. declaration_source ( db) ?;
215
200
let file_id = in_file_source. file_id . original_file ( db. upcast ( ) ) ;
216
201
let syntax = in_file_source. value . syntax ( ) ;
217
- ( vis_offset ( syntax) , in_file_source . value . visibility ( ) , syntax. text_range ( ) , file_id)
202
+ ( ast :: AnyHasVisibility :: cast ( syntax. clone ( ) ) . unwrap ( ) , syntax. text_range ( ) , file_id)
218
203
}
219
204
// FIXME
220
205
hir:: ModuleDef :: Macro ( _) => return None ,
221
206
// Enum variants can't be private, we can't modify builtin types
222
207
hir:: ModuleDef :: Variant ( _) | hir:: ModuleDef :: BuiltinType ( _) => return None ,
223
208
} ;
224
209
225
- Some ( ( offset, current_visibility , target, target_file, target_name) )
210
+ Some ( ( offset, target, target_file, target_name) )
226
211
}
227
212
228
213
#[ cfg( test) ]
0 commit comments