aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src')
-rw-r--r--crates/ra_assists/src/handlers/replace_let_with_if_let.rs16
-rw-r--r--crates/ra_assists/src/handlers/replace_unwrap_with_match.rs52
-rw-r--r--crates/ra_assists/src/utils.rs15
3 files changed, 35 insertions, 48 deletions
diff --git a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
index bdbaae389..fb134f677 100644
--- a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
@@ -1,6 +1,5 @@
1use std::iter::once; 1use std::iter::once;
2 2
3use hir::Adt;
4use ra_syntax::{ 3use ra_syntax::{
5 ast::{ 4 ast::{
6 self, 5 self,
@@ -12,6 +11,7 @@ use ra_syntax::{
12 11
13use crate::{ 12use crate::{
14 assist_ctx::{Assist, AssistCtx}, 13 assist_ctx::{Assist, AssistCtx},
14 utils::happy_try_variant,
15 AssistId, 15 AssistId,
16}; 16};
17 17
@@ -45,20 +45,10 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option<Assist> {
45 let init = let_stmt.initializer()?; 45 let init = let_stmt.initializer()?;
46 let original_pat = let_stmt.pat()?; 46 let original_pat = let_stmt.pat()?;
47 let ty = ctx.sema.type_of_expr(&init)?; 47 let ty = ctx.sema.type_of_expr(&init)?;
48 let enum_ = match ty.as_adt() { 48 let happy_variant = happy_try_variant(ctx.sema, &ty);
49 Some(Adt::Enum(it)) => it,
50 _ => return None,
51 };
52 let happy_case =
53 [("Result", "Ok"), ("Option", "Some")].iter().find_map(|(known_type, happy_case)| {
54 if &enum_.name(ctx.db).to_string() == known_type {
55 return Some(happy_case);
56 }
57 None
58 });
59 49
60 ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", |edit| { 50 ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", |edit| {
61 let with_placeholder: ast::Pat = match happy_case { 51 let with_placeholder: ast::Pat = match happy_variant {
62 None => make::placeholder_pat().into(), 52 None => make::placeholder_pat().into(),
63 Some(var_name) => make::tuple_struct_pat( 53 Some(var_name) => make::tuple_struct_pat(
64 make::path_unqualified(make::path_segment(make::name_ref(var_name))), 54 make::path_unqualified(make::path_segment(make::name_ref(var_name))),
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 62cb7a763..89211b44a 100644
--- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
@@ -1,12 +1,11 @@
1use std::iter; 1use std::iter;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 ast::{self, make}, 4 ast::{self, edit::IndentLevel, make},
5 AstNode, 5 AstNode,
6}; 6};
7 7
8use crate::{Assist, AssistCtx, AssistId}; 8use crate::{utils::happy_try_variant, Assist, AssistCtx, AssistId};
9use ast::edit::IndentLevel;
10 9
11// Assist: replace_unwrap_with_match 10// Assist: replace_unwrap_with_match
12// 11//
@@ -38,42 +37,27 @@ pub(crate) fn replace_unwrap_with_match(ctx: AssistCtx) -> Option<Assist> {
38 } 37 }
39 let caller = method_call.expr()?; 38 let caller = method_call.expr()?;
40 let ty = ctx.sema.type_of_expr(&caller)?; 39 let ty = ctx.sema.type_of_expr(&caller)?;
40 let happy_variant = happy_try_variant(ctx.sema, &ty)?;
41 41
42 let type_name = ty.as_adt()?.name(ctx.sema.db).to_string(); 42 ctx.add_assist(AssistId("replace_unwrap_with_match"), "Replace unwrap with match", |edit| {
43 let ok_path = make::path_unqualified(make::path_segment(make::name_ref(happy_variant)));
44 let it = make::bind_pat(make::name("a")).into();
45 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
43 46
44 for (unwrap_type, variant_name) in [("Result", "Ok"), ("Option", "Some")].iter() { 47 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a")));
45 if &type_name == unwrap_type { 48 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path));
46 return ctx.add_assist(
47 AssistId("replace_unwrap_with_match"),
48 "Replace unwrap with match",
49 |edit| {
50 let ok_path =
51 make::path_unqualified(make::path_segment(make::name_ref(variant_name)));
52 let it = make::bind_pat(make::name("a")).into();
53 let ok_tuple = make::tuple_struct_pat(ok_path, iter::once(it)).into();
54 49
55 let bind_path = make::path_unqualified(make::path_segment(make::name_ref("a"))); 50 let unreachable_call = make::unreachable_macro_call().into();
56 let ok_arm = make::match_arm(iter::once(ok_tuple), make::expr_path(bind_path)); 51 let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call);
57 52
58 let unreachable_call = make::unreachable_macro_call().into(); 53 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
59 let err_arm = make::match_arm( 54 let match_expr = make::expr_match(caller.clone(), match_arm_list);
60 iter::once(make::placeholder_pat().into()), 55 let match_expr = IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr);
61 unreachable_call,
62 );
63 56
64 let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]); 57 edit.target(method_call.syntax().text_range());
65 let match_expr = make::expr_match(caller.clone(), match_arm_list); 58 edit.set_cursor(caller.syntax().text_range().start());
66 let match_expr = 59 edit.replace_ast::<ast::Expr>(method_call.into(), match_expr);
67 IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr); 60 })
68
69 edit.target(method_call.syntax().text_range());
70 edit.set_cursor(caller.syntax().text_range().start());
71 edit.replace_ast::<ast::Expr>(method_call.into(), match_expr);
72 },
73 );
74 }
75 }
76 None
77} 61}
78 62
79#[cfg(test)] 63#[cfg(test)]
diff --git a/crates/ra_assists/src/utils.rs b/crates/ra_assists/src/utils.rs
index 3d6c59bda..316c8b20f 100644
--- a/crates/ra_assists/src/utils.rs
+++ b/crates/ra_assists/src/utils.rs
@@ -1,7 +1,7 @@
1//! Assorted functions shared by several assists. 1//! Assorted functions shared by several assists.
2pub(crate) mod insert_use; 2pub(crate) mod insert_use;
3 3
4use hir::Semantics; 4use hir::{Adt, Semantics, Type};
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{
7 ast::{self, make, NameOwner}, 7 ast::{self, make, NameOwner},
@@ -99,3 +99,16 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
99 _ => None, 99 _ => None,
100 } 100 }
101} 101}
102
103pub(crate) fn happy_try_variant(sema: &Semantics<RootDatabase>, ty: &Type) -> Option<&'static str> {
104 let enum_ = match ty.as_adt() {
105 Some(Adt::Enum(it)) => it,
106 _ => return None,
107 };
108 [("Result", "Ok"), ("Option", "Some")].iter().find_map(|(known_type, happy_case)| {
109 if &enum_.name(sema.db).to_string() == known_type {
110 return Some(*happy_case);
111 }
112 None
113 })
114}