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