11use hir:: { db:: HirDatabase , HasSource , HasVisibility , ModuleDef , PathResolution , ScopeDef } ;
22use ide_db:: base_db:: FileId ;
33use syntax:: {
4- ast:: { self , HasVisibility as _} ,
5- AstNode , TextRange , TextSize ,
4+ ast:: { self , edit_in_place :: HasVisibilityEdit , make , HasVisibility as _} ,
5+ AstNode , TextRange ,
66} ;
77
8- use crate :: { utils :: vis_offset , AssistContext , AssistId , AssistKind , Assists } ;
8+ use crate :: { AssistContext , AssistId , AssistKind , Assists } ;
99
1010// FIXME: this really should be a fix for diagnostic, rather than an assist.
1111
@@ -58,11 +58,13 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
5858 return None ;
5959 } ;
6060
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) ?;
6362
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+ } ;
6668
6769 let assist_label = match target_name {
6870 None => format ! ( "Change visibility to {missing_visibility}" ) ,
@@ -71,23 +73,14 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
7173 }
7274 } ;
7375
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) ;
9184 }
9285 } )
9386}
@@ -107,19 +100,22 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
107100 let target_module = parent. module ( ctx. db ( ) ) ;
108101
109102 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 {
111104 hir:: FieldSource :: Named ( it) => {
112105 let s = it. syntax ( ) ;
113- ( vis_offset ( s ) , it . visibility ( ) , s. text_range ( ) )
106+ ( ast :: AnyHasVisibility :: cast ( s . clone ( ) ) . unwrap ( ) , s. text_range ( ) )
114107 }
115108 hir:: FieldSource :: Pos ( it) => {
116109 let s = it. syntax ( ) ;
117- ( vis_offset ( s ) , it . visibility ( ) , s. text_range ( ) )
110+ ( ast :: AnyHasVisibility :: cast ( s . clone ( ) ) . unwrap ( ) , s. text_range ( ) )
118111 }
119112 } ;
120113
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+ } ;
123119 let target_file = in_file_source. file_id . original_file ( ctx. db ( ) ) ;
124120
125121 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<'_>
129125 target_name. display( ctx. db( ) )
130126 ) ;
131127
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) ;
149136 }
150137 } )
151138}
152139
153140fn target_data_for_def (
154141 db : & dyn HirDatabase ,
155142 def : hir:: ModuleDef ,
156- ) -> Option < ( TextSize , Option < ast:: Visibility > , TextRange , FileId , Option < hir:: Name > ) > {
143+ ) -> Option < ( ast:: AnyHasVisibility , TextRange , FileId , Option < hir:: Name > ) > {
157144 fn offset_target_and_file_id < S , Ast > (
158145 db : & dyn HirDatabase ,
159146 x : S ,
160- ) -> Option < ( TextSize , Option < ast:: Visibility > , TextRange , FileId ) >
147+ ) -> Option < ( ast:: AnyHasVisibility , TextRange , FileId ) >
161148 where
162149 S : HasSource < Ast = Ast > ,
163150 Ast : AstNode + ast:: HasVisibility ,
@@ -166,17 +153,15 @@ fn target_data_for_def(
166153 let in_file_syntax = source. syntax ( ) ;
167154 let file_id = in_file_syntax. file_id ;
168155 let syntax = in_file_syntax. value ;
169- let current_visibility = source. value . visibility ( ) ;
170156 Some ( (
171- vis_offset ( syntax) ,
172- current_visibility,
157+ ast:: AnyHasVisibility :: cast ( syntax. clone ( ) ) . unwrap ( ) ,
173158 syntax. text_range ( ) ,
174159 file_id. original_file ( db. upcast ( ) ) ,
175160 ) )
176161 }
177162
178163 let target_name;
179- let ( offset, current_visibility , target, target_file) = match def {
164+ let ( offset, target, target_file) = match def {
180165 hir:: ModuleDef :: Function ( f) => {
181166 target_name = Some ( f. name ( db) ) ;
182167 offset_target_and_file_id ( db, f) ?
@@ -214,15 +199,15 @@ fn target_data_for_def(
214199 let in_file_source = m. declaration_source ( db) ?;
215200 let file_id = in_file_source. file_id . original_file ( db. upcast ( ) ) ;
216201 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)
218203 }
219204 // FIXME
220205 hir:: ModuleDef :: Macro ( _) => return None ,
221206 // Enum variants can't be private, we can't modify builtin types
222207 hir:: ModuleDef :: Variant ( _) | hir:: ModuleDef :: BuiltinType ( _) => return None ,
223208 } ;
224209
225- Some ( ( offset, current_visibility , target, target_file, target_name) )
210+ Some ( ( offset, target, target_file, target_name) )
226211}
227212
228213#[ cfg( test) ]
0 commit comments