Skip to content

Commit c801090

Browse files
committed
Opinionated reordering
1 parent 6e1e749 commit c801090

File tree

4 files changed

+68
-17
lines changed

4 files changed

+68
-17
lines changed

src/formatting/reorder.rs

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_ast::ast;
1212
use rustc_span::{symbol::sym, Span};
1313

1414
use crate::config::Config;
15+
use crate::formatting::imports::UseSegment;
1516
use crate::formatting::modules::{get_mod_inner_attrs, FileModMap};
1617
use crate::formatting::{
1718
imports::{merge_use_trees, UseTree},
@@ -227,19 +228,32 @@ fn rewrite_reorderable_items(
227228
if context.config.merge_imports() {
228229
normalized_items = merge_use_trees(normalized_items);
229230
}
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+
};
231238

232239
// 4 = "use ", 1 = ";"
233240
let nested_shape = shape.offset_left(4)?.sub_width(1)?;
234-
let item_vec: Vec<_> = normalized_items
241+
let item_vec: Vec<_> = reordered_imports
235242
.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)
239253
})
240-
.collect();
254+
.collect::<Option<Vec<_>>>()?;
241255

242-
wrap_reorderable_items(context, &item_vec, nested_shape)
256+
Some(item_vec.join("\n\n"))
243257
}
244258
_ => {
245259
let list_items = itemize_list(
@@ -268,6 +282,38 @@ fn contains_macro_use_attr(attrs: &[ast::Attribute]) -> bool {
268282
crate::formatting::attr::contains_name(attrs, sym::macro_use)
269283
}
270284

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+
271317
/// A simplified version of `ast::ItemKind`.
272318
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
273319
enum ReorderableItemKind {
@@ -311,11 +357,10 @@ impl ReorderableItemKind {
311357
}
312358
}
313359

314-
fn in_group(self) -> bool {
360+
fn in_group(self, config: &Config) -> bool {
315361
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(),
319364
ReorderableItemKind::Other => false,
320365
}
321366
}
@@ -376,7 +421,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
376421
let item_kind = ReorderableItemKind::from(items[0], self.file_mod_map);
377422
if item_kind.is_reorderable(self.config) {
378423
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));
380425
let (_, rest) = items.split_at(visited_items_num);
381426
items = rest;
382427
} else {

src/test/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ fn system_tests() {
198198
});
199199
}
200200

201+
#[test]
202+
fn temp() {
203+
let vpb = vec![Path::new("tests/source/import_opinionated.rs").to_path_buf()];
204+
let (_reports, _count, fails) = check_files(vpb, &None);
205+
assert_eq!(fails, 0);
206+
}
207+
201208
#[test]
202209
fn checkstyle_test() {
203210
init_log();

tests/source/import_opinionated.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// rustfmt:reorder_imports_opinionated: true
1+
// rustfmt-reorder_imports_opinionated: true
22
use chrono::Utc;
33
use super::update::convert_publish_payload;
44

tests/target/import_opinionated.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
// rustfmt:reorder_imports_opinionated: true
1+
// rustfmt-reorder_imports_opinionated: true
22
use std::sync::Arc;
33

4+
use broker::database::PooledConnection;
45
use chrono::Utc;
56
use juniper::{FieldError, FieldResult};
67
use uuid::Uuid;
78

8-
use broker::database::PooledConnection;
9-
10-
use crate::models::Event;
119
use super::schema::{Context, Payload};
1210
use super::update::convert_publish_payload;
11+
use crate::models::Event;

0 commit comments

Comments
 (0)