@@ -14,15 +14,17 @@ use crate::{utils::get_methods, AssistContext, AssistId, AssistKind, Assists};
14
14
//
15
15
pub ( crate ) fn sort_items ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
16
16
if let Some ( trait_ast) = ctx. find_node_at_offset :: < ast:: Trait > ( ) {
17
- sort_methods_assist ( acc, trait_ast. assoc_item_list ( ) ?)
17
+ add_sort_methods_assist ( acc, trait_ast. assoc_item_list ( ) ?)
18
18
} else if let Some ( impl_ast) = ctx. find_node_at_offset :: < ast:: Impl > ( ) {
19
- sort_methods_assist ( acc, impl_ast. assoc_item_list ( ) ?)
19
+ add_sort_methods_assist ( acc, impl_ast. assoc_item_list ( ) ?)
20
+ } else if let Some ( struct_ast) = ctx. find_node_at_offset :: < ast:: Struct > ( ) {
21
+ add_sort_fields_assist ( acc, struct_ast. field_list ( ) ?)
20
22
} else {
21
23
None
22
24
}
23
25
}
24
26
25
- fn sort_methods_assist ( acc : & mut Assists , item_list : ast:: AssocItemList ) -> Option < ( ) > {
27
+ fn add_sort_methods_assist ( acc : & mut Assists , item_list : ast:: AssocItemList ) -> Option < ( ) > {
26
28
let methods = get_methods ( & item_list) ;
27
29
let sorted = sort_by_name ( & methods) ;
28
30
@@ -45,6 +47,36 @@ fn sort_methods_assist(acc: &mut Assists, item_list: ast::AssocItemList) -> Opti
45
47
)
46
48
}
47
49
50
+ fn add_sort_fields_assist ( acc : & mut Assists , field_list : ast:: FieldList ) -> Option < ( ) > {
51
+ fn record_fields ( field_list : & ast:: FieldList ) -> Option < Vec < ast:: RecordField > > {
52
+ match field_list {
53
+ ast:: FieldList :: RecordFieldList ( it) => Some ( it. fields ( ) . collect ( ) ) ,
54
+ ast:: FieldList :: TupleFieldList ( _) => None ,
55
+ }
56
+ }
57
+
58
+ let fields = record_fields ( & field_list) ?;
59
+ let sorted = sort_by_name ( & fields) ;
60
+
61
+ if fields == sorted {
62
+ cov_mark:: hit!( not_applicable_if_sorted) ;
63
+ return None ;
64
+ }
65
+
66
+ acc. add (
67
+ AssistId ( "sort_items" , AssistKind :: RefactorRewrite ) ,
68
+ "Sort methods alphabetically" ,
69
+ field_list. syntax ( ) . text_range ( ) ,
70
+ |builder| {
71
+ let methods = fields. into_iter ( ) . map ( |fn_| builder. make_mut ( fn_) ) . collect :: < Vec < _ > > ( ) ;
72
+ methods
73
+ . into_iter ( )
74
+ . zip ( sorted)
75
+ . for_each ( |( old, new) | ted:: replace ( old. syntax ( ) , new. clone_for_update ( ) . syntax ( ) ) ) ;
76
+ } ,
77
+ )
78
+ }
79
+
48
80
fn sort_by_name < T : NameOwner + Clone > ( initial : & [ T ] ) -> Vec < T > {
49
81
initial
50
82
. iter ( )
@@ -99,6 +131,22 @@ $0impl Bar {
99
131
)
100
132
}
101
133
134
+ #[ test]
135
+ fn not_applicable_if_struct_sorted ( ) {
136
+ cov_mark:: check!( not_applicable_if_sorted) ;
137
+
138
+ check_assist_not_applicable (
139
+ sort_items,
140
+ r#"
141
+ $0struct Bar {
142
+ a: u32,
143
+ b: u8,
144
+ c: u64,
145
+ }
146
+ "# ,
147
+ )
148
+ }
149
+
102
150
#[ test]
103
151
fn sort_trait ( ) {
104
152
check_assist (
@@ -146,4 +194,70 @@ impl Bar {
146
194
"# ,
147
195
)
148
196
}
197
+
198
+ #[ test]
199
+ fn sort_struct ( ) {
200
+ check_assist (
201
+ sort_items,
202
+ r#"
203
+ $0struct Bar {
204
+ b: u8,
205
+ a: u32,
206
+ c: u64,
207
+ }
208
+ "# ,
209
+ r#"
210
+ struct Bar {
211
+ a: u32,
212
+ b: u8,
213
+ c: u64,
214
+ }
215
+ "# ,
216
+ )
217
+ }
218
+
219
+ #[ test]
220
+ fn sort_generic_struct_with_lifetime ( ) {
221
+ check_assist (
222
+ sort_items,
223
+ r#"
224
+ $0struct Bar<'a, T> {
225
+ d: &'a str,
226
+ b: u8,
227
+ a: T,
228
+ c: u64,
229
+ }
230
+ "# ,
231
+ r#"
232
+ struct Bar<'a, T> {
233
+ a: T,
234
+ b: u8,
235
+ c: u64,
236
+ d: &'a str,
237
+ }
238
+ "# ,
239
+ )
240
+ }
241
+
242
+ #[ test]
243
+ fn sort_struct_fields_diff_len ( ) {
244
+ check_assist (
245
+ sort_items,
246
+ r#"
247
+ $0struct Bar {
248
+ aaa: u8,
249
+ a: usize,
250
+ b: u8,
251
+ }
252
+ "# ,
253
+ r#"
254
+ struct Bar {
255
+ a: usize,
256
+ aaa: u8,
257
+ b: u8,
258
+ }
259
+ "# ,
260
+ )
261
+ }
262
+
149
263
}
0 commit comments