1+ use itertools:: Itertools ;
12use syntax:: {
23 SyntaxKind :: WHITESPACE ,
3- ast:: { AstNode , BlockExpr , ElseBranch , Expr , IfExpr , MatchArm , Pat , edit:: AstNodeEdit , make} ,
4+ ast:: {
5+ AstNode , BlockExpr , ElseBranch , Expr , IfExpr , MatchArm , Pat , edit:: AstNodeEdit , make,
6+ syntax_factory:: SyntaxFactory ,
7+ } ,
8+ syntax_editor:: Element ,
49} ;
510
611use crate :: { AssistContext , AssistId , Assists } ;
@@ -131,8 +136,10 @@ pub(crate) fn move_arm_cond_to_match_guard(
131136 AssistId :: refactor_rewrite ( "move_arm_cond_to_match_guard" ) ,
132137 "Move condition to match guard" ,
133138 replace_node. text_range ( ) ,
134- |edit| {
135- edit. delete ( match_arm. syntax ( ) . text_range ( ) ) ;
139+ |builder| {
140+ let make = SyntaxFactory :: without_mappings ( ) ;
141+ let mut replace_arms = vec ! [ ] ;
142+
136143 // Dedent if if_expr is in a BlockExpr
137144 let dedent = if needs_dedent {
138145 cov_mark:: hit!( move_guard_ifelse_in_block) ;
@@ -141,47 +148,30 @@ pub(crate) fn move_arm_cond_to_match_guard(
141148 cov_mark:: hit!( move_guard_ifelse_else_block) ;
142149 0
143150 } ;
144- let then_arm_end = match_arm. syntax ( ) . text_range ( ) . end ( ) ;
145151 let indent_level = match_arm. indent_level ( ) ;
146- let spaces = indent_level;
147152
148- let mut first = true ;
149153 for ( cond, block) in conds_blocks {
150- if !first {
151- edit. insert ( then_arm_end, format ! ( "\n {spaces}" ) ) ;
152- } else {
153- first = false ;
154- }
155- let guard = format ! ( "{match_pat} if {cond} => " ) ;
156- edit. insert ( then_arm_end, guard) ;
157154 let only_expr = block. statements ( ) . next ( ) . is_none ( ) ;
158- match & block. tail_expr ( ) {
159- Some ( then_expr) if only_expr => {
160- edit. insert ( then_arm_end, then_expr. syntax ( ) . text ( ) ) ;
161- edit. insert ( then_arm_end, "," ) ;
162- }
163- _ => {
164- let to_insert = block. dedent ( dedent. into ( ) ) . syntax ( ) . text ( ) ;
165- edit. insert ( then_arm_end, to_insert)
166- }
167- }
155+ let expr = match block. tail_expr ( ) {
156+ Some ( then_expr) if only_expr => then_expr,
157+ _ => block. dedent ( dedent. into ( ) ) . into ( ) ,
158+ } ;
159+ let guard = make. match_guard ( cond) ;
160+ let new_arm = make. match_arm ( match_pat. clone ( ) , Some ( guard) , expr) ;
161+ replace_arms. push ( new_arm) ;
168162 }
169- if let Some ( e ) = tail {
163+ if let Some ( block ) = tail {
170164 cov_mark:: hit!( move_guard_ifelse_else_tail) ;
171- let guard = format ! ( "\n {spaces}{match_pat} => " ) ;
172- edit. insert ( then_arm_end, guard) ;
173- let only_expr = e. statements ( ) . next ( ) . is_none ( ) ;
174- match & e. tail_expr ( ) {
165+ let only_expr = block. statements ( ) . next ( ) . is_none ( ) ;
166+ let expr = match block. tail_expr ( ) {
175167 Some ( expr) if only_expr => {
176168 cov_mark:: hit!( move_guard_ifelse_expr_only) ;
177- edit. insert ( then_arm_end, expr. syntax ( ) . text ( ) ) ;
178- edit. insert ( then_arm_end, "," ) ;
179- }
180- _ => {
181- let to_insert = e. dedent ( dedent. into ( ) ) . syntax ( ) . text ( ) ;
182- edit. insert ( then_arm_end, to_insert)
169+ expr
183170 }
184- }
171+ _ => block. dedent ( dedent. into ( ) ) . into ( ) ,
172+ } ;
173+ let new_arm = make. match_arm ( match_pat, None , expr) ;
174+ replace_arms. push ( new_arm) ;
185175 } else {
186176 // There's no else branch. Add a pattern without guard, unless the following match
187177 // arm is `_ => ...`
@@ -193,9 +183,21 @@ pub(crate) fn move_arm_cond_to_match_guard(
193183 {
194184 cov_mark:: hit!( move_guard_ifelse_has_wildcard) ;
195185 }
196- _ => edit. insert ( then_arm_end, format ! ( "\n {spaces}{match_pat} => {{}}" ) ) ,
186+ _ => {
187+ let block_expr = make. expr_empty_block ( ) . into ( ) ;
188+ replace_arms. push ( make. match_arm ( match_pat, None , block_expr) ) ;
189+ }
197190 }
198191 }
192+
193+ let mut edit = builder. make_editor ( match_arm. syntax ( ) ) ;
194+
195+ let newline = make. whitespace ( & format ! ( "\n {indent_level}" ) ) ;
196+ let replace_arms = replace_arms. iter ( ) . map ( |it| it. syntax ( ) . syntax_element ( ) ) ;
197+ let replace_arms = Itertools :: intersperse ( replace_arms, newline. syntax_element ( ) ) ;
198+ edit. replace_with_many ( match_arm. syntax ( ) , replace_arms. collect ( ) ) ;
199+
200+ builder. add_file_edits ( ctx. vfs_file_id ( ) , edit) ;
199201 } ,
200202 )
201203}
0 commit comments