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