diff options
author | Galilée 'Bill' Enguehard <[email protected]> | 2020-05-21 22:27:38 +0100 |
---|---|---|
committer | Galilée 'Bill' Enguehard <[email protected]> | 2020-05-21 22:27:38 +0100 |
commit | 7fece3bdd2450c0807f7dd742239cae95f0cc65e (patch) | |
tree | 866c4db826c959e79c63a6727bdb9f2c61e6fc4f /crates/ra_assists/src/handlers/replace_unwrap_with_match.rs | |
parent | db926218b2082077750291f8426ddd28b284cd08 (diff) | |
parent | 59732df8d40dfadc6dcf5951265416576399712a (diff) |
Merge branch 'master' of github.com:rust-analyzer/rust-analyzer into modname_spacing
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.rs | 60 |
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 @@ | |||
1 | use std::iter; | 1 | use std::iter; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use 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 | ||
8 | use crate::{utils::TryEnum, Assist, AssistCtx, AssistId}; | 12 | use 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 | // ``` |
32 | pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> { | 39 | pub(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)] |
64 | mod tests { | 83 | mod 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) } | |||
82 | fn i<T>(a: T) -> T { a } | 102 | fn i<T>(a: T) -> T { a } |
83 | fn main() { | 103 | fn 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 } | |||
108 | fn i<T>(a: T) -> T { a } | 128 | fn i<T>(a: T) -> T { a } |
109 | fn main() { | 129 | fn 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) } | |||
134 | fn i<T>(a: T) -> T { a } | 154 | fn i<T>(a: T) -> T { a } |
135 | fn main() { | 155 | fn 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 | ", |