Skip to content

Commit fa80ddf

Browse files
committed
Reorder impl items based on its kind
The ordering is defined as follows: type < cosnt < macro < method Items that are same kind will not be reordered: that is, the item that an user has put first comes first.
1 parent 94f5a05 commit fa80ddf

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

src/items.rs

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Formatting top-level items - functions, structs, enums, traits, impls.
1212

1313
use std::borrow::Cow;
14-
use std::cmp::min;
14+
use std::cmp::{min, Ordering};
1515

1616
use config::lists::*;
1717
use regex::Regex;
@@ -660,12 +660,55 @@ pub fn format_impl(
660660

661661
if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
662662
let mut visitor = FmtVisitor::from_context(context);
663-
visitor.block_indent = offset.block_only().block_indent(context.config);
663+
let item_indent = offset.block_only().block_indent(context.config);
664+
visitor.block_indent = item_indent;
664665
visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
665666

666667
visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
667-
for item in items {
668-
visitor.visit_impl_item(item);
668+
if context.config.reorder_impl_items() {
669+
// Create visitor for each items, then reorder them.
670+
let mut buffer = vec![];
671+
for item in items {
672+
visitor.visit_impl_item(item);
673+
buffer.push((visitor.buffer.clone(), item.clone()));
674+
visitor.buffer.clear();
675+
}
676+
// type -> const -> macro -> method
677+
use ast::ImplItemKind::*;
678+
fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool {
679+
match (a, b) {
680+
(Type(..), Type(..)) | (Const(..), Const(..)) => false,
681+
_ => true,
682+
}
683+
}
684+
685+
buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) {
686+
(Type(..), _) => Ordering::Less,
687+
(_, Type(..)) => Ordering::Greater,
688+
(Const(..), _) => Ordering::Less,
689+
(_, Const(..)) => Ordering::Greater,
690+
(Macro(..), _) => Ordering::Less,
691+
(_, Macro(..)) => Ordering::Greater,
692+
_ => Ordering::Less,
693+
});
694+
let mut prev_kind = None;
695+
for (buf, item) in buffer {
696+
// Make sure that there are at least a single empty line between
697+
// different impl items.
698+
if prev_kind
699+
.as_ref()
700+
.map_or(false, |prev_kind| need_empty_line(prev_kind, &item.node))
701+
{
702+
visitor.push_str("\n");
703+
}
704+
visitor.push_str(&item_indent.to_string_with_newline(context.config));
705+
visitor.push_str(buf.trim());
706+
prev_kind = Some(item.node.clone());
707+
}
708+
} else {
709+
for item in items {
710+
visitor.visit_impl_item(item);
711+
}
669712
}
670713

671714
visitor.format_missing(item.span.hi() - BytePos(1));

0 commit comments

Comments
 (0)