|
11 | 11 | // Formatting top-level items - functions, structs, enums, traits, impls.
|
12 | 12 |
|
13 | 13 | use std::borrow::Cow;
|
14 |
| -use std::cmp::min; |
| 14 | +use std::cmp::{min, Ordering}; |
15 | 15 |
|
16 | 16 | use config::lists::*;
|
17 | 17 | use regex::Regex;
|
@@ -660,12 +660,55 @@ pub fn format_impl(
|
660 | 660 |
|
661 | 661 | if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
|
662 | 662 | 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; |
664 | 665 | visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
|
665 | 666 |
|
666 | 667 | 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 | + } |
669 | 712 | }
|
670 | 713 |
|
671 | 714 | visitor.format_missing(item.span.hi() - BytePos(1));
|
|
0 commit comments