Skip to content

Commit a3fba04

Browse files
authored
Merge pull request #2593 from topecongiro/issue-2455
Add reorder_impl_items config option
2 parents b7ba6f7 + fa80ddf commit a3fba04

File tree

7 files changed

+128
-4
lines changed

7 files changed

+128
-4
lines changed

Configurations.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,42 @@ mod sit;
14131413
**Note** `mod` with `#[macro_export]` will not be reordered since that could change the semantic
14141414
of the original source code.
14151415

1416+
## `reorder_impl_items`
1417+
1418+
Reorder impl items. `type` and `const` are put first, then macros and methods.
1419+
1420+
- **Default value**: `false`
1421+
- **Possible values**: `true`, `false`
1422+
- **Stable**: No
1423+
1424+
#### `false` (default)
1425+
1426+
```rust
1427+
struct Dummy;
1428+
1429+
impl Iterator for Dummy {
1430+
fn next(&mut self) -> Option<Self::Item> {
1431+
None
1432+
}
1433+
1434+
type Item = i32;
1435+
}
1436+
```
1437+
1438+
#### `true`
1439+
1440+
```rust
1441+
struct Dummy;
1442+
1443+
impl Iterator for Dummy {
1444+
type Item = i32;
1445+
1446+
fn next(&mut self) -> Option<Self::Item> {
1447+
None
1448+
}
1449+
}
1450+
```
1451+
14161452
## `report_todo`
14171453

14181454
Report `TODO` items in comments.

src/config/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ create_config! {
7575
reorder_imported_names: bool, true, false,
7676
"Reorder lists of names in import statements alphabetically";
7777
reorder_modules: bool, true, false, "Reorder module statemtents alphabetically in group";
78+
reorder_impl_items: bool, false, false, "Reorder impl items";
7879

7980
// Spaces around punctuation
8081
binop_separator: SeparatorPlace, SeparatorPlace::Front, false,

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));
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// rustfmt-reorder_impl_items: false
2+
3+
struct Dummy;
4+
5+
impl Iterator for Dummy {
6+
fn next(&mut self) -> Option<Self::Item> {
7+
None
8+
}
9+
10+
type Item = i32;
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// rustfmt-reorder_impl_items: true
2+
3+
struct Dummy;
4+
5+
impl Iterator for Dummy {
6+
fn next(&mut self) -> Option<Self::Item> {
7+
None
8+
}
9+
10+
type Item = i32;
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// rustfmt-reorder_impl_items: false
2+
3+
struct Dummy;
4+
5+
impl Iterator for Dummy {
6+
fn next(&mut self) -> Option<Self::Item> {
7+
None
8+
}
9+
10+
type Item = i32;
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// rustfmt-reorder_impl_items: true
2+
3+
struct Dummy;
4+
5+
impl Iterator for Dummy {
6+
type Item = i32;
7+
8+
fn next(&mut self) -> Option<Self::Item> {
9+
None
10+
}
11+
}

0 commit comments

Comments
 (0)