diff --git a/src/items.rs b/src/items.rs index 0fb5520f6bdd..8435de621475 100644 --- a/src/items.rs +++ b/src/items.rs @@ -618,10 +618,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&header); - // TODO: Add max_width checking - // let budget = try_opt!(context.config.max_width.checked_sub(result.len())); - // let indent = offset + result.len(); - let body_lo = context.codemap.span_after(item.span, "{"); let generics_str = try_opt!(rewrite_generics(context, @@ -636,8 +632,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) type_param_bounds, offset, context.config.max_width)); - - if offset.width() + result.len() + trait_bound_str.len() > context.config.max_width { + // If the trait, generics, and trait bound cannot fit on the same line, + // put the trait bounds on an indented new line + if offset.width() + last_line_width(&result) + trait_bound_str.len() > + context.config.ideal_width { result.push('\n'); let width = context.block_indent.width() + context.config.tab_spaces; let trait_indent = Indent::new(0, width); @@ -645,19 +643,39 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } result.push_str(&trait_bound_str); - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let has_body = !trait_items.is_empty(); + + let where_density = if (context.config.where_density == Density::Compressed && + (!result.contains('\n') || + context.config.fn_args_layout == StructLitStyle::Block)) || + (context.config.fn_args_layout == StructLitStyle::Block && + result.is_empty()) || + (context.config.where_density == Density::CompressedIfEmpty && + !has_body && + !result.contains('\n')) { + Density::Compressed + } else { + Density::Tall + }; + + let where_budget = try_opt!(context.config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, context.config.item_brace_style, context.block_indent, where_budget, - context.config.where_density, + where_density, "{", - context.config.where_trailing_comma, + has_body, None)); + // If the where clause cannot fit on the same line, + // put the where clause on a new line if !where_clause_str.contains('\n') && - result.len() + where_clause_str.len() + offset.width() > context.config.max_width { + last_line_width(&result) + where_clause_str.len() + offset.width() > + context.config.ideal_width { result.push('\n'); let width = context.block_indent.width() + context.config.tab_spaces - 1; let where_indent = Indent::new(0, width); @@ -672,7 +690,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() { + if !where_clause_str.is_empty() && + (trait_items.len() > 0 || result.contains('\n')) { result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { @@ -704,6 +723,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); result.push('\n'); result.push_str(&outer_indent_str); + } else if result.contains('\n') { + result.push('\n'); } result.push('}'); @@ -1000,7 +1021,7 @@ pub fn rewrite_static(prefix: &str, ident: ast::Ident, ty: &ast::Ty, mutability: ast::Mutability, - expr: &ast::Expr, + expr_opt: Option<&ptr::P>, context: &RewriteContext) -> Option { let prefix = format!("{}{} {}{}: ", @@ -1013,21 +1034,26 @@ pub fn rewrite_static(prefix: &str, context.config.max_width - context.block_indent.width() - prefix.len() - 2, context.block_indent)); - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") + if let Some(ref expr) = expr_opt { + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; + let remaining_width = context.config.max_width - context.block_indent.width() - 1; + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) + .map(|s| s + ";") + } else { + let lhs = format!("{}{};", prefix, ty_str); + Some(lhs) + } } -pub fn rewrite_associated_type(prefix: &str, - ident: ast::Ident, +pub fn rewrite_associated_type(ident: ast::Ident, ty_opt: Option<&ptr::P>, ty_param_bounds_opt: Option<&ast::TyParamBounds>, context: &RewriteContext, indent: Indent) -> Option { - let prefix = format!("{} {}", prefix, ident); + let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = &ty_param_bounds.as_slice(); @@ -1058,37 +1084,6 @@ pub fn rewrite_associated_type(prefix: &str, } } -pub fn rewrite_associated_static(prefix: &str, - vis: ast::Visibility, - ident: ast::Ident, - ty: &ast::Ty, - mutability: ast::Mutability, - expr_opt: &Option>, - context: &RewriteContext) - -> Option { - let prefix = format!("{}{} {}{}: ", - format_visibility(vis), - prefix, - format_mutability(mutability), - ident); - // 2 = " =".len() - let ty_str = try_opt!(ty.rewrite(context, - context.config.max_width - context.block_indent.width() - - prefix.len() - 2, - context.block_indent)); - - if let &Some(ref expr) = expr_opt { - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) - .map(|s| s + ";") - } else { - let lhs = format!("{}{};", prefix, ty_str); - Some(lhs) - } -} - impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { diff --git a/src/visitor.rs b/src/visitor.rs index f5774da7d649..62fbfd7613fa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,8 +21,7 @@ use config::Config; use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, - rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -267,7 +266,7 @@ impl<'a> FmtVisitor<'a> { item.ident, ty, mutability, - expr, + Some(expr), &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -277,7 +276,7 @@ impl<'a> FmtVisitor<'a> { item.ident, ty, ast::Mutability::Immutable, - expr, + Some(expr), &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -315,14 +314,14 @@ impl<'a> FmtVisitor<'a> { } match ti.node { - ast::TraitItemKind::Const(ref ty, ref expr) => { - let rewrite = rewrite_associated_static("const", - ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr, - &self.get_context()); + ast::TraitItemKind::Const(ref ty, ref expr_opt) => { + let rewrite = rewrite_static("const", + ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr_opt.as_ref(), + &self.get_context()); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { @@ -338,8 +337,7 @@ impl<'a> FmtVisitor<'a> { ti.id); } ast::TraitItemKind::Type(ref type_param_bounds, _) => { - let rewrite = rewrite_associated_type("type", - ti.ident, + let rewrite = rewrite_associated_type(ti.ident, None, Some(type_param_bounds), &self.get_context(), @@ -368,13 +366,12 @@ impl<'a> FmtVisitor<'a> { ii.ident, ty, ast::Mutability::Immutable, - &expr, + Some(expr), &self.get_context()); self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Type(ref ty) => { - let rewrite = rewrite_associated_type("type", - ii.ident, + let rewrite = rewrite_associated_type(ii.ident, Some(ty), None, &self.get_context(), diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 3fb6a1b85e22..faac57179c20 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -43,3 +43,13 @@ trait Foo { type Bar: Baz;} trait ConstCheck:Foo where T: Baz { const J: i32; } + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar { fn test(); } + +trait WhereList where T: Foo, J: Bar {} + diff --git a/tests/target/trait.rs b/tests/target/trait.rs index f784fa145301..d8acc1ba229b 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -41,7 +41,28 @@ trait Foo { type Bar: Baz; } -trait ConstCheck: Foo where T: Baz +trait ConstCheck: Foo + where T: Baz { const J: i32; } + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo +{ +} + +trait FooBar + : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where J: Bar +{ + fn test(); +} + +trait WhereList + where T: Foo, + J: Bar +{ +}