@@ -72,12 +72,6 @@ fn if_expr_to_guarded_return(
7272 ctx : & AssistContext < ' _ > ,
7373) -> Option < ( ) > {
7474 let make = SyntaxFactory :: without_mappings ( ) ;
75- let else_block = match if_expr. else_branch ( ) {
76- Some ( ast:: ElseBranch :: Block ( block_expr) ) => Some ( block_expr) ,
77- Some ( _) => return None ,
78- _ => None ,
79- } ;
80-
8175 let cond = if_expr. condition ( ) ?;
8276
8377 let if_token_range = if_expr. if_token ( ) ?. text_range ( ) ;
@@ -102,7 +96,7 @@ fn if_expr_to_guarded_return(
10296 }
10397
10498 let container = container_of ( & parent_block) ?;
105- let else_block = ElseBlock :: new ( & ctx. sema , else_block , & container) ?;
99+ let else_block = ElseBlock :: new ( & ctx. sema , if_expr . else_branch ( ) , & container) ?;
106100
107101 if parent_block. tail_expr ( ) != Some ( if_expr. clone ( ) . into ( ) )
108102 && !( else_block. is_never_block
@@ -237,37 +231,47 @@ fn container_of(block: &ast::BlockExpr) -> Option<SyntaxNode> {
237231}
238232
239233struct ElseBlock < ' db > {
240- exist_else_block : Option < ast:: BlockExpr > ,
234+ exist_else_branch : Option < ast:: ElseBranch > ,
241235 is_never_block : bool ,
242236 kind : EarlyKind < ' db > ,
243237}
244238
245239impl < ' db > ElseBlock < ' db > {
246240 fn new (
247241 sema : & Semantics < ' db , RootDatabase > ,
248- exist_else_block : Option < ast:: BlockExpr > ,
242+ exist_else_branch : Option < ast:: ElseBranch > ,
249243 parent_container : & SyntaxNode ,
250244 ) -> Option < Self > {
251- let is_never_block = exist_else_block. as_ref ( ) . is_some_and ( |it| is_never_block ( sema, it) ) ;
245+ let is_never_block =
246+ exist_else_branch. as_ref ( ) . is_some_and ( |it| is_never_else_branch ( sema, it) ) ;
252247 let kind = EarlyKind :: from_node ( parent_container, sema) ?;
253248
254- Some ( Self { exist_else_block, is_never_block, kind } )
249+ Some ( Self { exist_else_branch, is_never_block, kind } )
250+ }
251+
252+ fn make_else_block_from_exist_branch ( & self , make : & SyntaxFactory ) -> Option < ast:: BlockExpr > {
253+ match self . exist_else_branch . as_ref ( ) ? {
254+ ast:: ElseBranch :: Block ( block_expr) => Some ( block_expr. reset_indent ( ) ) ,
255+ ast:: ElseBranch :: IfExpr ( if_expr) => {
256+ Some ( make. block_expr ( None , Some ( if_expr. reset_indent ( ) . indent ( 1 . into ( ) ) . into ( ) ) ) )
257+ }
258+ }
255259 }
256260
257261 fn make_early_block (
258262 self ,
259263 sema : & Semantics < ' _ , RootDatabase > ,
260264 make : & SyntaxFactory ,
261265 ) -> ast:: BlockExpr {
262- let Some ( block_expr) = self . exist_else_block else {
266+ let Some ( block_expr) = self . make_else_block_from_exist_branch ( make ) else {
263267 return make. tail_only_block_expr ( self . kind . make_early_expr ( sema, make, None ) ) ;
264268 } ;
265269
266270 if self . is_never_block {
267- return block_expr. reset_indent ( ) ;
271+ return block_expr;
268272 }
269273
270- let ( editor, block_expr) = SyntaxEditor :: with_ast_node ( & block_expr. reset_indent ( ) ) ;
274+ let ( editor, block_expr) = SyntaxEditor :: with_ast_node ( & block_expr) ;
271275 let make = editor. make ( ) ;
272276
273277 let last_stmt = block_expr. statements ( ) . last ( ) . map ( |it| it. syntax ( ) . clone ( ) ) ;
@@ -284,8 +288,8 @@ impl<'db> ElseBlock<'db> {
284288 editor. replace ( tail_expr. syntax ( ) , early_expr. syntax ( ) ) ;
285289 } else {
286290 let last_stmt = match block_expr. tail_expr ( ) {
287- Some ( expr) => make. expr_stmt ( expr) . syntax ( ) . clone ( ) ,
288- None => last_element. clone ( ) ,
291+ Some ( expr) if !expr . is_block_like ( ) => make. expr_stmt ( expr) . syntax ( ) . clone ( ) ,
292+ _ => last_element. clone ( ) ,
289293 } ;
290294 let whitespace =
291295 make. whitespace ( & whitespace. map_or ( String :: new ( ) , |it| it. to_string ( ) ) ) ;
@@ -401,6 +405,27 @@ fn is_early_block(then_block: &ast::StmtList) -> bool {
401405 || then_block. statements ( ) . filter_map ( into_expr) . any ( is_early_expr)
402406}
403407
408+ fn is_never_else_branch ( sema : & Semantics < ' _ , RootDatabase > , it : & ast:: ElseBranch ) -> bool {
409+ match it {
410+ ast:: ElseBranch :: Block ( block_expr) => is_never_block ( sema, block_expr) ,
411+ ast:: ElseBranch :: IfExpr ( if_expr) => {
412+ let mut if_exprs =
413+ std:: iter:: successors ( Some ( if_expr. clone ( ) ) , |it| match it. else_branch ( ) ? {
414+ ast:: ElseBranch :: Block ( _) => None ,
415+ ast:: ElseBranch :: IfExpr ( if_expr) => Some ( if_expr) ,
416+ } ) ;
417+ if_exprs. all ( |it| {
418+ let else_is_never = match it. else_branch ( ) {
419+ None => false ,
420+ Some ( ast:: ElseBranch :: IfExpr ( _) ) => true ,
421+ Some ( ast:: ElseBranch :: Block ( block) ) => is_never_block ( sema, & block) ,
422+ } ;
423+ else_is_never && it. then_branch ( ) . is_some_and ( |it| is_never_block ( sema, & it) )
424+ } )
425+ }
426+ }
427+ }
428+
404429#[ cfg( test) ]
405430mod tests {
406431 use crate :: tests:: { check_assist, check_assist_not_applicable} ;
@@ -1024,6 +1049,42 @@ fn main() {
10241049 ) ;
10251050 }
10261051
1052+ #[ test]
1053+ fn convert_inside_loop_with_else_if ( ) {
1054+ check_assist (
1055+ convert_to_guarded_return,
1056+ r#"
1057+ fn main() {
1058+ loop {
1059+ if$0 guard() {
1060+ foo();
1061+ bar();
1062+ } else if cond() {
1063+ break;
1064+ } else {
1065+ return
1066+ }
1067+ }
1068+ }
1069+ "# ,
1070+ r#"
1071+ fn main() {
1072+ loop {
1073+ if !guard() {
1074+ if cond() {
1075+ break;
1076+ } else {
1077+ return
1078+ }
1079+ }
1080+ foo();
1081+ bar();
1082+ }
1083+ }
1084+ "# ,
1085+ ) ;
1086+ }
1087+
10271088 #[ test]
10281089 fn convert_let_inside_loop ( ) {
10291090 check_assist (
@@ -1055,6 +1116,7 @@ fn main() {
10551116 check_assist (
10561117 convert_to_guarded_return,
10571118 r#"
1119+ //- minicore: iterator
10581120fn main() {
10591121 for n in ns {
10601122 if$0 let Some(n) = n {
@@ -1107,6 +1169,7 @@ fn main() {
11071169 check_assist (
11081170 convert_to_guarded_return,
11091171 r#"
1172+ //- minicore: iterator
11101173fn main() {
11111174 for n in ns {
11121175 if$0 let Some(n) = n {
@@ -1133,6 +1196,109 @@ fn main() {
11331196 ) ;
11341197 }
11351198
1199+ #[ test]
1200+ fn convert_let_inside_for_with_else_if ( ) {
1201+ check_assist (
1202+ convert_to_guarded_return,
1203+ r#"
1204+ //- minicore: iterator
1205+ fn main() {
1206+ for n in ns {
1207+ if$0 let Some(n) = n {
1208+ foo(n);
1209+ bar();
1210+ } else if cond() {
1211+ return
1212+ } else {
1213+ baz()
1214+ }
1215+ }
1216+ }
1217+ "# ,
1218+ r#"
1219+ fn main() {
1220+ for n in ns {
1221+ let Some(n) = n else {
1222+ if cond() {
1223+ return
1224+ } else {
1225+ baz()
1226+ }
1227+ continue
1228+ };
1229+ foo(n);
1230+ bar();
1231+ }
1232+ }
1233+ "# ,
1234+ ) ;
1235+
1236+ check_assist (
1237+ convert_to_guarded_return,
1238+ r#"
1239+ //- minicore: iterator
1240+ fn main() {
1241+ for n in ns {
1242+ if$0 let Some(n) = n {
1243+ foo(n);
1244+ bar();
1245+ } else if cond() {
1246+ return
1247+ }
1248+ }
1249+ }
1250+ "# ,
1251+ r#"
1252+ fn main() {
1253+ for n in ns {
1254+ let Some(n) = n else {
1255+ if cond() {
1256+ return
1257+ }
1258+ continue
1259+ };
1260+ foo(n);
1261+ bar();
1262+ }
1263+ }
1264+ "# ,
1265+ ) ;
1266+
1267+ check_assist (
1268+ convert_to_guarded_return,
1269+ r#"
1270+ //- minicore: iterator
1271+ fn main() {
1272+ for n in ns {
1273+ if$0 let Some(n) = n {
1274+ foo(n);
1275+ bar();
1276+ } else if cond() {
1277+ return
1278+ } else {
1279+ break
1280+ }
1281+ }
1282+ }
1283+ "# ,
1284+ r#"
1285+ fn main() {
1286+ for n in ns {
1287+ let Some(n) = n else {
1288+ if cond() {
1289+ return
1290+ } else {
1291+ break
1292+ }
1293+ };
1294+ foo(n);
1295+ bar();
1296+ }
1297+ }
1298+ "# ,
1299+ ) ;
1300+ }
1301+
11361302 #[ test]
11371303 fn convert_let_stmt_inside_fn ( ) {
11381304 check_assist (
@@ -1415,7 +1581,7 @@ fn main() {
14151581 }
14161582
14171583 #[ test]
1418- fn ignore_else_if ( ) {
1584+ fn ignore_on_else_if ( ) {
14191585 check_assist_not_applicable (
14201586 convert_to_guarded_return,
14211587 r#"
0 commit comments