diff --git a/src/visitor.rs b/src/visitor.rs index a792148130b..1fe8655309f 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -973,7 +973,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { 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(", "))); + result.push_str(&try_opt!(format_derive(context, &derive_args, shape))); derive_args.clear(); } } @@ -990,6 +990,38 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { } } +// Format `#[derive(..)]`, using visual indent & mixed style when we need to go multiline. +fn format_derive(context: &RewriteContext, derive_args: &[String], shape: Shape) -> Option { + let mut result = String::with_capacity(128); + result.push_str("#[derive("); + // 11 = `#[derive()]` + let initial_budget = try_opt!(shape.width.checked_sub(11)); + let mut budget = initial_budget; + let num = derive_args.len(); + for (i, a) in derive_args.iter().enumerate() { + // 2 = `, ` or `)]` + let width = a.len() + 2; + if width > budget { + if i > 0 { + // Remove trailing whitespace. + result.pop(); + } + result.push('\n'); + // 9 = `#[derive(` + result.push_str(&(shape.indent + 9).to_string(context.config)); + budget = initial_budget; + } else { + budget = budget.checked_sub(width).unwrap_or(0); + } + result.push_str(a); + if i != num - 1 { + result.push_str(", ") + } + } + result.push_str(")]"); + Some(result) +} + fn is_derive(attr: &ast::Attribute) -> bool { match attr.meta() { Some(meta_item) => match meta_item.node { diff --git a/tests/source/attrib.rs b/tests/source/attrib.rs index 4d23d8b79d1..6653dd2daa9 100644 --- a/tests/source/attrib.rs +++ b/tests/source/attrib.rs @@ -146,3 +146,7 @@ fn attributes_on_statements() { # [ attr ( on ( mac ) ) ] foo!(); } + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, Deserialize)] +pub struct HP(pub u8); diff --git a/tests/target/attrib.rs b/tests/target/attrib.rs index 467d168ef4f..e220b48fb38 100644 --- a/tests/target/attrib.rs +++ b/tests/target/attrib.rs @@ -146,3 +146,8 @@ fn attributes_on_statements() { #[attr(on(mac))] foo!(); } + +// Large derive +#[derive(Add, Sub, Mul, Div, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash, Serialize, + Deserialize)] +pub struct HP(pub u8);