@@ -192,19 +192,20 @@ fn check_field_shorthand(acc: &mut Vec<Diagnostic>, file_id: FileId, node: &Synt
192
192
match_ast ! {
193
193
match node {
194
194
ast:: RecordExpr ( it) => check_expr_field_shorthand( acc, file_id, it) ,
195
- _ => None
195
+ ast:: RecordPat ( it) => check_pat_field_shorthand( acc, file_id, it) ,
196
+ _ => ( )
196
197
}
197
198
} ;
198
199
}
199
200
200
201
fn check_expr_field_shorthand (
201
202
acc : & mut Vec < Diagnostic > ,
202
203
file_id : FileId ,
203
- record_lit : ast:: RecordExpr ,
204
+ record_expr : ast:: RecordExpr ,
204
205
) {
205
- let record_field_list = match record_lit . record_expr_field_list ( ) {
206
+ let record_field_list = match record_expr . record_expr_field_list ( ) {
206
207
Some ( it) => it,
207
- None => ( ) ,
208
+ None => return ,
208
209
} ;
209
210
for record_field in record_field_list. fields ( ) {
210
211
let ( name_ref, expr) = match record_field. name_ref ( ) . zip ( record_field. expr ( ) ) {
@@ -239,6 +240,48 @@ fn check_expr_field_shorthand(
239
240
}
240
241
}
241
242
243
+ fn check_pat_field_shorthand (
244
+ acc : & mut Vec < Diagnostic > ,
245
+ file_id : FileId ,
246
+ record_pat : ast:: RecordPat ,
247
+ ) {
248
+ let record_pat_field_list = match record_pat. record_pat_field_list ( ) {
249
+ Some ( it) => it,
250
+ None => return ,
251
+ } ;
252
+ for record_pat_field in record_pat_field_list. fields ( ) {
253
+ let ( name_ref, pat) = match record_pat_field. name_ref ( ) . zip ( record_pat_field. pat ( ) ) {
254
+ Some ( it) => it,
255
+ None => continue ,
256
+ } ;
257
+
258
+ let field_name = name_ref. syntax ( ) . text ( ) . to_string ( ) ;
259
+ let field_pat = pat. syntax ( ) . text ( ) . to_string ( ) ;
260
+ let field_name_is_tup_index = name_ref. as_tuple_field ( ) . is_some ( ) ;
261
+ if field_name != field_pat || field_name_is_tup_index {
262
+ continue ;
263
+ }
264
+
265
+ let mut edit_builder = TextEdit :: builder ( ) ;
266
+ edit_builder. delete ( record_pat_field. syntax ( ) . text_range ( ) ) ;
267
+ edit_builder. insert ( record_pat_field. syntax ( ) . text_range ( ) . start ( ) , field_name) ;
268
+ let edit = edit_builder. finish ( ) ;
269
+
270
+ let field_range = record_pat_field. syntax ( ) . text_range ( ) ;
271
+ acc. push ( Diagnostic {
272
+ // name: None,
273
+ range : field_range,
274
+ message : "Shorthand struct pattern" . to_string ( ) ,
275
+ severity : Severity :: WeakWarning ,
276
+ fix : Some ( Fix :: new (
277
+ "Use struct field shorthand" ,
278
+ SourceFileEdit { file_id, edit } . into ( ) ,
279
+ field_range,
280
+ ) ) ,
281
+ } ) ;
282
+ }
283
+ }
284
+
242
285
#[ cfg( test) ]
243
286
mod tests {
244
287
use expect_test:: { expect, Expect } ;
@@ -735,7 +778,7 @@ mod a {
735
778
}
736
779
737
780
#[ test]
738
- fn test_check_struct_shorthand_initialization ( ) {
781
+ fn test_check_expr_field_shorthand ( ) {
739
782
check_no_diagnostics (
740
783
r#"
741
784
struct A { a: &'static str }
@@ -786,6 +829,52 @@ fn main() {
786
829
) ;
787
830
}
788
831
832
+ #[ test]
833
+ fn test_check_pat_field_shorthand ( ) {
834
+ check_no_diagnostics (
835
+ r#"
836
+ struct A { a: &'static str }
837
+ fn f(a: A) { let A { a: hello } = a; }
838
+ "# ,
839
+ ) ;
840
+ check_no_diagnostics (
841
+ r#"
842
+ struct A(usize);
843
+ fn f(a: A) { let A { 0: 0 } = a; }
844
+ "# ,
845
+ ) ;
846
+
847
+ check_fix (
848
+ r#"
849
+ struct A { a: &'static str }
850
+ fn f(a: A) {
851
+ let A { a<|>: a } = a;
852
+ }
853
+ "# ,
854
+ r#"
855
+ struct A { a: &'static str }
856
+ fn f(a: A) {
857
+ let A { a } = a;
858
+ }
859
+ "# ,
860
+ ) ;
861
+
862
+ check_fix (
863
+ r#"
864
+ struct A { a: &'static str, b: &'static str }
865
+ fn f(a: A) {
866
+ let A { a<|>: a, b } = a;
867
+ }
868
+ "# ,
869
+ r#"
870
+ struct A { a: &'static str, b: &'static str }
871
+ fn f(a: A) {
872
+ let A { a, b } = a;
873
+ }
874
+ "# ,
875
+ ) ;
876
+ }
877
+
789
878
#[ test]
790
879
fn test_add_field_from_usage ( ) {
791
880
check_fix (
0 commit comments