Skip to content

Commit 7bf9aa2

Browse files
committed
Add reorder_extern_crates and reorder_extern_crates_in_group config options
1 parent b1b2dc8 commit 7bf9aa2

File tree

3 files changed

+68
-29
lines changed

3 files changed

+68
-29
lines changed

src/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@ create_config! {
558558
exceeds `chain_one_line_max`";
559559
imports_indent: IndentStyle, IndentStyle::Visual, "Indent of imports";
560560
imports_layout: ListTactic, ListTactic::Mixed, "Item layout inside a import block";
561+
reorder_extern_crates: bool, true, "Reorder extern crate statements alphabetically";
562+
reorder_extern_crates_in_group: bool, true, "Reorder extern crate statements in group";
561563
reorder_imports: bool, false, "Reorder import statements alphabetically";
562564
reorder_imports_in_group: bool, false, "Reorder import statements in group";
563565
reorder_imported_names: bool, true,

src/imports.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,14 @@ fn compare_view_paths(a: &ast::ViewPath_, b: &ast::ViewPath_) -> Ordering {
113113
}
114114
}
115115

116-
fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option<Ordering> {
116+
fn compare_use_items(context: &RewriteContext, a: &ast::Item, b: &ast::Item) -> Option<Ordering> {
117117
match (&a.node, &b.node) {
118118
(&ast::ItemKind::Use(ref a_vp), &ast::ItemKind::Use(ref b_vp)) => {
119119
Some(compare_view_paths(&a_vp.node, &b_vp.node))
120120
}
121+
(&ast::ItemKind::ExternCrate(..), &ast::ItemKind::ExternCrate(..)) => {
122+
Some(context.snippet(a.span).cmp(&context.snippet(b.span)))
123+
}
121124
_ => None,
122125
}
123126
}
@@ -214,7 +217,9 @@ impl<'a> FmtVisitor<'a> {
214217
.collect::<Vec<_>>();
215218
let pos_after_last_use_item = last_pos_of_prev_use_item;
216219
// Order the imports by view-path & other import path properties
217-
ordered_use_items.sort_by(|a, b| compare_use_items(a.0, b.0).unwrap());
220+
ordered_use_items.sort_by(|a, b| {
221+
compare_use_items(&self.get_context(), a.0, b.0).unwrap()
222+
});
218223
// First, output the span before the first import
219224
let prev_span_str = self.snippet(utils::mk_sp(self.last_pos, pos_before_first_use_item));
220225
// Look for purely trailing space at the start of the prefix snippet before a linefeed, or

src/visitor.rs

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ fn is_use_item(item: &ast::Item) -> bool {
3636
}
3737
}
3838

39+
fn is_extern_crate(item: &ast::Item) -> bool {
40+
match item.node {
41+
ast::ItemKind::ExternCrate(..) => true,
42+
_ => false,
43+
}
44+
}
45+
3946
pub struct FmtVisitor<'a> {
4047
pub parse_session: &'a ParseSess,
4148
pub codemap: &'a CodeMap,
@@ -627,40 +634,65 @@ impl<'a> FmtVisitor<'a> {
627634
false
628635
}
629636

637+
fn reorder_items<F>(
638+
&mut self,
639+
items_left: &[ptr::P<ast::Item>],
640+
is_item: &F,
641+
in_group: bool,
642+
) -> usize
643+
where
644+
F: Fn(&ast::Item) -> bool,
645+
{
646+
let mut last = self.codemap.lookup_line_range(items_left[0].span());
647+
let item_length = items_left
648+
.iter()
649+
.take_while(|ppi| {
650+
is_item(&***ppi) && (!in_group || {
651+
let current = self.codemap.lookup_line_range(ppi.span());
652+
let in_same_group = current.lo < last.hi + 2;
653+
last = current;
654+
in_same_group
655+
})
656+
})
657+
.count();
658+
let items = &items_left[..item_length];
659+
660+
let at_least_one_in_file_lines = items
661+
.iter()
662+
.any(|item| !out_of_file_lines_range!(self, item.span));
663+
664+
if at_least_one_in_file_lines {
665+
self.format_imports(items);
666+
} else {
667+
for item in items {
668+
self.push_rewrite(item.span, None);
669+
}
670+
}
671+
672+
item_length
673+
}
674+
630675
fn walk_mod_items(&mut self, m: &ast::Mod) {
631676
let mut items_left: &[ptr::P<ast::Item>] = &m.items;
632677
while !items_left.is_empty() {
633678
// If the next item is a `use` declaration, then extract it and any subsequent `use`s
634679
// to be potentially reordered within `format_imports`. Otherwise, just format the
635680
// next item for output.
636681
if self.config.reorder_imports() && is_use_item(&*items_left[0]) {
637-
let reorder_imports_in_group = self.config.reorder_imports_in_group();
638-
let mut last = self.codemap.lookup_line_range(items_left[0].span());
639-
let use_item_length = items_left
640-
.iter()
641-
.take_while(|ppi| {
642-
is_use_item(&***ppi) && (!reorder_imports_in_group || {
643-
let current = self.codemap.lookup_line_range(ppi.span());
644-
let in_same_group = current.lo < last.hi + 2;
645-
last = current;
646-
in_same_group
647-
})
648-
})
649-
.count();
650-
let (use_items, rest) = items_left.split_at(use_item_length);
651-
652-
let at_least_one_in_file_lines = use_items
653-
.iter()
654-
.any(|item| !out_of_file_lines_range!(self, item.span));
655-
656-
if at_least_one_in_file_lines {
657-
self.format_imports(use_items);
658-
} else {
659-
for item in use_items {
660-
self.push_rewrite(item.span, None);
661-
}
662-
}
663-
682+
let used_items_len = self.reorder_items(
683+
&items_left,
684+
&is_use_item,
685+
self.config.reorder_imports_in_group(),
686+
);
687+
let (_, rest) = items_left.split_at(used_items_len);
688+
items_left = rest;
689+
} else if self.config.reorder_extern_crates() && is_extern_crate(&*items_left[0]) {
690+
let used_items_len = self.reorder_items(
691+
&items_left,
692+
&is_extern_crate,
693+
self.config.reorder_extern_crates_in_group(),
694+
);
695+
let (_, rest) = items_left.split_at(used_items_len);
664696
items_left = rest;
665697
} else {
666698
// `unwrap()` is safe here because we know `items_left`

0 commit comments

Comments
 (0)