From 94f5a05a6a7e786692dcc6862cb396c1a8803b98 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 4 Apr 2018 14:57:30 +0900 Subject: [PATCH 1/2] Add reorder_impl_items config option --- Configurations.md | 36 +++++++++++++++++++ src/config/mod.rs | 1 + .../configs/reorder_impl_items/false.rs | 11 ++++++ .../source/configs/reorder_impl_items/true.rs | 11 ++++++ .../configs/reorder_impl_items/false.rs | 11 ++++++ .../target/configs/reorder_impl_items/true.rs | 11 ++++++ 6 files changed, 81 insertions(+) create mode 100644 tests/source/configs/reorder_impl_items/false.rs create mode 100644 tests/source/configs/reorder_impl_items/true.rs create mode 100644 tests/target/configs/reorder_impl_items/false.rs create mode 100644 tests/target/configs/reorder_impl_items/true.rs diff --git a/Configurations.md b/Configurations.md index 13c7acaed4f..e10a20e59f5 100644 --- a/Configurations.md +++ b/Configurations.md @@ -1413,6 +1413,42 @@ mod sit; **Note** `mod` with `#[macro_export]` will not be reordered since that could change the semantic of the original source code. +## `reorder_impl_items` + +Reorder impl items. `type` and `const` are put first, then macros and methods. + +- **Default value**: `false` +- **Possible values**: `true`, `false` +- **Stable**: No + +#### `false` (default) + +```rust +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} +``` + +#### `true` + +```rust +struct Dummy; + +impl Iterator for Dummy { + type Item = i32; + + fn next(&mut self) -> Option { + None + } +} +``` + ## `report_todo` Report `TODO` items in comments. diff --git a/src/config/mod.rs b/src/config/mod.rs index 5d5e91ebaed..4c571c8c813 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -75,6 +75,7 @@ create_config! { reorder_imported_names: bool, true, false, "Reorder lists of names in import statements alphabetically"; reorder_modules: bool, true, false, "Reorder module statemtents alphabetically in group"; + reorder_impl_items: bool, false, false, "Reorder impl items"; // Spaces around punctuation binop_separator: SeparatorPlace, SeparatorPlace::Front, false, diff --git a/tests/source/configs/reorder_impl_items/false.rs b/tests/source/configs/reorder_impl_items/false.rs new file mode 100644 index 00000000000..beb99f0fb8e --- /dev/null +++ b/tests/source/configs/reorder_impl_items/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: false + +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} diff --git a/tests/source/configs/reorder_impl_items/true.rs b/tests/source/configs/reorder_impl_items/true.rs new file mode 100644 index 00000000000..612b1c84abd --- /dev/null +++ b/tests/source/configs/reorder_impl_items/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: true + +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} diff --git a/tests/target/configs/reorder_impl_items/false.rs b/tests/target/configs/reorder_impl_items/false.rs new file mode 100644 index 00000000000..beb99f0fb8e --- /dev/null +++ b/tests/target/configs/reorder_impl_items/false.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: false + +struct Dummy; + +impl Iterator for Dummy { + fn next(&mut self) -> Option { + None + } + + type Item = i32; +} diff --git a/tests/target/configs/reorder_impl_items/true.rs b/tests/target/configs/reorder_impl_items/true.rs new file mode 100644 index 00000000000..f2294412a99 --- /dev/null +++ b/tests/target/configs/reorder_impl_items/true.rs @@ -0,0 +1,11 @@ +// rustfmt-reorder_impl_items: true + +struct Dummy; + +impl Iterator for Dummy { + type Item = i32; + + fn next(&mut self) -> Option { + None + } +} From fa80ddf876c9a8a5aa205b1bbbe370ef2996e7c7 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Wed, 4 Apr 2018 14:57:55 +0900 Subject: [PATCH 2/2] 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. --- src/items.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/items.rs b/src/items.rs index 621b2a2074d..940cd245523 100644 --- a/src/items.rs +++ b/src/items.rs @@ -11,7 +11,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. use std::borrow::Cow; -use std::cmp::min; +use std::cmp::{min, Ordering}; use config::lists::*; use regex::Regex; @@ -660,12 +660,55 @@ pub fn format_impl( if !items.is_empty() || contains_comment(&snippet[open_pos..]) { let mut visitor = FmtVisitor::from_context(context); - visitor.block_indent = offset.block_only().block_indent(context.config); + let item_indent = offset.block_only().block_indent(context.config); + visitor.block_indent = item_indent; visitor.last_pos = item.span.lo() + BytePos(open_pos as u32); visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); - for item in items { - visitor.visit_impl_item(item); + if context.config.reorder_impl_items() { + // Create visitor for each items, then reorder them. + let mut buffer = vec![]; + for item in items { + visitor.visit_impl_item(item); + buffer.push((visitor.buffer.clone(), item.clone())); + visitor.buffer.clear(); + } + // type -> const -> macro -> method + use ast::ImplItemKind::*; + fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool { + match (a, b) { + (Type(..), Type(..)) | (Const(..), Const(..)) => false, + _ => true, + } + } + + buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) { + (Type(..), _) => Ordering::Less, + (_, Type(..)) => Ordering::Greater, + (Const(..), _) => Ordering::Less, + (_, Const(..)) => Ordering::Greater, + (Macro(..), _) => Ordering::Less, + (_, Macro(..)) => Ordering::Greater, + _ => Ordering::Less, + }); + let mut prev_kind = None; + for (buf, item) in buffer { + // Make sure that there are at least a single empty line between + // different impl items. + if prev_kind + .as_ref() + .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.node)) + { + visitor.push_str("\n"); + } + visitor.push_str(&item_indent.to_string_with_newline(context.config)); + visitor.push_str(buf.trim()); + prev_kind = Some(item.node.clone()); + } + } else { + for item in items { + visitor.visit_impl_item(item); + } } visitor.format_missing(item.span.hi() - BytePos(1));