@@ -8,10 +8,7 @@ use itertools::Itertools;
8
8
use syntax:: ast:: edit_in_place:: Removable ;
9
9
use syntax:: ast:: { self , make, AstNode , HasName , MatchArmList , MatchExpr , Pat } ;
10
10
11
- use crate :: {
12
- utils:: { self , render_snippet, Cursor } ,
13
- AssistContext , AssistId , AssistKind , Assists ,
14
- } ;
11
+ use crate :: { utils, AssistContext , AssistId , AssistKind , Assists } ;
15
12
16
13
// Assist: add_missing_match_arms
17
14
//
@@ -202,7 +199,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
202
199
AssistId ( "add_missing_match_arms" , AssistKind :: QuickFix ) ,
203
200
"Fill match arms" ,
204
201
target_range,
205
- |builder | {
202
+ |edit | {
206
203
let new_match_arm_list = match_arm_list. clone_for_update ( ) ;
207
204
208
205
// having any hidden variants means that we need a catch-all arm
@@ -252,24 +249,39 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
252
249
new_match_arm_list. add_arm ( arm) ;
253
250
}
254
251
255
- let old_range = ctx. sema . original_range ( match_arm_list. syntax ( ) ) . range ;
256
- match ( first_new_arm, ctx. config . snippet_cap ) {
257
- ( Some ( first_new_arm) , Some ( cap) ) => {
258
- let extend_lifetime;
259
- let cursor =
260
- match first_new_arm. syntax ( ) . descendants ( ) . find_map ( ast:: WildcardPat :: cast)
261
- {
262
- Some ( it) => {
263
- extend_lifetime = it. syntax ( ) . clone ( ) ;
264
- Cursor :: Replace ( & extend_lifetime)
265
- }
266
- None => Cursor :: Before ( first_new_arm. syntax ( ) ) ,
267
- } ;
268
- let snippet = render_snippet ( cap, new_match_arm_list. syntax ( ) , cursor) ;
269
- builder. replace_snippet ( cap, old_range, snippet) ;
252
+ if let ( Some ( first_new_arm) , Some ( cap) ) = ( first_new_arm, ctx. config . snippet_cap ) {
253
+ match first_new_arm. syntax ( ) . descendants ( ) . find_map ( ast:: WildcardPat :: cast) {
254
+ Some ( it) => edit. add_placeholder_snippet ( cap, it) ,
255
+ None => edit. add_tabstop_before ( cap, first_new_arm) ,
270
256
}
271
- _ => builder. replace ( old_range, new_match_arm_list. to_string ( ) ) ,
272
257
}
258
+
259
+ // FIXME: Hack for mutable syntax trees not having great support for macros
260
+ // Just replace the element that the original range came from
261
+ let old_place = {
262
+ // Find the original element
263
+ let old_file_range = ctx. sema . original_range ( match_arm_list. syntax ( ) ) ;
264
+ let file = ctx. sema . parse ( old_file_range. file_id ) ;
265
+ let old_place = file. syntax ( ) . covering_element ( old_file_range. range ) ;
266
+
267
+ // Make `old_place` mut
268
+ match old_place {
269
+ syntax:: SyntaxElement :: Node ( it) => {
270
+ syntax:: SyntaxElement :: from ( edit. make_syntax_mut ( it) )
271
+ }
272
+ syntax:: SyntaxElement :: Token ( it) => {
273
+ // Don't have a way to make tokens mut, so instead make the parent mut
274
+ // and find the token again
275
+ let parent = edit. make_syntax_mut ( it. parent ( ) . unwrap ( ) ) ;
276
+ let mut_token =
277
+ parent. covering_element ( it. text_range ( ) ) . into_token ( ) . unwrap ( ) ;
278
+
279
+ syntax:: SyntaxElement :: from ( mut_token)
280
+ }
281
+ }
282
+ } ;
283
+
284
+ syntax:: ted:: replace ( old_place, new_match_arm_list. syntax ( ) ) ;
273
285
} ,
274
286
)
275
287
}
0 commit comments