Merge pull request #1910 from topecongiro/config-merge_derives
Add merge_derives config option
This commit is contained in:
commit
1a02c35f9b
6 changed files with 179 additions and 20 deletions
|
|
@ -1230,7 +1230,7 @@ Put a match sub-patterns' separator (`|`) in front or back.
|
|||
- **Default value**: `"Back"`
|
||||
- **Possible values**: `"Back"`, `"Front"`
|
||||
|
||||
#### `"Back"`
|
||||
#### `"Back"`:
|
||||
|
||||
```rust
|
||||
match m {
|
||||
|
|
@ -1243,7 +1243,7 @@ match m {
|
|||
}
|
||||
```
|
||||
|
||||
#### `Front`
|
||||
#### `Front`:
|
||||
|
||||
```rust
|
||||
match m {
|
||||
|
|
@ -1265,6 +1265,29 @@ Maximum width of each line
|
|||
|
||||
See also [`error_on_line_overflow`](#error_on_line_overflow).
|
||||
|
||||
## `merge_derives`
|
||||
|
||||
Merge multiple derives into a single one.
|
||||
|
||||
- **Default value**: `true`
|
||||
- **Possible values**: `true`, `false`
|
||||
|
||||
#### `true`:
|
||||
|
||||
```rust
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum Foo {}
|
||||
```
|
||||
|
||||
#### `false`:
|
||||
|
||||
```rust
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Foo {}
|
||||
```
|
||||
|
||||
## `multiline_closure_forces_block`
|
||||
|
||||
Force multiline closure bodies to be wrapped in a block
|
||||
|
|
@ -1272,6 +1295,18 @@ Force multiline closure bodies to be wrapped in a block
|
|||
- **Default value**: `false`
|
||||
- **Possible values**: `false`, `true`
|
||||
|
||||
#### `true`:
|
||||
|
||||
```rust
|
||||
|
||||
result.and_then(|maybe_value| {
|
||||
match maybe_value {
|
||||
None => ...,
|
||||
Some(value) => ...,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### `false`:
|
||||
|
||||
```rust
|
||||
|
|
@ -1281,17 +1316,6 @@ result.and_then(|maybe_value| match maybe_value {
|
|||
})
|
||||
```
|
||||
|
||||
#### `true`:
|
||||
|
||||
```rust
|
||||
result.and_then(|maybe_value| {
|
||||
match maybe_value {
|
||||
None => ...,
|
||||
Some(value) => ...,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## `multiline_match_arm_forces_block`
|
||||
|
||||
Force multiline match arm bodies to be wrapped in a block
|
||||
|
|
|
|||
|
|
@ -619,6 +619,7 @@ create_config! {
|
|||
"Force multiline closure bodies to be wrapped in a block";
|
||||
multiline_match_arm_forces_block: bool, false,
|
||||
"Force multiline match arm bodies to be wrapped in a block";
|
||||
merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one";
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ use config::{Config, IndentStyle};
|
|||
use rewrite::RewriteContext;
|
||||
use utils::{first_line_width, last_line_width, mk_sp};
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
/// Formatting tactic for lists. This will be cast down to a
|
||||
/// DefinitiveListTactic depending on the number and length of the items and
|
||||
/// their comments.
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum ListTactic {
|
||||
// One item per row.
|
||||
Vertical,
|
||||
|
|
@ -144,8 +144,8 @@ impl ListItem {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
/// The definitive formatting tactic for lists.
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum DefinitiveListTactic {
|
||||
Vertical,
|
||||
Horizontal,
|
||||
|
|
|
|||
|
|
@ -925,7 +925,10 @@ impl<'a> Rewrite for [ast::Attribute] {
|
|||
}
|
||||
let indent = shape.indent.to_string(context.config);
|
||||
|
||||
for (i, a) in self.iter().enumerate() {
|
||||
let mut derive_args = Vec::new();
|
||||
|
||||
let mut iter = self.iter().enumerate().peekable();
|
||||
while let Some((i, a)) = iter.next() {
|
||||
let a_str = try_opt!(a.rewrite(context, shape));
|
||||
|
||||
// Write comments and blank lines between attributes.
|
||||
|
|
@ -952,17 +955,62 @@ impl<'a> Rewrite for [ast::Attribute] {
|
|||
} else if multi_line {
|
||||
result.push('\n');
|
||||
}
|
||||
result.push_str(&indent);
|
||||
if derive_args.is_empty() {
|
||||
result.push_str(&indent);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the attribute itself.
|
||||
result.push_str(&a_str);
|
||||
let mut insert_new_line = true;
|
||||
if context.config.merge_derives() {
|
||||
// If the attribute is `#[derive(...)]`, take the arguments.
|
||||
if let Some(mut args) = get_derive_args(context, a) {
|
||||
derive_args.append(&mut args);
|
||||
match iter.peek() {
|
||||
// If the next attribute is `#[derive(...)]` as well, skip rewriting.
|
||||
Some(&(_, next_attr)) if is_derive(next_attr) => insert_new_line = false,
|
||||
// If not, rewrite the merged derives.
|
||||
_ => {
|
||||
result.push_str(&format!("#[derive({})]", derive_args.join(", ")));
|
||||
derive_args.clear();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.push_str(&a_str);
|
||||
}
|
||||
} else {
|
||||
result.push_str(&a_str);
|
||||
}
|
||||
|
||||
if i < self.len() - 1 {
|
||||
if insert_new_line && i < self.len() - 1 {
|
||||
result.push('\n');
|
||||
}
|
||||
}
|
||||
|
||||
Some(result)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_derive(attr: &ast::Attribute) -> bool {
|
||||
match attr.meta() {
|
||||
Some(meta_item) => match meta_item.node {
|
||||
ast::MetaItemKind::List(..) => meta_item.name.as_str() == "derive",
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the arguments of `#[derive(...)]`.
|
||||
fn get_derive_args(context: &RewriteContext, attr: &ast::Attribute) -> Option<Vec<String>> {
|
||||
attr.meta().and_then(|meta_item| match meta_item.node {
|
||||
ast::MetaItemKind::List(ref args) if meta_item.name.as_str() == "derive" => {
|
||||
// Every argument of `derive` should be `NestedMetaItemKind::Literal`.
|
||||
Some(
|
||||
args.iter()
|
||||
.map(|a| context.snippet(a.span))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
46
tests/source/configs-merge_derives-true.rs
Normal file
46
tests/source/configs-merge_derives-true.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
// rustfmt-merge_derives: true
|
||||
// Merge multiple derives to a single one.
|
||||
|
||||
#[bar]
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[foo]
|
||||
#[derive(Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Foo {}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Bar {}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum FooBar {}
|
||||
|
||||
mod foo {
|
||||
#[bar]
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[foo]
|
||||
#[derive(Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Foo {}
|
||||
}
|
||||
|
||||
mod bar {
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Bar {}
|
||||
}
|
||||
|
||||
mod foobar {
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum FooBar {}
|
||||
}
|
||||
40
tests/target/configs-merge_derives-true.rs
Normal file
40
tests/target/configs-merge_derives-true.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// rustfmt-merge_derives: true
|
||||
// Merge multiple derives to a single one.
|
||||
|
||||
#[bar]
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[foo]
|
||||
#[derive(Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Foo {}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Bar {}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum FooBar {}
|
||||
|
||||
mod foo {
|
||||
#[bar]
|
||||
#[derive(Eq, PartialEq)]
|
||||
#[foo]
|
||||
#[derive(Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Foo {}
|
||||
}
|
||||
|
||||
mod bar {
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[foobar]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Bar {}
|
||||
}
|
||||
|
||||
mod foobar {
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
pub enum FooBar {}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue