diff options
Diffstat (limited to 'crates/ra_assists/src/replace_if_let_with_match.rs')
-rw-r--r-- | crates/ra_assists/src/replace_if_let_with_match.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/crates/ra_assists/src/replace_if_let_with_match.rs b/crates/ra_assists/src/replace_if_let_with_match.rs new file mode 100644 index 000000000..f6af47ec9 --- /dev/null +++ b/crates/ra_assists/src/replace_if_let_with_match.rs | |||
@@ -0,0 +1,80 @@ | |||
1 | use ra_syntax::{AstNode, ast}; | ||
2 | use ra_ide_api_light::formatting::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.replace_node_and_indent(if_expr.syntax(), match_expr); | ||
21 | edit.set_cursor(if_expr.syntax().range().start()) | ||
22 | }) | ||
23 | } | ||
24 | |||
25 | fn build_match_expr( | ||
26 | expr: &ast::Expr, | ||
27 | pat1: &ast::Pat, | ||
28 | arm1: &ast::Block, | ||
29 | arm2: &ast::Block, | ||
30 | ) -> String { | ||
31 | let mut buf = String::new(); | ||
32 | buf.push_str(&format!("match {} {{\n", expr.syntax().text())); | ||
33 | buf.push_str(&format!( | ||
34 | " {} => {}\n", | ||
35 | pat1.syntax().text(), | ||
36 | format_arm(arm1) | ||
37 | )); | ||
38 | buf.push_str(&format!(" _ => {}\n", format_arm(arm2))); | ||
39 | buf.push_str("}"); | ||
40 | buf | ||
41 | } | ||
42 | |||
43 | fn format_arm(block: &ast::Block) -> 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; | ||
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 | } | ||