aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs')
-rw-r--r--crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs b/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs
new file mode 100644
index 000000000..30c371480
--- /dev/null
+++ b/crates/ra_ide_api_light/src/assists/replace_if_let_with_match.rs
@@ -0,0 +1,92 @@
1use ra_syntax::{
2 AstNode, SyntaxKind::{L_CURLY, R_CURLY, WHITESPACE},
3 ast,
4};
5
6use crate::assists::{AssistCtx, Assist};
7
8pub fn replace_if_let_with_match(ctx: AssistCtx) -> 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 = if_expr.else_branch()?;
15
16 ctx.build("replace with match", |edit| {
17 let match_expr = build_match_expr(expr, pat, then_block, else_block);
18 edit.replace_node_and_indent(if_expr.syntax(), match_expr);
19 edit.set_cursor(if_expr.syntax().range().start())
20 })
21}
22
23fn build_match_expr(
24 expr: &ast::Expr,
25 pat1: &ast::Pat,
26 arm1: &ast::Block,
27 arm2: &ast::Block,
28) -> String {
29 let mut buf = String::new();
30 buf.push_str(&format!("match {} {{\n", expr.syntax().text()));
31 buf.push_str(&format!(
32 " {} => {}\n",
33 pat1.syntax().text(),
34 format_arm(arm1)
35 ));
36 buf.push_str(&format!(" _ => {}\n", format_arm(arm2)));
37 buf.push_str("}");
38 buf
39}
40
41fn format_arm(block: &ast::Block) -> String {
42 match extract_expression(block) {
43 None => block.syntax().text().to_string(),
44 Some(e) => format!("{},", e.syntax().text()),
45 }
46}
47
48fn extract_expression(block: &ast::Block) -> Option<&ast::Expr> {
49 let expr = block.expr()?;
50 let non_trivial_children = block.syntax().children().filter(|it| {
51 !(it == &expr.syntax()
52 || it.kind() == L_CURLY
53 || it.kind() == R_CURLY
54 || it.kind() == WHITESPACE)
55 });
56 if non_trivial_children.count() > 0 {
57 return None;
58 }
59 Some(expr)
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65 use crate::assists::check_assist;
66
67 #[test]
68 fn test_replace_if_let_with_match_unwraps_simple_expressions() {
69 check_assist(
70 replace_if_let_with_match,
71 "
72impl VariantData {
73 pub fn is_struct(&self) -> bool {
74 if <|>let VariantData::Struct(..) = *self {
75 true
76 } else {
77 false
78 }
79 }
80} ",
81 "
82impl VariantData {
83 pub fn is_struct(&self) -> bool {
84 <|>match *self {
85 VariantData::Struct(..) => true,
86 _ => false,
87 }
88 }
89} ",
90 )
91 }
92}