aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/assists/src/handlers/change_return_type_to_result.rs121
1 files changed, 107 insertions, 14 deletions
diff --git a/crates/assists/src/handlers/change_return_type_to_result.rs b/crates/assists/src/handlers/change_return_type_to_result.rs
index be480943c..76f33a5b6 100644
--- a/crates/assists/src/handlers/change_return_type_to_result.rs
+++ b/crates/assists/src/handlers/change_return_type_to_result.rs
@@ -2,7 +2,7 @@ use std::iter;
2 2
3use syntax::{ 3use syntax::{
4 ast::{self, make, BlockExpr, Expr, LoopBodyOwner}, 4 ast::{self, make, BlockExpr, Expr, LoopBodyOwner},
5 AstNode, SyntaxNode, 5 match_ast, AstNode, SyntaxNode,
6}; 6};
7use test_utils::mark; 7use test_utils::mark;
8 8
@@ -21,8 +21,18 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
21// ``` 21// ```
22pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 22pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
23 let ret_type = ctx.find_node_at_offset::<ast::RetType>()?; 23 let ret_type = ctx.find_node_at_offset::<ast::RetType>()?;
24 // FIXME: extend to lambdas as well 24 let parent = ret_type.syntax().parent()?;
25 let fn_def = ret_type.syntax().parent().and_then(ast::Fn::cast)?; 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 };
26 36
27 let type_ref = &ret_type.ty()?; 37 let type_ref = &ret_type.ty()?;
28 let ret_type_str = type_ref.syntax().text().to_string(); 38 let ret_type_str = type_ref.syntax().text().to_string();
@@ -34,16 +44,14 @@ pub(crate) fn change_return_type_to_result(acc: &mut Assists, ctx: &AssistContex
34 } 44 }
35 } 45 }
36 46
37 let block_expr = &fn_def.body()?;
38
39 acc.add( 47 acc.add(
40 AssistId("change_return_type_to_result", AssistKind::RefactorRewrite), 48 AssistId("change_return_type_to_result", AssistKind::RefactorRewrite),
41 "Wrap return type in Result", 49 "Wrap return type in Result",
42 type_ref.syntax().text_range(), 50 type_ref.syntax().text_range(),
43 |builder| { 51 |builder| {
44 let mut tail_return_expr_collector = TailReturnCollector::new(); 52 let mut tail_return_expr_collector = TailReturnCollector::new();
45 tail_return_expr_collector.collect_jump_exprs(block_expr, false); 53 tail_return_expr_collector.collect_jump_exprs(&block_expr, false);
46 tail_return_expr_collector.collect_tail_exprs(block_expr); 54 tail_return_expr_collector.collect_tail_exprs(&block_expr);
47 55
48 for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap { 56 for ret_expr_arg in tail_return_expr_collector.exprs_to_wrap {
49 let ok_wrapped = make::expr_call( 57 let ok_wrapped = make::expr_call(
@@ -285,16 +293,20 @@ mod tests {
285 } 293 }
286 294
287 #[test] 295 #[test]
288 fn change_return_type_to_result_simple_return_type() { 296 fn change_return_type_to_result_simple_closure() {
289 check_assist( 297 check_assist(
290 change_return_type_to_result, 298 change_return_type_to_result,
291 r#"fn foo() -> i32<|> { 299 r#"fn foo() {
292 let test = "test"; 300 || -> i32<|> {
293 return 42i32; 301 let test = "test";
302 return 42i32;
303 };
294 }"#, 304 }"#,
295 r#"fn foo() -> Result<i32, ${0:_}> { 305 r#"fn foo() {
296 let test = "test"; 306 || -> Result<i32, ${0:_}> {
297 return Ok(42i32); 307 let test = "test";
308 return Ok(42i32);
309 };
298 }"#, 310 }"#,
299 ); 311 );
300 } 312 }
@@ -311,6 +323,29 @@ mod tests {
311 } 323 }
312 324
313 #[test] 325 #[test]
326 fn change_return_type_to_result_simple_return_type_bad_cursor_closure() {
327 check_assist_not_applicable(
328 change_return_type_to_result,
329 r#"fn foo() {
330 || -> i32 {
331 let test = "test";<|>
332 return 42i32;
333 };
334 }"#,
335 );
336 }
337
338 #[test]
339 fn change_return_type_to_result_closure_non_block() {
340 check_assist_not_applicable(
341 change_return_type_to_result,
342 r#"fn foo() {
343 || -> i<|>32 3;
344 }"#,
345 );
346 }
347
348 #[test]
314 fn change_return_type_to_result_simple_return_type_already_result_std() { 349 fn change_return_type_to_result_simple_return_type_already_result_std() {
315 check_assist_not_applicable( 350 check_assist_not_applicable(
316 change_return_type_to_result, 351 change_return_type_to_result,
@@ -334,6 +369,19 @@ mod tests {
334 } 369 }
335 370
336 #[test] 371 #[test]
372 fn change_return_type_to_result_simple_return_type_already_result_closure() {
373 check_assist_not_applicable(
374 change_return_type_to_result,
375 r#"fn foo() {
376 || -> Result<i32<|>, String> {
377 let test = "test";
378 return 42i32;
379 };
380 }"#,
381 );
382 }
383
384 #[test]
337 fn change_return_type_to_result_simple_with_cursor() { 385 fn change_return_type_to_result_simple_with_cursor() {
338 check_assist( 386 check_assist(
339 change_return_type_to_result, 387 change_return_type_to_result,
@@ -364,6 +412,25 @@ mod tests {
364 } 412 }
365 413
366 #[test] 414 #[test]
415 fn change_return_type_to_result_simple_with_tail_closure() {
416 check_assist(
417 change_return_type_to_result,
418 r#"fn foo() {
419 || -><|> i32 {
420 let test = "test";
421 42i32
422 };
423 }"#,
424 r#"fn foo() {
425 || -> Result<i32, ${0:_}> {
426 let test = "test";
427 Ok(42i32)
428 };
429 }"#,
430 );
431 }
432
433 #[test]
367 fn change_return_type_to_result_simple_with_tail_only() { 434 fn change_return_type_to_result_simple_with_tail_only() {
368 check_assist( 435 check_assist(
369 change_return_type_to_result, 436 change_return_type_to_result,
@@ -375,6 +442,7 @@ mod tests {
375 }"#, 442 }"#,
376 ); 443 );
377 } 444 }
445
378 #[test] 446 #[test]
379 fn change_return_type_to_result_simple_with_tail_block_like() { 447 fn change_return_type_to_result_simple_with_tail_block_like() {
380 check_assist( 448 check_assist(
@@ -397,6 +465,31 @@ mod tests {
397 } 465 }
398 466
399 #[test] 467 #[test]
468 fn change_return_type_to_result_simple_without_block_closure() {
469 check_assist(
470 change_return_type_to_result,
471 r#"fn foo() {
472 || -> i32<|> {
473 if true {
474 42i32
475 } else {
476 24i32
477 }
478 };
479 }"#,
480 r#"fn foo() {
481 || -> Result<i32, ${0:_}> {
482 if true {
483 Ok(42i32)
484 } else {
485 Ok(24i32)
486 }
487 };
488 }"#,
489 );
490 }
491
492 #[test]
400 fn change_return_type_to_result_simple_with_nested_if() { 493 fn change_return_type_to_result_simple_with_nested_if() {
401 check_assist( 494 check_assist(
402 change_return_type_to_result, 495 change_return_type_to_result,