mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 13:03:31 +00:00
Add merge_match_arm assist, bump rowan to 0.6.1
This commit is contained in:
parent
a5fe9f7a87
commit
e6113c0998
4 changed files with 194 additions and 4 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -1326,7 +1326,7 @@ dependencies = [
|
|||
"ra_parser 0.1.0",
|
||||
"ra_rustc_lexer 0.1.0-pre.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ra_text_edit 0.1.0",
|
||||
"rowan 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rowan 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smol_str 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"test_utils 0.1.0",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1596,7 +1596,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rowan"
|
||||
version = "0.6.0"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2281,7 +2281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7790c7f1cc73d831d28dc5a7deb316a006e7848e6a7f467cdb10a0a9e0fb1c"
|
||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||
"checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f"
|
||||
"checksum rowan 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a796c0517d6969224c42e9ef01356363b0a7c57d10ec986c9a600d075666a5ff"
|
||||
"checksum rowan 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03e34c2e5f01d7fa4ab7e6a49da44f59fb38ffb61e6c9f714deb8e157274c2c7"
|
||||
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
||||
"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
|
|
|
@ -93,6 +93,7 @@ mod flip_comma;
|
|||
mod flip_binexpr;
|
||||
mod change_visibility;
|
||||
mod fill_match_arms;
|
||||
mod merge_match_arms;
|
||||
mod introduce_variable;
|
||||
mod inline_local_variable;
|
||||
mod replace_if_let_with_match;
|
||||
|
@ -109,6 +110,7 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
|
|||
add_impl::add_impl,
|
||||
change_visibility::change_visibility,
|
||||
fill_match_arms::fill_match_arms,
|
||||
merge_match_arms::merge_match_arms,
|
||||
flip_comma::flip_comma,
|
||||
flip_binexpr::flip_binexpr,
|
||||
introduce_variable::introduce_variable,
|
||||
|
|
188
crates/ra_assists/src/merge_match_arms.rs
Normal file
188
crates/ra_assists/src/merge_match_arms.rs
Normal file
|
@ -0,0 +1,188 @@
|
|||
use crate::{Assist, AssistCtx, AssistId, TextRange, TextUnit};
|
||||
use hir::db::HirDatabase;
|
||||
use ra_syntax::ast::{AstNode, MatchArm};
|
||||
|
||||
pub(crate) fn merge_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
|
||||
let current_arm = ctx.node_at_offset::<MatchArm>()?;
|
||||
|
||||
// We check if the following match arm matches this one. We could, but don't,
|
||||
// compare to the previous match arm as well.
|
||||
let next = current_arm.syntax().next_sibling();
|
||||
let next_arm = MatchArm::cast(next?.clone())?;
|
||||
|
||||
// Don't try to handle arms with guards for now - can add support for this later
|
||||
if current_arm.guard().is_some() || next_arm.guard().is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let current_expr = current_arm.expr()?;
|
||||
let next_expr = next_arm.expr()?;
|
||||
|
||||
// Check for match arm equality by comparing lengths and then string contents
|
||||
if current_expr.syntax().text_range().len() != next_expr.syntax().text_range().len() {
|
||||
return None;
|
||||
}
|
||||
if current_expr.syntax().text() != next_expr.syntax().text() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let cursor_to_end = current_arm.syntax().text_range().end() - ctx.frange.range.start();
|
||||
|
||||
ctx.add_action(AssistId("merge_match_arms"), "merge match arms", |edit| {
|
||||
fn contains_placeholder(a: &MatchArm) -> bool {
|
||||
a.pats().any(|x| match x.kind() {
|
||||
ra_syntax::ast::PatKind::PlaceholderPat(..) => true,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
let pats = if contains_placeholder(¤t_arm) || contains_placeholder(&next_arm) {
|
||||
"_".into()
|
||||
} else {
|
||||
let ps: Vec<String> = current_arm
|
||||
.pats()
|
||||
.map(|x| x.syntax().to_string())
|
||||
.chain(next_arm.pats().map(|x| x.syntax().to_string()))
|
||||
.collect();
|
||||
ps.join(" | ")
|
||||
};
|
||||
|
||||
let arm = format!("{} => {}", pats, current_expr.syntax().text());
|
||||
let offset = TextUnit::from_usize(arm.len()) - cursor_to_end;
|
||||
|
||||
let start = current_arm.syntax().text_range().start();
|
||||
let end = next_arm.syntax().text_range().end();
|
||||
|
||||
edit.target(current_arm.syntax().text_range());
|
||||
edit.replace(TextRange::from_to(start, end), arm);
|
||||
edit.set_cursor(start + offset);
|
||||
});
|
||||
|
||||
ctx.build()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::merge_match_arms;
|
||||
use crate::helpers::{check_assist, check_assist_not_applicable};
|
||||
|
||||
#[test]
|
||||
fn merge_match_arms_single_patterns() {
|
||||
check_assist(
|
||||
merge_match_arms,
|
||||
r#"
|
||||
#[derive(Debug)]
|
||||
enum X { A, B, C }
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = match x {
|
||||
X::A => { 1i32<|> }
|
||||
X::B => { 1i32 }
|
||||
X::C => { 2i32 }
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Debug)]
|
||||
enum X { A, B, C }
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = match x {
|
||||
X::A | X::B => { 1i32<|> }
|
||||
X::C => { 2i32 }
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_match_arms_multiple_patterns() {
|
||||
check_assist(
|
||||
merge_match_arms,
|
||||
r#"
|
||||
#[derive(Debug)]
|
||||
enum X { A, B, C, D, E }
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = match x {
|
||||
X::A | X::B => {<|> 1i32 },
|
||||
X::C | X::D => { 1i32 },
|
||||
X::E => { 2i32 },
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Debug)]
|
||||
enum X { A, B, C, D, E }
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = match x {
|
||||
X::A | X::B | X::C | X::D => {<|> 1i32 },
|
||||
X::E => { 2i32 },
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_match_arms_placeholder_pattern() {
|
||||
check_assist(
|
||||
merge_match_arms,
|
||||
r#"
|
||||
#[derive(Debug)]
|
||||
enum X { A, B, C, D, E }
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = match x {
|
||||
X::A => { 1i32 },
|
||||
X::B => { 2i<|>32 },
|
||||
_ => { 2i32 }
|
||||
}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Debug)]
|
||||
enum X { A, B, C, D, E }
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = match x {
|
||||
X::A => { 1i32 },
|
||||
_ => { 2i<|>32 }
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merge_match_arms_rejects_guards() {
|
||||
check_assist_not_applicable(
|
||||
merge_match_arms,
|
||||
r#"
|
||||
#[derive(Debug)]
|
||||
enum X {
|
||||
A(i32),
|
||||
B,
|
||||
C
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = match x {
|
||||
X::A(a) if a > 5 => { <|>1i32 },
|
||||
X::B => { 1i32 },
|
||||
X::C => { 2i32 }
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ repository = "https://github.com/rust-analyzer/rust-analyzer"
|
|||
[dependencies]
|
||||
unicode-xid = "0.1.0"
|
||||
itertools = "0.8.0"
|
||||
rowan = "0.6.0"
|
||||
rowan = "0.6.1"
|
||||
ra_rustc_lexer = { version = "0.1.0-pre.2" }
|
||||
|
||||
# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here
|
||||
|
|
Loading…
Reference in a new issue