@@ -12,6 +12,7 @@ use rustc_ast::ast;
12
12
use rustc_span:: { symbol:: sym, Span } ;
13
13
14
14
use crate :: config:: Config ;
15
+ use crate :: formatting:: imports:: UseSegment ;
15
16
use crate :: formatting:: modules:: { get_mod_inner_attrs, FileModMap } ;
16
17
use crate :: formatting:: {
17
18
imports:: { merge_use_trees, UseTree } ,
@@ -227,19 +228,32 @@ fn rewrite_reorderable_items(
227
228
if context. config . merge_imports ( ) {
228
229
normalized_items = merge_use_trees ( normalized_items) ;
229
230
}
230
- normalized_items. sort ( ) ;
231
+
232
+ let reordered_imports = if context. config . reorder_imports_opinionated ( ) {
233
+ group_and_sort_imports ( normalized_items)
234
+ } else {
235
+ normalized_items. sort ( ) ;
236
+ vec ! [ normalized_items]
237
+ } ;
231
238
232
239
// 4 = "use ", 1 = ";"
233
240
let nested_shape = shape. offset_left ( 4 ) ?. sub_width ( 1 ) ?;
234
- let item_vec: Vec < _ > = normalized_items
241
+ let item_vec: Vec < _ > = reordered_imports
235
242
. into_iter ( )
236
- . map ( |use_tree| ListItem {
237
- item : use_tree. rewrite_top_level ( context, nested_shape) ,
238
- ..use_tree. list_item . unwrap_or_else ( ListItem :: empty)
243
+ . filter ( |use_group| !use_group. is_empty ( ) )
244
+ . map ( |use_group| {
245
+ let item_vec: Vec < _ > = use_group
246
+ . into_iter ( )
247
+ . map ( |use_tree| ListItem {
248
+ item : use_tree. rewrite_top_level ( context, nested_shape) ,
249
+ ..use_tree. list_item . unwrap_or_else ( ListItem :: empty)
250
+ } )
251
+ . collect ( ) ;
252
+ wrap_reorderable_items ( context, & item_vec, nested_shape)
239
253
} )
240
- . collect ( ) ;
254
+ . collect :: < Option < Vec < _ > > > ( ) ? ;
241
255
242
- wrap_reorderable_items ( context , & item_vec, nested_shape )
256
+ Some ( item_vec. join ( " \n \n " ) )
243
257
}
244
258
_ => {
245
259
let list_items = itemize_list (
@@ -268,6 +282,38 @@ fn contains_macro_use_attr(attrs: &[ast::Attribute]) -> bool {
268
282
crate :: formatting:: attr:: contains_name ( attrs, sym:: macro_use)
269
283
}
270
284
285
+ /// Divides imports into three groups, corresponding to standard, external
286
+ /// and local imports. Sorts each subgroup.
287
+ fn group_and_sort_imports ( uts : Vec < UseTree > ) -> Vec < Vec < UseTree > > {
288
+ let mut std_imports = Vec :: new ( ) ;
289
+ let mut external_imports = Vec :: new ( ) ;
290
+ let mut local_imports = Vec :: new ( ) ;
291
+
292
+ for ut in uts. into_iter ( ) {
293
+ if ut. path . is_empty ( ) {
294
+ external_imports. push ( ut) ;
295
+ continue ;
296
+ }
297
+ match & ut. path [ 0 ] {
298
+ UseSegment :: Ident ( id, _) => match id. as_ref ( ) {
299
+ "std" | "alloc" | "core" => std_imports. push ( ut) ,
300
+ _ => external_imports. push ( ut) ,
301
+ } ,
302
+ UseSegment :: Slf ( _) | UseSegment :: Super ( _) | UseSegment :: Crate ( _) => {
303
+ local_imports. push ( ut)
304
+ }
305
+ // These are probably illegal here
306
+ UseSegment :: Glob | UseSegment :: List ( _) => external_imports. push ( ut) ,
307
+ }
308
+ }
309
+
310
+ std_imports. sort ( ) ;
311
+ external_imports. sort ( ) ;
312
+ local_imports. sort ( ) ;
313
+
314
+ vec ! [ std_imports, external_imports, local_imports]
315
+ }
316
+
271
317
/// A simplified version of `ast::ItemKind`.
272
318
#[ derive( Debug , PartialEq , Eq , Copy , Clone ) ]
273
319
enum ReorderableItemKind {
@@ -311,11 +357,10 @@ impl ReorderableItemKind {
311
357
}
312
358
}
313
359
314
- fn in_group ( self ) -> bool {
360
+ fn in_group ( self , config : & Config ) -> bool {
315
361
match self {
316
- ReorderableItemKind :: ExternCrate
317
- | ReorderableItemKind :: Mod
318
- | ReorderableItemKind :: Use => true ,
362
+ ReorderableItemKind :: ExternCrate | ReorderableItemKind :: Mod => true ,
363
+ ReorderableItemKind :: Use => !config. reorder_imports_opinionated ( ) ,
319
364
ReorderableItemKind :: Other => false ,
320
365
}
321
366
}
@@ -376,7 +421,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
376
421
let item_kind = ReorderableItemKind :: from ( items[ 0 ] , self . file_mod_map ) ;
377
422
if item_kind. is_reorderable ( self . config ) {
378
423
let visited_items_num =
379
- self . walk_reorderable_items ( items, item_kind, item_kind. in_group ( ) ) ;
424
+ self . walk_reorderable_items ( items, item_kind, item_kind. in_group ( self . config ) ) ;
380
425
let ( _, rest) = items. split_at ( visited_items_num) ;
381
426
items = rest;
382
427
} else {
0 commit comments