@@ -34,20 +34,29 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, TextRange};
34
34
// }
35
35
// ```
36
36
pub ( crate ) fn merge_match_arms ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
37
- let current_arm = ctx. find_node_at_offset :: < ast:: MatchArm > ( ) ?;
37
+ let current_arm = ctx. find_node_at_trimmed_offset :: < ast:: MatchArm > ( ) ?;
38
38
// Don't try to handle arms with guards for now - can add support for this later
39
39
if current_arm. guard ( ) . is_some ( ) {
40
40
return None ;
41
41
}
42
42
let current_expr = current_arm. expr ( ) ?;
43
43
let current_text_range = current_arm. syntax ( ) . text_range ( ) ;
44
44
let current_arm_types = get_arm_types ( ctx, & current_arm) ;
45
+ let multi_arm_selection = !ctx. has_empty_selection ( )
46
+ && ctx. selection_trimmed ( ) . end ( ) > current_arm. syntax ( ) . text_range ( ) . end ( ) ;
45
47
46
48
// We check if the following match arms match this one. We could, but don't,
47
49
// compare to the previous match arm as well.
48
50
let arms_to_merge = successors ( Some ( current_arm) , |it| neighbor ( it, Direction :: Next ) )
49
51
. take_while ( |arm| match arm. expr ( ) {
50
52
Some ( expr) if arm. guard ( ) . is_none ( ) => {
53
+ // don't include match arms that start after our selection
54
+ if multi_arm_selection
55
+ && arm. syntax ( ) . text_range ( ) . start ( ) >= ctx. selection_trimmed ( ) . end ( )
56
+ {
57
+ return false ;
58
+ }
59
+
51
60
let same_text = expr. syntax ( ) . text ( ) == current_expr. syntax ( ) . text ( ) ;
52
61
if !same_text {
53
62
return false ;
@@ -298,6 +307,96 @@ fn main() {
298
307
)
299
308
}
300
309
310
+ #[ test]
311
+ fn merge_match_arms_selection_has_leading_whitespace ( ) {
312
+ check_assist (
313
+ merge_match_arms,
314
+ r#"
315
+ #[derive(Debug)]
316
+ enum X { A, B, C }
317
+
318
+ fn main() {
319
+ match X::A {
320
+ $0 X::A => 0,
321
+ X::B => 0,$0
322
+ X::C => 1,
323
+ }
324
+ }
325
+ "# ,
326
+ r#"
327
+ #[derive(Debug)]
328
+ enum X { A, B, C }
329
+
330
+ fn main() {
331
+ match X::A {
332
+ X::A | X::B => 0,
333
+ X::C => 1,
334
+ }
335
+ }
336
+ "# ,
337
+ ) ;
338
+ }
339
+
340
+ #[ test]
341
+ fn merge_match_arms_stops_at_end_of_selection ( ) {
342
+ check_assist (
343
+ merge_match_arms,
344
+ r#"
345
+ #[derive(Debug)]
346
+ enum X { A, B, C }
347
+
348
+ fn main() {
349
+ match X::A {
350
+ $0 X::A => 0,
351
+ X::B => 0,
352
+ $0X::C => 0,
353
+ }
354
+ }
355
+ "# ,
356
+ r#"
357
+ #[derive(Debug)]
358
+ enum X { A, B, C }
359
+
360
+ fn main() {
361
+ match X::A {
362
+ X::A | X::B => 0,
363
+ X::C => 0,
364
+ }
365
+ }
366
+ "# ,
367
+ ) ;
368
+ }
369
+
370
+ #[ test]
371
+ fn merge_match_arms_works_despite_accidental_selection ( ) {
372
+ check_assist (
373
+ merge_match_arms,
374
+ r#"
375
+ #[derive(Debug)]
376
+ enum X { A, B, C }
377
+
378
+ fn main() {
379
+ match X::A {
380
+ X::$0A$0 => 0,
381
+ X::B => 0,
382
+ X::C => 1,
383
+ }
384
+ }
385
+ "# ,
386
+ r#"
387
+ #[derive(Debug)]
388
+ enum X { A, B, C }
389
+
390
+ fn main() {
391
+ match X::A {
392
+ X::A | X::B => 0,
393
+ X::C => 1,
394
+ }
395
+ }
396
+ "# ,
397
+ ) ;
398
+ }
399
+
301
400
#[ test]
302
401
fn merge_match_arms_rejects_guards ( ) {
303
402
check_assist_not_applicable (
0 commit comments