@@ -8,10 +8,7 @@ use itertools::Itertools;
88use syntax:: ast:: edit_in_place:: Removable ;
99use syntax:: ast:: { self , make, AstNode , HasName , MatchArmList , MatchExpr , Pat } ;
1010
11- use crate :: {
12- utils:: { self , render_snippet, Cursor } ,
13- AssistContext , AssistId , AssistKind , Assists ,
14- } ;
11+ use crate :: { utils, AssistContext , AssistId , AssistKind , Assists } ;
1512
1613// Assist: add_missing_match_arms
1714//
@@ -202,7 +199,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
202199 AssistId ( "add_missing_match_arms" , AssistKind :: QuickFix ) ,
203200 "Fill match arms" ,
204201 target_range,
205- |builder | {
202+ |edit | {
206203 let new_match_arm_list = match_arm_list. clone_for_update ( ) ;
207204
208205 // 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<'_>)
252249 new_match_arm_list. add_arm ( arm) ;
253250 }
254251
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) ,
270256 }
271- _ => builder. replace ( old_range, new_match_arm_list. to_string ( ) ) ,
272257 }
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 ( ) ) ;
273285 } ,
274286 )
275287}
0 commit comments