@@ -80,7 +80,7 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext) -> Option<TupleData> {
8080 . map ( |i| generate_name ( i, & name, & ident_pat, & usages, ctx) )
8181 . collect_vec ( ) ;
8282
83- Some ( TupleData { range, field_names, usages } )
83+ Some ( TupleData { ident_pat , range, field_names, usages } )
8484}
8585
8686fn generate_name (
@@ -95,31 +95,39 @@ fn generate_name(
9595}
9696
9797struct TupleData {
98- // ident_pat: IdentPat,
98+ ident_pat : IdentPat ,
9999 // name: String,
100100 range : TextRange ,
101101 field_names : Vec < String > ,
102102 // field_types: Vec<Type>,
103103 usages : Option < UsageSearchResult > ,
104104}
105105fn 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
108112 . field_names
109113 . 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) ) ) ) ;
111115 ast:: make:: tuple_pat ( fields)
112116 } ;
113117
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 ( ) ;
114125 match ctx. config . snippet_cap {
115126 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) ;
120128 builder. replace_snippet ( cap, data. range , snip) ;
121129 }
122- None => builder. replace ( data. range , new_tuple . to_string ( ) ) ,
130+ None => builder. replace ( data. range , text ) ,
123131 } ;
124132}
125133
@@ -462,6 +470,74 @@ fn foo(t: &(usize, usize)) -> usize {
462470 )
463471 }
464472
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+
465541 #[ test]
466542 fn dont_trigger_for_non_tuple_reference ( ) {
467543 check_assist_not_applicable (
@@ -733,6 +809,31 @@ fn main() {
733809 "# ,
734810 )
735811 }
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+ }
736837
737838 #[ test]
738839 fn in_for ( ) {
0 commit comments