@@ -80,7 +80,7 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext) -> Option<TupleData> {
80
80
. map ( |i| generate_name ( i, & name, & ident_pat, & usages, ctx) )
81
81
. collect_vec ( ) ;
82
82
83
- Some ( TupleData { range, field_names, usages } )
83
+ Some ( TupleData { ident_pat , range, field_names, usages } )
84
84
}
85
85
86
86
fn generate_name (
@@ -95,31 +95,39 @@ fn generate_name(
95
95
}
96
96
97
97
struct TupleData {
98
- // ident_pat: IdentPat,
98
+ ident_pat : IdentPat ,
99
99
// name: String,
100
100
range : TextRange ,
101
101
field_names : Vec < String > ,
102
102
// field_types: Vec<Type>,
103
103
usages : Option < UsageSearchResult > ,
104
104
}
105
105
fn edit_tuple_assignment ( data : & TupleData , builder : & mut AssistBuilder , ctx : & AssistContext ) {
106
- let new_tuple = {
107
- let fields = data
106
+ let tuple_pat = {
107
+ let original = & data. ident_pat ;
108
+ let is_ref = original. ref_token ( ) . is_some ( ) ;
109
+ let is_mut = original. mut_token ( ) . is_some ( ) ;
110
+ let fields =
111
+ data
108
112
. field_names
109
113
. iter ( )
110
- . map ( |name| ast:: Pat :: from ( ast:: make:: ident_pat ( false , false , ast:: make:: name ( name) ) ) ) ;
114
+ . map ( |name| ast:: Pat :: from ( ast:: make:: ident_pat ( is_ref , is_mut , ast:: make:: name ( name) ) ) ) ;
111
115
ast:: make:: tuple_pat ( fields)
112
116
} ;
113
117
118
+ let add_cursor = |text : & str | {
119
+ // place cursor on first tuple item
120
+ let first_tuple = & data. field_names [ 0 ] ;
121
+ text. replacen ( first_tuple, & format ! ( "$0{}" , first_tuple) , 1 )
122
+ } ;
123
+
124
+ let text = tuple_pat. to_string ( ) ;
114
125
match ctx. config . snippet_cap {
115
126
Some ( cap) => {
116
- // No support for placeholders in Code Actions, except for special rust analyzer handling which supports only first `$0`
117
- // -> place cursor on first variable
118
- let mut snip = new_tuple. to_string ( ) ;
119
- snip. insert_str ( 1 , "$0" ) ;
127
+ let snip = add_cursor ( & text) ;
120
128
builder. replace_snippet ( cap, data. range , snip) ;
121
129
}
122
- None => builder. replace ( data. range , new_tuple . to_string ( ) ) ,
130
+ None => builder. replace ( data. range , text ) ,
123
131
} ;
124
132
}
125
133
@@ -462,6 +470,74 @@ fn foo(t: &(usize, usize)) -> usize {
462
470
)
463
471
}
464
472
473
+ #[ test]
474
+ fn with_ref ( ) {
475
+ //Note: `v` has different types:
476
+ // * in 1st: `i32`
477
+ // * in 2nd: `&i32`
478
+ check_assist (
479
+ destructure_tuple_binding,
480
+ r#"
481
+ fn main() {
482
+ let ref $0t = (1,2);
483
+ let v = t.0;
484
+ }
485
+ "# ,
486
+ r#"
487
+ fn main() {
488
+ let (ref $0_0, ref _1) = (1,2);
489
+ let v = _0;
490
+ }
491
+ "# ,
492
+ )
493
+ }
494
+
495
+ #[ test]
496
+ fn with_mut ( ) {
497
+ check_assist (
498
+ destructure_tuple_binding,
499
+ r#"
500
+ fn main() {
501
+ let mut $0t = (1,2);
502
+ t.0 = 42;
503
+ let v = t.0;
504
+ }
505
+ "# ,
506
+ r#"
507
+ fn main() {
508
+ let (mut $0_0, mut _1) = (1,2);
509
+ _0 = 42;
510
+ let v = _0;
511
+ }
512
+ "# ,
513
+ )
514
+ }
515
+
516
+ #[ test]
517
+ fn with_ref_mut ( ) {
518
+ //Note: `v` has different types:
519
+ // * in 1st: `i32`
520
+ // * in 2nd: `&mut i32`
521
+ // Note: 2nd `_0 = 42` isn't valid; requires dereferencing (`*_0`), but isn't handled here!
522
+ check_assist (
523
+ destructure_tuple_binding,
524
+ r#"
525
+ fn main() {
526
+ let ref mut $0t = (1,2);
527
+ t.0 = 42;
528
+ let v = t.0;
529
+ }
530
+ "# ,
531
+ r#"
532
+ fn main() {
533
+ let (ref mut $0_0, ref mut _1) = (1,2);
534
+ _0 = 42;
535
+ let v = _0;
536
+ }
537
+ "# ,
538
+ )
539
+ }
540
+
465
541
#[ test]
466
542
fn dont_trigger_for_non_tuple_reference ( ) {
467
543
check_assist_not_applicable (
@@ -733,6 +809,31 @@ fn main() {
733
809
"# ,
734
810
)
735
811
}
812
+ #[ test]
813
+ fn in_match_reference_option ( ) {
814
+ check_assist (
815
+ destructure_tuple_binding,
816
+ r#"
817
+ //- minicore: option
818
+ fn main() {
819
+ let t = (1,2);
820
+ match Some(&t) {
821
+ Some($0t) => t.1,
822
+ _ => 0,
823
+ };
824
+ }
825
+ "# ,
826
+ r#"
827
+ fn main() {
828
+ let t = (1,2);
829
+ match Some(&t) {
830
+ Some(($0_0, _1)) => _1,
831
+ _ => 0,
832
+ };
833
+ }
834
+ "# ,
835
+ )
836
+ }
736
837
737
838
#[ test]
738
839
fn in_for ( ) {
0 commit comments