rust/crates/ra_assists/src/replace_if_let_with_match.rs

77 lines
2.1 KiB
Rust
Raw Normal View History

2019-01-10 09:32:02 -06:00
use ra_syntax::{AstNode, ast};
2019-02-03 12:26:35 -06:00
use ra_ide_api_light::formatting::extract_trivial_expression;
use hir::db::HirDatabase;
2019-01-08 05:21:29 -06:00
2019-02-03 12:26:35 -06:00
use crate::{AssistCtx, Assist};
2019-01-08 05:21:29 -06:00
2019-02-03 12:26:35 -06:00
pub(crate) fn replace_if_let_with_match(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
2019-01-08 05:21:29 -06:00
let if_expr: &ast::IfExpr = ctx.node_at_offset()?;
let cond = if_expr.condition()?;
let pat = cond.pat()?;
let expr = cond.expr()?;
let then_block = if_expr.then_branch()?;
let else_block = match if_expr.else_branch()? {
ast::ElseBranchFlavor::Block(it) => it,
ast::ElseBranchFlavor::IfExpr(_) => return None,
};
2019-01-08 05:21:29 -06:00
ctx.build("replace with match", |edit| {
let match_expr = build_match_expr(expr, pat, then_block, else_block);
edit.replace_node_and_indent(if_expr.syntax(), match_expr);
edit.set_cursor(if_expr.syntax().range().start())
})
}
fn build_match_expr(
expr: &ast::Expr,
pat1: &ast::Pat,
arm1: &ast::Block,
arm2: &ast::Block,
) -> String {
let mut buf = String::new();
buf.push_str(&format!("match {} {{\n", expr.syntax().text()));
2019-02-08 05:49:43 -06:00
buf.push_str(&format!(" {} => {}\n", pat1.syntax().text(), format_arm(arm1)));
2019-01-08 05:21:29 -06:00
buf.push_str(&format!(" _ => {}\n", format_arm(arm2)));
buf.push_str("}");
buf
}
fn format_arm(block: &ast::Block) -> String {
2019-01-10 09:32:02 -06:00
match extract_trivial_expression(block) {
2019-01-08 05:21:29 -06:00
None => block.syntax().text().to_string(),
Some(e) => format!("{},", e.syntax().text()),
}
}
#[cfg(test)]
mod tests {
use super::*;
2019-02-03 12:26:35 -06:00
use crate::helpers::check_assist;
2019-01-08 05:21:29 -06:00
#[test]
fn test_replace_if_let_with_match_unwraps_simple_expressions() {
check_assist(
replace_if_let_with_match,
"
impl VariantData {
pub fn is_struct(&self) -> bool {
if <|>let VariantData::Struct(..) = *self {
true
} else {
false
}
}
} ",
"
impl VariantData {
pub fn is_struct(&self) -> bool {
<|>match *self {
VariantData::Struct(..) => true,
_ => false,
}
}
} ",
)
}
}