aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/handlers/replace_unwrap_with_match.rs')
-rw-r--r--crates/ra_assists/src/handlers/replace_unwrap_with_match.rs60
1 files changed, 40 insertions, 20 deletions
diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
index 62d4ea522..cff7dfb81 100644
--- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
@@ -1,11 +1,18 @@
1use std::iter; 1use std::iter;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, edit::IndentLevel, make}, 4 ast::{
5 self,
6 edit::{AstNodeEdit, IndentLevel},
7 make,
8 },
5 AstNode, 9 AstNode,
6}; 10};
7 11
8use crate::{utils::TryEnum, Assist, AssistCtx, AssistId}; 12use crate::{
13 utils::{render_snippet, Cursor, TryEnum},
14 AssistContext, AssistId, Assists,
15};
9 16
10// Assist: replace_unwrap_with_match 17// Assist: replace_unwrap_with_match
11// 18//
@@ -25,11 +32,11 @@ use crate::{utils::TryEnum, Assist, AssistCtx, AssistId};
25// let x: Result<i32, i32> = Result::Ok(92); 32// let x: Result<i32, i32> = Result::Ok(92);
26// let y = match x { 33// let y = match x {
27// Ok(a) => a, 34// Ok(a) => a,
28// _ => unreachable!(), 35// $0_ => unreachable!(),
29// }; 36// };
30// } 37// }
31// ``` 38// ```
32pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> { 39pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
33 let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?; 40 let method_call: ast::MethodCallExpr = ctx.find_node_at_offset()?;
34 let name = method_call.name_ref()?; 41 let name = method_call.name_ref()?;
35 if name.text() != "unwrap" { 42 if name.text() != "unwrap" {
@@ -37,9 +44,9 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> {
37 } 44 }
38 let caller = method_call.expr()?; 45 let caller = method_call.expr()?;
39 let ty = ctx.sema.type_of_expr(&caller)?; 46 let ty = ctx.sema.type_of_expr(&caller)?;
40 let happy_variant = TryEnum::from_ty(ctx.sema, &ty)?.happy_case(); 47 let happy_variant = TryEnum::from_ty(&ctx.sema, &ty)?.happy_case();
41 48 let target = method_call.syntax().text_range();
42 ctx.add_assist(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", |edit| { 49 acc.add(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", target, |builder| {
43 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant))); 50 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant)));
44 let it = make::bind_pat(make::name("a")).into(); 51 let it = make::bind_pat(make::name("a")).into();
45 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into(); 52 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
@@ -47,23 +54,36 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> {
47 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); 54 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a")));
48 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); 55 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path));
49 56
50 let unreachable_call = make::unreachable_macro_call().into(); 57 let unreachable_call = make::expr_unreachable();
51 let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call); 58 let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call);
52 59
53 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); 60 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
54 let match_expr = make::expr_match(caller.clone(), match_arm_list); 61 let match_expr = make::expr_match(caller.clone(), match_arm_list)
55 let match_expr = IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); 62 .indent(IndentLevel::from_node(method_call.syntax()));
56 63
57 edit.target(method_call.syntax().text_range()); 64 let range = method_call.syntax().text_range();
58 edit.set_cursor(caller.syntax().text_range().start()); 65 match ctx.config.snippet_cap {
59 edit.replace_ast::<ast::Expr>(method_call.into(), match_expr); 66 Some(cap) => {
67 let err_arm = match_expr
68 .syntax()
69 .descendants()
70 .filter_map(ast::MatchArm::cast)
71 .last()
72 .unwrap();
73 let snippet =
74 render_snippet(cap, match_expr.syntax(), Cursor::Before(err_arm.syntax()));
75 builder.replace_snippet(cap, range, snippet)
76 }
77 None => builder.replace(range, match_expr.to_string()),
78 }
60 }) 79 })
61} 80}
62 81
63#[cfg(test)] 82#[cfg(test)]
64mod tests { 83mod tests {
84 use crate::tests::{check_assist, check_assist_target};
85
65 use super::*; 86 use super::*;
66 use crate::helpers::{check_assist, check_assist_target};
67 87
68 #[test] 88 #[test]
69 fn test_replace_result_unwrap_with_match() { 89 fn test_replace_result_unwrap_with_match() {
@@ -82,9 +102,9 @@ enum Result<T, E> { Ok(T), Err(E) }
82fn i<T>(a: T) -> T { a } 102fn i<T>(a: T) -> T { a }
83fn main() { 103fn main() {
84 let x: Result<i32, i32> = Result::Ok(92); 104 let x: Result<i32, i32> = Result::Ok(92);
85 let y = <|>match i(x) { 105 let y = match i(x) {
86 Ok(a) => a, 106 Ok(a) => a,
87 _ => unreachable!(), 107 $0_ => unreachable!(),
88 }; 108 };
89} 109}
90 ", 110 ",
@@ -108,9 +128,9 @@ enum Option<T> { Some(T), None }
108fn i<T>(a: T) -> T { a } 128fn i<T>(a: T) -> T { a }
109fn main() { 129fn main() {
110 let x = Option::Some(92); 130 let x = Option::Some(92);
111 let y = <|>match i(x) { 131 let y = match i(x) {
112 Some(a) => a, 132 Some(a) => a,
113 _ => unreachable!(), 133 $0_ => unreachable!(),
114 }; 134 };
115} 135}
116 ", 136 ",
@@ -134,9 +154,9 @@ enum Result<T, E> { Ok(T), Err(E) }
134fn i<T>(a: T) -> T { a } 154fn i<T>(a: T) -> T { a }
135fn main() { 155fn main() {
136 let x: Result<i32, i32> = Result::Ok(92); 156 let x: Result<i32, i32> = Result::Ok(92);
137 let y = <|>match i(x) { 157 let y = match i(x) {
138 Ok(a) => a, 158 Ok(a) => a,
139 _ => unreachable!(), 159 $0_ => unreachable!(),
140 }.count_zeroes(); 160 }.count_zeroes();
141} 161}
142 ", 162 ",