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