]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/wrap_return_type_in_result.rs
Merge #9242
[rust.git] / crates / ide_assists / src / handlers / wrap_return_type_in_result.rs
1 use std::iter;
2
3 use syntax::{
4     ast::{self, make, BlockExpr, Expr, LoopBodyOwner},
5     match_ast, AstNode, SyntaxNode,
6 };
7
8 use crate::{AssistContext, AssistId, AssistKind, Assists};
9
10 // Assist: wrap_return_type_in_result
11 //
12 // Wrap the function's return type into Result.
13 //
14 // ```
15 // fn foo() -> i32$0 { 42i32 }
16 // ```
17 // ->
18 // ```
19 // fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
20 // ```
21 pub(crate) fn wrap_return_type_in_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
22     let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
23     let parent = ret_type.syntax().parent()?;
24     let block_expr = match_ast! {
25         match parent {
26             ast::Fn(func) => func.body()?,
27             ast::ClosureExpr(closure) => match closure.body()? {
28                 Expr::BlockExpr(block) => block,
29                 // closures require a block when a return type is specified
30                 _ => return None,
31             },
32             _ => return None,
33         }
34     };
35
36     let type_ref = &ret_type.ty()?;
37     let ret_type_str = type_ref.syntax().text().to_string();
38     let first_part_ret_type = ret_type_str.splitn(2, '<').next();
39     if let Some(ret_type_first_part) = first_part_ret_type {
40         if ret_type_first_part.ends_with("Result") {
41             cov_mark::hit!(wrap_return_type_in_result_simple_return_type_already_result);
42             return None;
43         }
44     }
45
46     acc.add(
47         AssistId("wrap_return_type_in_result", AssistKind::RefactorRewrite),
48         "Wrap return type in Result",
49         type_ref.syntax().text_range(),
50         |builder| {
51             let mut tail_return_expr_collector = TailReturnCollector::new();
52             tail_return_expr_collector.collect_jump_exprs(&block_expr, false);
53             tail_return_expr_collector.collect_tail_exprs(&block_expr);
54
55             for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap {
56                 let ok_wrapped = make::expr_call(
57                     make::expr_path(make::ext::ident_path("Ok")),
58                     make::arg_list(iter::once(ret_expr_arg.clone())),
59                 );
60                 builder.replace_ast(ret_expr_arg, ok_wrapped);
61             }
62
63             match ctx.config.snippet_cap {
64                 Some(cap) => {
65                     let snippet = format!("Result<{}, ${{0:_}}>", type_ref);
66                     builder.replace_snippet(cap, type_ref.syntax().text_range(), snippet)
67                 }
68                 None => builder
69                     .replace(type_ref.syntax().text_range(), format!("Result<{}, _>", type_ref)),
70             }
71         },
72     )
73 }
74
75 struct TailReturnCollector {
76     exprs_to_wrap: Vec<ast::Expr>,
77 }
78
79 impl TailReturnCollector {
80     fn new() -> Self {
81         Self { exprs_to_wrap: vec![] }
82     }
83     /// Collect all`return` expression
84     fn collect_jump_exprs(&mut self, block_expr: &BlockExpr, collect_break: bool) {
85         let statements = block_expr.statements();
86         for stmt in statements {
87             let expr = match &stmt {
88                 ast::Stmt::ExprStmt(stmt) => stmt.expr(),
89                 ast::Stmt::LetStmt(stmt) => stmt.initializer(),
90                 ast::Stmt::Item(_) => continue,
91             };
92             if let Some(expr) = &expr {
93                 self.handle_exprs(expr, collect_break);
94             }
95         }
96
97         // Browse tail expressions for each block
98         if let Some(expr) = block_expr.tail_expr() {
99             if let Some(last_exprs) = get_tail_expr_from_block(&expr) {
100                 for last_expr in last_exprs {
101                     let last_expr = match last_expr {
102                         NodeType::Node(expr) => expr,
103                         NodeType::Leaf(expr) => expr.syntax().clone(),
104                     };
105
106                     if let Some(last_expr) = Expr::cast(last_expr.clone()) {
107                         self.handle_exprs(&last_expr, collect_break);
108                     } else if let Some(expr_stmt) = ast::Stmt::cast(last_expr) {
109                         let expr_stmt = match &expr_stmt {
110                             ast::Stmt::ExprStmt(stmt) => stmt.expr(),
111                             ast::Stmt::LetStmt(stmt) => stmt.initializer(),
112                             ast::Stmt::Item(_) => None,
113                         };
114                         if let Some(expr) = &expr_stmt {
115                             self.handle_exprs(expr, collect_break);
116                         }
117                     }
118                 }
119             }
120         }
121     }
122
123     fn handle_exprs(&mut self, expr: &Expr, collect_break: bool) {
124         match expr {
125             Expr::BlockExpr(block_expr) => {
126                 self.collect_jump_exprs(block_expr, collect_break);
127             }
128             Expr::ReturnExpr(ret_expr) => {
129                 if let Some(ret_expr_arg) = &ret_expr.expr() {
130                     self.exprs_to_wrap.push(ret_expr_arg.clone());
131                 }
132             }
133             Expr::BreakExpr(break_expr) if collect_break => {
134                 if let Some(break_expr_arg) = &break_expr.expr() {
135                     self.exprs_to_wrap.push(break_expr_arg.clone());
136                 }
137             }
138             Expr::IfExpr(if_expr) => {
139                 for block in if_expr.blocks() {
140                     self.collect_jump_exprs(&block, collect_break);
141                 }
142             }
143             Expr::LoopExpr(loop_expr) => {
144                 if let Some(block_expr) = loop_expr.loop_body() {
145                     self.collect_jump_exprs(&block_expr, collect_break);
146                 }
147             }
148             Expr::ForExpr(for_expr) => {
149                 if let Some(block_expr) = for_expr.loop_body() {
150                     self.collect_jump_exprs(&block_expr, collect_break);
151                 }
152             }
153             Expr::WhileExpr(while_expr) => {
154                 if let Some(block_expr) = while_expr.loop_body() {
155                     self.collect_jump_exprs(&block_expr, collect_break);
156                 }
157             }
158             Expr::MatchExpr(match_expr) => {
159                 if let Some(arm_list) = match_expr.match_arm_list() {
160                     arm_list.arms().filter_map(|match_arm| match_arm.expr()).for_each(|expr| {
161                         self.handle_exprs(&expr, collect_break);
162                     });
163                 }
164             }
165             _ => {}
166         }
167     }
168
169     fn collect_tail_exprs(&mut self, block: &BlockExpr) {
170         if let Some(expr) = block.tail_expr() {
171             self.handle_exprs(&expr, true);
172             self.fetch_tail_exprs(&expr);
173         }
174     }
175
176     fn fetch_tail_exprs(&mut self, expr: &Expr) {
177         if let Some(exprs) = get_tail_expr_from_block(expr) {
178             for node_type in &exprs {
179                 match node_type {
180                     NodeType::Leaf(expr) => {
181                         self.exprs_to_wrap.push(expr.clone());
182                     }
183                     NodeType::Node(expr) => {
184                         if let Some(last_expr) = Expr::cast(expr.clone()) {
185                             self.fetch_tail_exprs(&last_expr);
186                         }
187                     }
188                 }
189             }
190         }
191     }
192 }
193
194 #[derive(Debug)]
195 enum NodeType {
196     Leaf(ast::Expr),
197     Node(SyntaxNode),
198 }
199
200 /// Get a tail expression inside a block
201 fn get_tail_expr_from_block(expr: &Expr) -> Option<Vec<NodeType>> {
202     match expr {
203         Expr::IfExpr(if_expr) => {
204             let mut nodes = vec![];
205             for block in if_expr.blocks() {
206                 if let Some(block_expr) = block.tail_expr() {
207                     if let Some(tail_exprs) = get_tail_expr_from_block(&block_expr) {
208                         nodes.extend(tail_exprs);
209                     }
210                 } else if let Some(last_expr) = block.syntax().last_child() {
211                     nodes.push(NodeType::Node(last_expr));
212                 } else {
213                     nodes.push(NodeType::Node(block.syntax().clone()));
214                 }
215             }
216             Some(nodes)
217         }
218         Expr::LoopExpr(loop_expr) => {
219             loop_expr.syntax().last_child().map(|lc| vec![NodeType::Node(lc)])
220         }
221         Expr::ForExpr(for_expr) => {
222             for_expr.syntax().last_child().map(|lc| vec![NodeType::Node(lc)])
223         }
224         Expr::WhileExpr(while_expr) => {
225             while_expr.syntax().last_child().map(|lc| vec![NodeType::Node(lc)])
226         }
227         Expr::BlockExpr(block_expr) => {
228             block_expr.tail_expr().map(|lc| vec![NodeType::Node(lc.syntax().clone())])
229         }
230         Expr::MatchExpr(match_expr) => {
231             let arm_list = match_expr.match_arm_list()?;
232             let arms: Vec<NodeType> = arm_list
233                 .arms()
234                 .filter_map(|match_arm| match_arm.expr())
235                 .map(|expr| match expr {
236                     Expr::ReturnExpr(ret_expr) => NodeType::Node(ret_expr.syntax().clone()),
237                     Expr::BreakExpr(break_expr) => NodeType::Node(break_expr.syntax().clone()),
238                     _ => match expr.syntax().last_child() {
239                         Some(last_expr) => NodeType::Node(last_expr),
240                         None => NodeType::Node(expr.syntax().clone()),
241                     },
242                 })
243                 .collect();
244
245             Some(arms)
246         }
247         Expr::BreakExpr(expr) => expr.expr().map(|e| vec![NodeType::Leaf(e)]),
248         Expr::ReturnExpr(ret_expr) => Some(vec![NodeType::Node(ret_expr.syntax().clone())]),
249
250         Expr::CallExpr(_)
251         | Expr::Literal(_)
252         | Expr::TupleExpr(_)
253         | Expr::ArrayExpr(_)
254         | Expr::ParenExpr(_)
255         | Expr::PathExpr(_)
256         | Expr::RecordExpr(_)
257         | Expr::IndexExpr(_)
258         | Expr::MethodCallExpr(_)
259         | Expr::AwaitExpr(_)
260         | Expr::CastExpr(_)
261         | Expr::RefExpr(_)
262         | Expr::PrefixExpr(_)
263         | Expr::RangeExpr(_)
264         | Expr::BinExpr(_)
265         | Expr::MacroCall(_)
266         | Expr::BoxExpr(_) => Some(vec![NodeType::Leaf(expr.clone())]),
267         _ => None,
268     }
269 }
270
271 #[cfg(test)]
272 mod tests {
273     use crate::tests::{check_assist, check_assist_not_applicable};
274
275     use super::*;
276
277     #[test]
278     fn wrap_return_type_in_result_simple() {
279         check_assist(
280             wrap_return_type_in_result,
281             r#"
282 fn foo() -> i3$02 {
283     let test = "test";
284     return 42i32;
285 }
286 "#,
287             r#"
288 fn foo() -> Result<i32, ${0:_}> {
289     let test = "test";
290     return Ok(42i32);
291 }
292 "#,
293         );
294     }
295
296     #[test]
297     fn wrap_return_type_in_result_simple_closure() {
298         check_assist(
299             wrap_return_type_in_result,
300             r#"
301 fn foo() {
302     || -> i32$0 {
303         let test = "test";
304         return 42i32;
305     };
306 }
307 "#,
308             r#"
309 fn foo() {
310     || -> Result<i32, ${0:_}> {
311         let test = "test";
312         return Ok(42i32);
313     };
314 }
315 "#,
316         );
317     }
318
319     #[test]
320     fn wrap_return_type_in_result_simple_return_type_bad_cursor() {
321         check_assist_not_applicable(
322             wrap_return_type_in_result,
323             r#"
324 fn foo() -> i32 {
325     let test = "test";$0
326     return 42i32;
327 }
328 "#,
329         );
330     }
331
332     #[test]
333     fn wrap_return_type_in_result_simple_return_type_bad_cursor_closure() {
334         check_assist_not_applicable(
335             wrap_return_type_in_result,
336             r#"
337 fn foo() {
338     || -> i32 {
339         let test = "test";$0
340         return 42i32;
341     };
342 }
343 "#,
344         );
345     }
346
347     #[test]
348     fn wrap_return_type_in_result_closure_non_block() {
349         check_assist_not_applicable(wrap_return_type_in_result, r#"fn foo() { || -> i$032 3; }"#);
350     }
351
352     #[test]
353     fn wrap_return_type_in_result_simple_return_type_already_result_std() {
354         check_assist_not_applicable(
355             wrap_return_type_in_result,
356             r#"
357 fn foo() -> std::result::Result<i32$0, String> {
358     let test = "test";
359     return 42i32;
360 }
361 "#,
362         );
363     }
364
365     #[test]
366     fn wrap_return_type_in_result_simple_return_type_already_result() {
367         cov_mark::check!(wrap_return_type_in_result_simple_return_type_already_result);
368         check_assist_not_applicable(
369             wrap_return_type_in_result,
370             r#"
371 fn foo() -> Result<i32$0, String> {
372     let test = "test";
373     return 42i32;
374 }
375 "#,
376         );
377     }
378
379     #[test]
380     fn wrap_return_type_in_result_simple_return_type_already_result_closure() {
381         check_assist_not_applicable(
382             wrap_return_type_in_result,
383             r#"
384 fn foo() {
385     || -> Result<i32$0, String> {
386         let test = "test";
387         return 42i32;
388     };
389 }
390 "#,
391         );
392     }
393
394     #[test]
395     fn wrap_return_type_in_result_simple_with_cursor() {
396         check_assist(
397             wrap_return_type_in_result,
398             r#"
399 fn foo() -> $0i32 {
400     let test = "test";
401     return 42i32;
402 }
403 "#,
404             r#"
405 fn foo() -> Result<i32, ${0:_}> {
406     let test = "test";
407     return Ok(42i32);
408 }
409 "#,
410         );
411     }
412
413     #[test]
414     fn wrap_return_type_in_result_simple_with_tail() {
415         check_assist(
416             wrap_return_type_in_result,
417             r#"
418 fn foo() ->$0 i32 {
419     let test = "test";
420     42i32
421 }
422 "#,
423             r#"
424 fn foo() -> Result<i32, ${0:_}> {
425     let test = "test";
426     Ok(42i32)
427 }
428 "#,
429         );
430     }
431
432     #[test]
433     fn wrap_return_type_in_result_simple_with_tail_closure() {
434         check_assist(
435             wrap_return_type_in_result,
436             r#"
437 fn foo() {
438     || ->$0 i32 {
439         let test = "test";
440         42i32
441     };
442 }
443 "#,
444             r#"
445 fn foo() {
446     || -> Result<i32, ${0:_}> {
447         let test = "test";
448         Ok(42i32)
449     };
450 }
451 "#,
452         );
453     }
454
455     #[test]
456     fn wrap_return_type_in_result_simple_with_tail_only() {
457         check_assist(
458             wrap_return_type_in_result,
459             r#"fn foo() -> i32$0 { 42i32 }"#,
460             r#"fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }"#,
461         );
462     }
463
464     #[test]
465     fn wrap_return_type_in_result_simple_with_tail_block_like() {
466         check_assist(
467             wrap_return_type_in_result,
468             r#"
469 fn foo() -> i32$0 {
470     if true {
471         42i32
472     } else {
473         24i32
474     }
475 }
476 "#,
477             r#"
478 fn foo() -> Result<i32, ${0:_}> {
479     if true {
480         Ok(42i32)
481     } else {
482         Ok(24i32)
483     }
484 }
485 "#,
486         );
487     }
488
489     #[test]
490     fn wrap_return_type_in_result_simple_without_block_closure() {
491         check_assist(
492             wrap_return_type_in_result,
493             r#"
494 fn foo() {
495     || -> i32$0 {
496         if true {
497             42i32
498         } else {
499             24i32
500         }
501     };
502 }
503 "#,
504             r#"
505 fn foo() {
506     || -> Result<i32, ${0:_}> {
507         if true {
508             Ok(42i32)
509         } else {
510             Ok(24i32)
511         }
512     };
513 }
514 "#,
515         );
516     }
517
518     #[test]
519     fn wrap_return_type_in_result_simple_with_nested_if() {
520         check_assist(
521             wrap_return_type_in_result,
522             r#"
523 fn foo() -> i32$0 {
524     if true {
525         if false {
526             1
527         } else {
528             2
529         }
530     } else {
531         24i32
532     }
533 }
534 "#,
535             r#"
536 fn foo() -> Result<i32, ${0:_}> {
537     if true {
538         if false {
539             Ok(1)
540         } else {
541             Ok(2)
542         }
543     } else {
544         Ok(24i32)
545     }
546 }
547 "#,
548         );
549     }
550
551     #[test]
552     fn wrap_return_type_in_result_simple_with_await() {
553         check_assist(
554             wrap_return_type_in_result,
555             r#"
556 async fn foo() -> i$032 {
557     if true {
558         if false {
559             1.await
560         } else {
561             2.await
562         }
563     } else {
564         24i32.await
565     }
566 }
567 "#,
568             r#"
569 async fn foo() -> Result<i32, ${0:_}> {
570     if true {
571         if false {
572             Ok(1.await)
573         } else {
574             Ok(2.await)
575         }
576     } else {
577         Ok(24i32.await)
578     }
579 }
580 "#,
581         );
582     }
583
584     #[test]
585     fn wrap_return_type_in_result_simple_with_array() {
586         check_assist(
587             wrap_return_type_in_result,
588             r#"fn foo() -> [i32;$0 3] { [1, 2, 3] }"#,
589             r#"fn foo() -> Result<[i32; 3], ${0:_}> { Ok([1, 2, 3]) }"#,
590         );
591     }
592
593     #[test]
594     fn wrap_return_type_in_result_simple_with_cast() {
595         check_assist(
596             wrap_return_type_in_result,
597             r#"
598 fn foo() -$0> i32 {
599     if true {
600         if false {
601             1 as i32
602         } else {
603             2 as i32
604         }
605     } else {
606         24 as i32
607     }
608 }
609 "#,
610             r#"
611 fn foo() -> Result<i32, ${0:_}> {
612     if true {
613         if false {
614             Ok(1 as i32)
615         } else {
616             Ok(2 as i32)
617         }
618     } else {
619         Ok(24 as i32)
620     }
621 }
622 "#,
623         );
624     }
625
626     #[test]
627     fn wrap_return_type_in_result_simple_with_tail_block_like_match() {
628         check_assist(
629             wrap_return_type_in_result,
630             r#"
631 fn foo() -> i32$0 {
632     let my_var = 5;
633     match my_var {
634         5 => 42i32,
635         _ => 24i32,
636     }
637 }
638 "#,
639             r#"
640 fn foo() -> Result<i32, ${0:_}> {
641     let my_var = 5;
642     match my_var {
643         5 => Ok(42i32),
644         _ => Ok(24i32),
645     }
646 }
647 "#,
648         );
649     }
650
651     #[test]
652     fn wrap_return_type_in_result_simple_with_loop_with_tail() {
653         check_assist(
654             wrap_return_type_in_result,
655             r#"
656 fn foo() -> i32$0 {
657     let my_var = 5;
658     loop {
659         println!("test");
660         5
661     }
662     my_var
663 }
664 "#,
665             r#"
666 fn foo() -> Result<i32, ${0:_}> {
667     let my_var = 5;
668     loop {
669         println!("test");
670         5
671     }
672     Ok(my_var)
673 }
674 "#,
675         );
676     }
677
678     #[test]
679     fn wrap_return_type_in_result_simple_with_loop_in_let_stmt() {
680         check_assist(
681             wrap_return_type_in_result,
682             r#"
683 fn foo() -> i32$0 {
684     let my_var = let x = loop {
685         break 1;
686     };
687     my_var
688 }
689 "#,
690             r#"
691 fn foo() -> Result<i32, ${0:_}> {
692     let my_var = let x = loop {
693         break 1;
694     };
695     Ok(my_var)
696 }
697 "#,
698         );
699     }
700
701     #[test]
702     fn wrap_return_type_in_result_simple_with_tail_block_like_match_return_expr() {
703         check_assist(
704             wrap_return_type_in_result,
705             r#"
706 fn foo() -> i32$0 {
707     let my_var = 5;
708     let res = match my_var {
709         5 => 42i32,
710         _ => return 24i32,
711     };
712     res
713 }
714 "#,
715             r#"
716 fn foo() -> Result<i32, ${0:_}> {
717     let my_var = 5;
718     let res = match my_var {
719         5 => 42i32,
720         _ => return Ok(24i32),
721     };
722     Ok(res)
723 }
724 "#,
725         );
726
727         check_assist(
728             wrap_return_type_in_result,
729             r#"
730 fn foo() -> i32$0 {
731     let my_var = 5;
732     let res = if my_var == 5 {
733         42i32
734     } else {
735         return 24i32;
736     };
737     res
738 }
739 "#,
740             r#"
741 fn foo() -> Result<i32, ${0:_}> {
742     let my_var = 5;
743     let res = if my_var == 5 {
744         42i32
745     } else {
746         return Ok(24i32);
747     };
748     Ok(res)
749 }
750 "#,
751         );
752     }
753
754     #[test]
755     fn wrap_return_type_in_result_simple_with_tail_block_like_match_deeper() {
756         check_assist(
757             wrap_return_type_in_result,
758             r#"
759 fn foo() -> i32$0 {
760     let my_var = 5;
761     match my_var {
762         5 => {
763             if true {
764                 42i32
765             } else {
766                 25i32
767             }
768         },
769         _ => {
770             let test = "test";
771             if test == "test" {
772                 return bar();
773             }
774             53i32
775         },
776     }
777 }
778 "#,
779             r#"
780 fn foo() -> Result<i32, ${0:_}> {
781     let my_var = 5;
782     match my_var {
783         5 => {
784             if true {
785                 Ok(42i32)
786             } else {
787                 Ok(25i32)
788             }
789         },
790         _ => {
791             let test = "test";
792             if test == "test" {
793                 return Ok(bar());
794             }
795             Ok(53i32)
796         },
797     }
798 }
799 "#,
800         );
801     }
802
803     #[test]
804     fn wrap_return_type_in_result_simple_with_tail_block_like_early_return() {
805         check_assist(
806             wrap_return_type_in_result,
807             r#"
808 fn foo() -> i$032 {
809     let test = "test";
810     if test == "test" {
811         return 24i32;
812     }
813     53i32
814 }
815 "#,
816             r#"
817 fn foo() -> Result<i32, ${0:_}> {
818     let test = "test";
819     if test == "test" {
820         return Ok(24i32);
821     }
822     Ok(53i32)
823 }
824 "#,
825         );
826     }
827
828     #[test]
829     fn wrap_return_type_in_result_simple_with_closure() {
830         check_assist(
831             wrap_return_type_in_result,
832             r#"
833 fn foo(the_field: u32) ->$0 u32 {
834     let true_closure = || { return true; };
835     if the_field < 5 {
836         let mut i = 0;
837         if true_closure() {
838             return 99;
839         } else {
840             return 0;
841         }
842     }
843     the_field
844 }
845 "#,
846             r#"
847 fn foo(the_field: u32) -> Result<u32, ${0:_}> {
848     let true_closure = || { return true; };
849     if the_field < 5 {
850         let mut i = 0;
851         if true_closure() {
852             return Ok(99);
853         } else {
854             return Ok(0);
855         }
856     }
857     Ok(the_field)
858 }
859 "#,
860         );
861
862         check_assist(
863             wrap_return_type_in_result,
864             r#"
865             fn foo(the_field: u32) -> u32$0 {
866                 let true_closure = || {
867                     return true;
868                 };
869                 if the_field < 5 {
870                     let mut i = 0;
871
872
873                     if true_closure() {
874                         return 99;
875                     } else {
876                         return 0;
877                     }
878                 }
879                 let t = None;
880
881                 t.unwrap_or_else(|| the_field)
882             }
883             "#,
884             r#"
885             fn foo(the_field: u32) -> Result<u32, ${0:_}> {
886                 let true_closure = || {
887                     return true;
888                 };
889                 if the_field < 5 {
890                     let mut i = 0;
891
892
893                     if true_closure() {
894                         return Ok(99);
895                     } else {
896                         return Ok(0);
897                     }
898                 }
899                 let t = None;
900
901                 Ok(t.unwrap_or_else(|| the_field))
902             }
903             "#,
904         );
905     }
906
907     #[test]
908     fn wrap_return_type_in_result_simple_with_weird_forms() {
909         check_assist(
910             wrap_return_type_in_result,
911             r#"
912 fn foo() -> i32$0 {
913     let test = "test";
914     if test == "test" {
915         return 24i32;
916     }
917     let mut i = 0;
918     loop {
919         if i == 1 {
920             break 55;
921         }
922         i += 1;
923     }
924 }
925 "#,
926             r#"
927 fn foo() -> Result<i32, ${0:_}> {
928     let test = "test";
929     if test == "test" {
930         return Ok(24i32);
931     }
932     let mut i = 0;
933     loop {
934         if i == 1 {
935             break Ok(55);
936         }
937         i += 1;
938     }
939 }
940 "#,
941         );
942
943         check_assist(
944             wrap_return_type_in_result,
945             r#"
946 fn foo() -> i32$0 {
947     let test = "test";
948     if test == "test" {
949         return 24i32;
950     }
951     let mut i = 0;
952     loop {
953         loop {
954             if i == 1 {
955                 break 55;
956             }
957             i += 1;
958         }
959     }
960 }
961 "#,
962             r#"
963 fn foo() -> Result<i32, ${0:_}> {
964     let test = "test";
965     if test == "test" {
966         return Ok(24i32);
967     }
968     let mut i = 0;
969     loop {
970         loop {
971             if i == 1 {
972                 break Ok(55);
973             }
974             i += 1;
975         }
976     }
977 }
978 "#,
979         );
980
981         check_assist(
982             wrap_return_type_in_result,
983             r#"
984 fn foo() -> i3$02 {
985     let test = "test";
986     let other = 5;
987     if test == "test" {
988         let res = match other {
989             5 => 43,
990             _ => return 56,
991         };
992     }
993     let mut i = 0;
994     loop {
995         loop {
996             if i == 1 {
997                 break 55;
998             }
999             i += 1;
1000         }
1001     }
1002 }
1003 "#,
1004             r#"
1005 fn foo() -> Result<i32, ${0:_}> {
1006     let test = "test";
1007     let other = 5;
1008     if test == "test" {
1009         let res = match other {
1010             5 => 43,
1011             _ => return Ok(56),
1012         };
1013     }
1014     let mut i = 0;
1015     loop {
1016         loop {
1017             if i == 1 {
1018                 break Ok(55);
1019             }
1020             i += 1;
1021         }
1022     }
1023 }
1024 "#,
1025         );
1026
1027         check_assist(
1028             wrap_return_type_in_result,
1029             r#"
1030 fn foo(the_field: u32) -> u32$0 {
1031     if the_field < 5 {
1032         let mut i = 0;
1033         loop {
1034             if i > 5 {
1035                 return 55u32;
1036             }
1037             i += 3;
1038         }
1039         match i {
1040             5 => return 99,
1041             _ => return 0,
1042         };
1043     }
1044     the_field
1045 }
1046 "#,
1047             r#"
1048 fn foo(the_field: u32) -> Result<u32, ${0:_}> {
1049     if the_field < 5 {
1050         let mut i = 0;
1051         loop {
1052             if i > 5 {
1053                 return Ok(55u32);
1054             }
1055             i += 3;
1056         }
1057         match i {
1058             5 => return Ok(99),
1059             _ => return Ok(0),
1060         };
1061     }
1062     Ok(the_field)
1063 }
1064 "#,
1065         );
1066
1067         check_assist(
1068             wrap_return_type_in_result,
1069             r#"
1070 fn foo(the_field: u32) -> u3$02 {
1071     if the_field < 5 {
1072         let mut i = 0;
1073         match i {
1074             5 => return 99,
1075             _ => return 0,
1076         }
1077     }
1078     the_field
1079 }
1080 "#,
1081             r#"
1082 fn foo(the_field: u32) -> Result<u32, ${0:_}> {
1083     if the_field < 5 {
1084         let mut i = 0;
1085         match i {
1086             5 => return Ok(99),
1087             _ => return Ok(0),
1088         }
1089     }
1090     Ok(the_field)
1091 }
1092 "#,
1093         );
1094
1095         check_assist(
1096             wrap_return_type_in_result,
1097             r#"
1098 fn foo(the_field: u32) -> u32$0 {
1099     if the_field < 5 {
1100         let mut i = 0;
1101         if i == 5 {
1102             return 99
1103         } else {
1104             return 0
1105         }
1106     }
1107     the_field
1108 }
1109 "#,
1110             r#"
1111 fn foo(the_field: u32) -> Result<u32, ${0:_}> {
1112     if the_field < 5 {
1113         let mut i = 0;
1114         if i == 5 {
1115             return Ok(99)
1116         } else {
1117             return Ok(0)
1118         }
1119     }
1120     Ok(the_field)
1121 }
1122 "#,
1123         );
1124
1125         check_assist(
1126             wrap_return_type_in_result,
1127             r#"
1128 fn foo(the_field: u32) -> $0u32 {
1129     if the_field < 5 {
1130         let mut i = 0;
1131         if i == 5 {
1132             return 99;
1133         } else {
1134             return 0;
1135         }
1136     }
1137     the_field
1138 }
1139 "#,
1140             r#"
1141 fn foo(the_field: u32) -> Result<u32, ${0:_}> {
1142     if the_field < 5 {
1143         let mut i = 0;
1144         if i == 5 {
1145             return Ok(99);
1146         } else {
1147             return Ok(0);
1148         }
1149     }
1150     Ok(the_field)
1151 }
1152 "#,
1153         );
1154     }
1155 }