diff options
| author | Laurențiu Nicola <lnicola@users.noreply.github.com> | 2024-11-19 17:45:52 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-19 17:45:52 +0000 |
| commit | af318f732024fc47def3cfc9cd254b61ea1337d7 (patch) | |
| tree | c0557e240841c022ed7fc8aeb7e3943e211e1f25 | |
| parent | 00a8fc1c3d5c919995bbdbebd9a76dac2b4066fb (diff) | |
| parent | effe9ac712da3ae7488c5b7f1211d2f2609a22d7 (diff) | |
| download | rust-af318f732024fc47def3cfc9cd254b61ea1337d7.tar.gz rust-af318f732024fc47def3cfc9cd254b61ea1337d7.zip | |
Merge pull request #18529 from cmrschwarz/allow_leading_whitespace_in_merge_match_arms
Improve selection handling for the `merge_match_arms` assist
| -rw-r--r-- | src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs | 3 | ||||
| -rw-r--r-- | src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs | 101 |
2 files changed, 103 insertions, 1 deletions
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index 1d2d3350f7c..0146369f298 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -116,6 +116,9 @@ impl<'a> AssistContext<'a> { pub(crate) fn find_node_at_offset<N: AstNode>(&self) -> Option<N> { find_node_at_offset(self.source_file.syntax(), self.offset()) } + pub(crate) fn find_node_at_trimmed_offset<N: AstNode>(&self) -> Option<N> { + find_node_at_offset(self.source_file.syntax(), self.trimmed_range.start()) + } pub(crate) fn find_node_at_range<N: AstNode>(&self) -> Option<N> { find_node_at_range(self.source_file.syntax(), self.trimmed_range) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs index 4608e9494bc..f83de931eab 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/merge_match_arms.rs @@ -34,7 +34,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange}; // } // ``` pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { - let current_arm = ctx.find_node_at_offset::<ast::MatchArm>()?; + let current_arm = ctx.find_node_at_trimmed_offset::<ast::MatchArm>()?; // Don't try to handle arms with guards for now - can add support for this later if current_arm.guard().is_some() { return None; @@ -42,12 +42,21 @@ pub(crate) fn merge_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let current_expr = current_arm.expr()?; let current_text_range = current_arm.syntax().text_range(); let current_arm_types = get_arm_types(ctx, ¤t_arm); + let multi_arm_selection = !ctx.has_empty_selection() + && ctx.selection_trimmed().end() > current_arm.syntax().text_range().end(); // We check if the following match arms match this one. We could, but don't, // compare to the previous match arm as well. let arms_to_merge = successors(Some(current_arm), |it| neighbor(it, Direction::Next)) .take_while(|arm| match arm.expr() { Some(expr) if arm.guard().is_none() => { + // don't include match arms that start after our selection + if multi_arm_selection + && arm.syntax().text_range().start() >= ctx.selection_trimmed().end() + { + return false; + } + let same_text = expr.syntax().text() == current_expr.syntax().text(); if !same_text { return false; @@ -299,6 +308,96 @@ fn main() { } #[test] + fn merge_match_arms_selection_has_leading_whitespace() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + $0 X::A => 0, + X::B => 0,$0 + X::C => 1, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 1, + } +} +"#, + ); + } + + #[test] + fn merge_match_arms_stops_at_end_of_selection() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + $0 X::A => 0, + X::B => 0, + $0X::C => 0, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 0, + } +} +"#, + ); + } + + #[test] + fn merge_match_arms_works_despite_accidental_selection() { + check_assist( + merge_match_arms, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::$0A$0 => 0, + X::B => 0, + X::C => 1, + } +} +"#, + r#" +#[derive(Debug)] +enum X { A, B, C } + +fn main() { + match X::A { + X::A | X::B => 0, + X::C => 1, + } +} +"#, + ); + } + + #[test] fn merge_match_arms_rejects_guards() { check_assist_not_applicable( merge_match_arms, |
