diff options
Diffstat (limited to 'crates/ra_assists/src/assists/replace_if_let_with_match.rs')
-rw-r--r-- | crates/ra_assists/src/assists/replace_if_let_with_match.rs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/crates/ra_assists/src/assists/replace_if_let_with_match.rs b/crates/ra_assists/src/assists/replace_if_let_with_match.rs new file mode 100644 index 000000000..401835c57 --- /dev/null +++ b/crates/ra_assists/src/assists/replace_if_let_with_match.rs | |||
@@ -0,0 +1,102 @@ | |||
1 | use format_buf::format; | ||
2 | use hir::db::HirDatabase; | ||
3 | use ra_fmt::extract_trivial_expression; | ||
4 | use ra_syntax::{ast, AstNode}; | ||
5 | |||
6 | use crate::{Assist, AssistCtx, AssistId}; | ||
7 | |||
8 | pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
9 | let if_expr: ast::IfExpr = ctx.node_at_offset()?; | ||
10 | let cond = if_expr.condition()?; | ||
11 | let pat = cond.pat()?; | ||
12 | let expr = cond.expr()?; | ||
13 | let then_block = if_expr.then_branch()?; | ||
14 | let else_block = match if_expr.else_branch()? { | ||
15 | ast::ElseBranch::Block(it) => it, | ||
16 | ast::ElseBranch::IfExpr(_) => return None, | ||
17 | }; | ||
18 | |||
19 | ctx.add_action(AssistId("replace_if_let_with_match"), "replace with match", |edit| { | ||
20 | let match_expr = build_match_expr(expr, pat, then_block, else_block); | ||
21 | edit.target(if_expr.syntax().text_range()); | ||
22 | edit.replace_node_and_indent(if_expr.syntax(), match_expr); | ||
23 | edit.set_cursor(if_expr.syntax().text_range().start()) | ||
24 | }); | ||
25 | |||
26 | ctx.build() | ||
27 | } | ||
28 | |||
29 | fn build_match_expr( | ||
30 | expr: ast::Expr, | ||
31 | pat1: ast::Pat, | ||
32 | arm1: ast::BlockExpr, | ||
33 | arm2: ast::BlockExpr, | ||
34 | ) -> String { | ||
35 | let mut buf = String::new(); | ||
36 | format!(buf, "match {} {{\n", expr.syntax().text()); | ||
37 | format!(buf, " {} => {}\n", pat1.syntax().text(), format_arm(&arm1)); | ||
38 | format!(buf, " _ => {}\n", format_arm(&arm2)); | ||
39 | buf.push_str("}"); | ||
40 | buf | ||
41 | } | ||
42 | |||
43 | fn format_arm(block: &ast::BlockExpr) -> String { | ||
44 | match extract_trivial_expression(block) { | ||
45 | None => block.syntax().text().to_string(), | ||
46 | Some(e) => format!("{},", e.syntax().text()), | ||
47 | } | ||
48 | } | ||
49 | |||
50 | #[cfg(test)] | ||
51 | mod tests { | ||
52 | use super::*; | ||
53 | use crate::helpers::{check_assist, check_assist_target}; | ||
54 | |||
55 | #[test] | ||
56 | fn test_replace_if_let_with_match_unwraps_simple_expressions() { | ||
57 | check_assist( | ||
58 | replace_if_let_with_match, | ||
59 | " | ||
60 | impl VariantData { | ||
61 | pub fn is_struct(&self) -> bool { | ||
62 | if <|>let VariantData::Struct(..) = *self { | ||
63 | true | ||
64 | } else { | ||
65 | false | ||
66 | } | ||
67 | } | ||
68 | } ", | ||
69 | " | ||
70 | impl VariantData { | ||
71 | pub fn is_struct(&self) -> bool { | ||
72 | <|>match *self { | ||
73 | VariantData::Struct(..) => true, | ||
74 | _ => false, | ||
75 | } | ||
76 | } | ||
77 | } ", | ||
78 | ) | ||
79 | } | ||
80 | |||
81 | #[test] | ||
82 | fn replace_if_let_with_match_target() { | ||
83 | check_assist_target( | ||
84 | replace_if_let_with_match, | ||
85 | " | ||
86 | impl VariantData { | ||
87 | pub fn is_struct(&self) -> bool { | ||
88 | if <|>let VariantData::Struct(..) = *self { | ||
89 | true | ||
90 | } else { | ||
91 | false | ||
92 | } | ||
93 | } | ||
94 | } ", | ||
95 | "if let VariantData::Struct(..) = *self { | ||
96 | true | ||
97 | } else { | ||
98 | false | ||
99 | }", | ||
100 | ); | ||
101 | } | ||
102 | } | ||