@@ -109,7 +109,13 @@ pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Optio
109
109
}
110
110
return signature_help_for_record_pat( & sema, record, token) ;
111
111
} ,
112
- ast:: TupleStructPat ( tuple_pat) => { } ,
112
+ ast:: TupleStructPat ( tuple_pat) => {
113
+ let cursor_outside = tuple_pat. r_paren_token( ) . as_ref( ) == Some ( & token) ;
114
+ if cursor_outside {
115
+ continue ;
116
+ }
117
+ return signature_help_for_tuple_struct_pat( & sema, tuple_pat, token) ;
118
+ } ,
113
119
_ => ( ) ,
114
120
}
115
121
}
@@ -367,6 +373,90 @@ fn signature_help_for_record_lit(
367
373
)
368
374
}
369
375
376
+ fn signature_help_for_record_pat (
377
+ sema : & Semantics < ' _ , RootDatabase > ,
378
+ record : ast:: RecordPat ,
379
+ token : SyntaxToken ,
380
+ ) -> Option < SignatureHelp > {
381
+ signature_help_for_record_ (
382
+ sema,
383
+ record. record_pat_field_list ( ) ?. syntax ( ) . children_with_tokens ( ) ,
384
+ & record. path ( ) ?,
385
+ record
386
+ . record_pat_field_list ( ) ?
387
+ . fields ( )
388
+ . filter_map ( |field| sema. resolve_record_pat_field ( & field) ) ,
389
+ token,
390
+ )
391
+ }
392
+
393
+ fn signature_help_for_tuple_struct_pat (
394
+ sema : & Semantics < ' _ , RootDatabase > ,
395
+ pat : ast:: TupleStructPat ,
396
+ token : SyntaxToken ,
397
+ ) -> Option < SignatureHelp > {
398
+ let rest_pat = pat. fields ( ) . find ( |it| matches ! ( it, ast:: Pat :: RestPat ( _) ) ) ;
399
+ let is_left_of_rest_pat =
400
+ rest_pat. map_or ( true , |it| token. text_range ( ) . start ( ) < it. syntax ( ) . text_range ( ) . end ( ) ) ;
401
+
402
+ let mut res = SignatureHelp {
403
+ doc : None ,
404
+ signature : String :: new ( ) ,
405
+ parameters : vec ! [ ] ,
406
+ active_parameter : None ,
407
+ } ;
408
+
409
+ let db = sema. db ;
410
+ let path_res = sema. resolve_path ( & pat. path ( ) ?) ?;
411
+ let fields: Vec < _ > = if let PathResolution :: Def ( ModuleDef :: Variant ( variant) ) = path_res {
412
+ let en = variant. parent_enum ( db) ;
413
+
414
+ res. doc = en. docs ( db) . map ( |it| it. into ( ) ) ;
415
+ format_to ! ( res. signature, "enum {}::{} (" , en. name( db) , variant. name( db) ) ;
416
+ variant. fields ( db)
417
+ } else {
418
+ let adt = match path_res {
419
+ PathResolution :: SelfType ( imp) => imp. self_ty ( db) . as_adt ( ) ?,
420
+ PathResolution :: Def ( ModuleDef :: Adt ( adt) ) => adt,
421
+ _ => return None ,
422
+ } ;
423
+
424
+ match adt {
425
+ hir:: Adt :: Struct ( it) => {
426
+ res. doc = it. docs ( db) . map ( |it| it. into ( ) ) ;
427
+ format_to ! ( res. signature, "struct {} (" , it. name( db) ) ;
428
+ it. fields ( db)
429
+ }
430
+ _ => return None ,
431
+ }
432
+ } ;
433
+ let commas = pat
434
+ . syntax ( )
435
+ . children_with_tokens ( )
436
+ . filter_map ( syntax:: NodeOrToken :: into_token)
437
+ . filter ( |t| t. kind ( ) == syntax:: T ![ , ] ) ;
438
+ res. active_parameter = Some ( if is_left_of_rest_pat {
439
+ commas. take_while ( |t| t. text_range ( ) . start ( ) <= token. text_range ( ) . start ( ) ) . count ( )
440
+ } else {
441
+ let n_commas = commas
442
+ . collect :: < Vec < _ > > ( )
443
+ . into_iter ( )
444
+ . rev ( )
445
+ . take_while ( |t| t. text_range ( ) . start ( ) > token. text_range ( ) . start ( ) )
446
+ . count ( ) ;
447
+ fields. len ( ) . saturating_sub ( 1 ) . saturating_sub ( n_commas)
448
+ } ) ;
449
+
450
+ let mut buf = String :: new ( ) ;
451
+ for ty in fields. into_iter ( ) . map ( |it| it. ty ( db) ) {
452
+ format_to ! ( buf, "{}" , ty. display_truncated( db, Some ( 20 ) ) ) ;
453
+ res. push_call_param ( & buf) ;
454
+ buf. clear ( ) ;
455
+ }
456
+ res. signature . push_str ( ")" ) ;
457
+ Some ( res)
458
+ }
459
+
370
460
fn signature_help_for_record_ (
371
461
sema : & Semantics < ' _ , RootDatabase > ,
372
462
field_list_children : SyntaxElementChildren ,
@@ -442,23 +532,6 @@ fn signature_help_for_record_(
442
532
Some ( res)
443
533
}
444
534
445
- fn signature_help_for_record_pat (
446
- sema : & Semantics < ' _ , RootDatabase > ,
447
- record : ast:: RecordPat ,
448
- token : SyntaxToken ,
449
- ) -> Option < SignatureHelp > {
450
- signature_help_for_record_ (
451
- sema,
452
- record. record_pat_field_list ( ) ?. syntax ( ) . children_with_tokens ( ) ,
453
- & record. path ( ) ?,
454
- record
455
- . record_pat_field_list ( ) ?
456
- . fields ( )
457
- . filter_map ( |field| sema. resolve_record_pat_field ( & field) ) ,
458
- token,
459
- )
460
- }
461
-
462
535
#[ cfg( test) ]
463
536
mod tests {
464
537
use std:: iter;
@@ -480,6 +553,7 @@ mod tests {
480
553
( database, FilePosition { file_id, offset } )
481
554
}
482
555
556
+ #[ track_caller]
483
557
fn check ( ra_fixture : & str , expect : Expect ) {
484
558
let fixture = format ! (
485
559
r#"
@@ -931,6 +1005,119 @@ fn main() {
931
1005
) ;
932
1006
}
933
1007
1008
+ #[ test]
1009
+ fn tuple_struct_pat ( ) {
1010
+ check (
1011
+ r#"
1012
+ /// A cool tuple struct
1013
+ struct S(u32, i32);
1014
+ fn main() {
1015
+ let S(0, $0);
1016
+ }
1017
+ "# ,
1018
+ expect ! [ [ r#"
1019
+ A cool tuple struct
1020
+ ------
1021
+ struct S (u32, i32)
1022
+ --- ^^^
1023
+ "# ] ] ,
1024
+ ) ;
1025
+ }
1026
+
1027
+ #[ test]
1028
+ fn tuple_struct_pat_rest ( ) {
1029
+ check (
1030
+ r#"
1031
+ /// A cool tuple struct
1032
+ struct S(u32, i32, f32, u16);
1033
+ fn main() {
1034
+ let S(0, .., $0);
1035
+ }
1036
+ "# ,
1037
+ expect ! [ [ r#"
1038
+ A cool tuple struct
1039
+ ------
1040
+ struct S (u32, i32, f32, u16)
1041
+ --- --- --- ^^^
1042
+ "# ] ] ,
1043
+ ) ;
1044
+ check (
1045
+ r#"
1046
+ /// A cool tuple struct
1047
+ struct S(u32, i32, f32, u16, u8);
1048
+ fn main() {
1049
+ let S(0, .., $0, 0);
1050
+ }
1051
+ "# ,
1052
+ expect ! [ [ r#"
1053
+ A cool tuple struct
1054
+ ------
1055
+ struct S (u32, i32, f32, u16, u8)
1056
+ --- --- --- ^^^ --
1057
+ "# ] ] ,
1058
+ ) ;
1059
+ check (
1060
+ r#"
1061
+ /// A cool tuple struct
1062
+ struct S(u32, i32, f32, u16);
1063
+ fn main() {
1064
+ let S($0, .., 1);
1065
+ }
1066
+ "# ,
1067
+ expect ! [ [ r#"
1068
+ A cool tuple struct
1069
+ ------
1070
+ struct S (u32, i32, f32, u16)
1071
+ ^^^ --- --- ---
1072
+ "# ] ] ,
1073
+ ) ;
1074
+ check (
1075
+ r#"
1076
+ /// A cool tuple struct
1077
+ struct S(u32, i32, f32, u16, u8);
1078
+ fn main() {
1079
+ let S(1, .., 1, $0, 2);
1080
+ }
1081
+ "# ,
1082
+ expect ! [ [ r#"
1083
+ A cool tuple struct
1084
+ ------
1085
+ struct S (u32, i32, f32, u16, u8)
1086
+ --- --- --- ^^^ --
1087
+ "# ] ] ,
1088
+ ) ;
1089
+ check (
1090
+ r#"
1091
+ /// A cool tuple struct
1092
+ struct S(u32, i32, f32, u16);
1093
+ fn main() {
1094
+ let S(1, $0.., 1);
1095
+ }
1096
+ "# ,
1097
+ expect ! [ [ r#"
1098
+ A cool tuple struct
1099
+ ------
1100
+ struct S (u32, i32, f32, u16)
1101
+ --- ^^^ --- ---
1102
+ "# ] ] ,
1103
+ ) ;
1104
+ check (
1105
+ r#"
1106
+ /// A cool tuple struct
1107
+ struct S(u32, i32, f32, u16);
1108
+ fn main() {
1109
+ let S(1, ..$0, 1);
1110
+ }
1111
+ "# ,
1112
+ expect ! [ [ r#"
1113
+ A cool tuple struct
1114
+ ------
1115
+ struct S (u32, i32, f32, u16)
1116
+ --- ^^^ --- ---
1117
+ "# ] ] ,
1118
+ ) ;
1119
+ }
1120
+
934
1121
#[ test]
935
1122
fn generic_struct ( ) {
936
1123
check (
0 commit comments