diff --git a/src/config.rs b/src/config.rs index 329c67d2b0d9..1b4d79ab6ee8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -90,6 +90,7 @@ create_config! { fn_return_indent: ReturnIndent, fn_args_paren_newline: bool, fn_args_density: Density, + fn_args_layout: StructLitStyle, fn_arg_indent: BlockIndentStyle, where_density: Density, // Should we at least try to put the where clause on the same line as // the rest of the function decl? @@ -123,6 +124,7 @@ impl Default for Config { fn_return_indent: ReturnIndent::WithArgs, fn_args_paren_newline: true, fn_args_density: Density::Tall, + fn_args_layout: StructLitStyle::Visual, fn_arg_indent: BlockIndentStyle::Visual, where_density: Density::Tall, where_indent: BlockIndentStyle::Tabbed, @@ -131,7 +133,7 @@ impl Default for Config { generics_indent: BlockIndentStyle::Visual, struct_trailing_comma: SeparatorTactic::Vertical, struct_lit_trailing_comma: SeparatorTactic::Vertical, - struct_lit_style: StructLitStyle::BlockIndent, + struct_lit_style: StructLitStyle::Block, enum_trailing_comma: true, report_todo: ReportTactic::Always, report_fixme: ReportTactic::Never, diff --git a/src/expr.rs b/src/expr.rs index 20c56ccd34ff..19b3693d94be 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -940,10 +940,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, // Foo { a: Foo } - indent is +3, width is -5. let h_budget = try_opt!(width.checked_sub(path_str.len() + 5)); let (indent, v_budget) = match context.config.struct_lit_style { - StructLitStyle::VisualIndent => { + StructLitStyle::Visual => { (offset + path_str.len() + 3, h_budget) } - StructLitStyle::BlockIndent => { + StructLitStyle::Block => { // If we are all on one line, then we'll ignore the indent, and we // have a smaller budget. let indent = context.block_indent + context.config.tab_spaces; @@ -1012,7 +1012,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let fields_str = write_list(&items.collect::>(), &fmt); match context.config.struct_lit_style { - StructLitStyle::BlockIndent if fields_str.contains('\n') => { + StructLitStyle::Block if fields_str.contains('\n') => { let inner_indent = make_indent(context.block_indent + context.config.tab_spaces); let outer_indent = make_indent(context.block_indent); Some(format!("{} {{\n{}{}\n{}}}", path_str, inner_indent, fields_str, outer_indent)) @@ -1020,7 +1020,7 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, _ => Some(format!("{} {{ {} }}", path_str, fields_str)), } - // FIXME if context.config.struct_lit_style == VisualIndent, but we run out + // FIXME if context.config.struct_lit_style == Visual, but we run out // of space, we should fall back to BlockIndent. } diff --git a/src/items.rs b/src/items.rs index fd163cec6800..4d84a1420452 100644 --- a/src/items.rs +++ b/src/items.rs @@ -10,7 +10,7 @@ // Formatting top-level items - functions, structs, enums, traits, impls. -use {ReturnIndent, BraceStyle}; +use {ReturnIndent, BraceStyle, StructLitStyle}; use utils::{format_mutability, format_visibility, make_indent, contains_skip, span_after, end_typaram}; use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic}; @@ -225,6 +225,10 @@ impl<'a> FmtVisitor<'a> { result.push_str("(\n"); result.push_str(&make_indent(arg_indent)); } + } else if self.config.fn_args_layout == StructLitStyle::Block { + arg_indent = indent + self.config.tab_spaces; + result.push_str("(\n"); + result.push_str(&make_indent(arg_indent)); } else { result.push('('); } @@ -245,14 +249,20 @@ impl<'a> FmtVisitor<'a> { indent, arg_indent, args_span)); + if self.config.fn_args_layout == StructLitStyle::Block { + result.push('\n'); + } result.push(')'); // Return type. if !ret_str.is_empty() { // If we've already gone multi-line, or the return type would push // over the max width, then put the return type on a new line. - if result.contains("\n") || - result.len() + indent + ret_str.len() > self.config.max_width { + // Unless we are formatting args like a block, in which case there + // should always be room for the return type. + if (result.contains("\n") || + result.len() + indent + ret_str.len() > self.config.max_width) && + self.config.fn_args_layout != StructLitStyle::Block { let indent = match self.config.fn_return_indent { ReturnIndent::WithWhereClause => indent + 4, // TODO we might want to check that using the arg indent doesn't @@ -285,8 +295,11 @@ impl<'a> FmtVisitor<'a> { } } - let where_density = if self.config.where_density == Density::Compressed && - !result.contains('\n') { + let where_density = if (self.config.where_density == Density::Compressed && + (!result.contains('\n') || + self.config.fn_args_layout == StructLitStyle::Block)) || + (self.config.fn_args_layout == StructLitStyle::Block && + ret_str.is_empty()) { Density::Compressed } else { Density::Tall diff --git a/src/lib.rs b/src/lib.rs index f410f7e54680..83c0c5ae1b76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,13 +133,13 @@ impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); pub enum StructLitStyle { // First line on the same line as the opening brace, all lines aligned with // the first line. - VisualIndent, + Visual, // First line is on a new line and all lines align with block indent. - BlockIndent, + Block, // FIXME Maybe we should also have an option to align types. } -impl_enum_decodable!(StructLitStyle, VisualIndent, BlockIndent); +impl_enum_decodable!(StructLitStyle, Visual, Block); enum ErrorKind { // Line has exceeded character limit diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 08a0c22cc109..c5122b760a0b 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -7,6 +7,7 @@ fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_density = "Tall" +fn_args_layout = "Visual" fn_arg_indent = "Visual" where_density = "Tall" where_indent = "Tabbed" @@ -15,7 +16,7 @@ where_pred_indent = "Visual" generics_indent = "Visual" struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" -struct_lit_style = "BlockIndent" +struct_lit_style = "Block" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" diff --git a/tests/source/fn-custom-6.rs b/tests/source/fn-custom-6.rs new file mode 100644 index 000000000000..1042fa5bd880 --- /dev/null +++ b/tests/source/fn-custom-6.rs @@ -0,0 +1,36 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_indent: Inherit +// rustfmt-fn_brace_style: PreferSameLine +// Test different indents. + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) where T: UUUUUUUUUUU { + bar(); +} + +fn foo(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb) -> String where T: UUUUUUUUUUU { + foo(); +} + +fn bar(a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb, c: Cccccccccccccccccc, d: Dddddddddddddddd, e: Eeeeeeeeeeeeeee) -> String where T: UUUUUUUUUUU { + bar(); +} diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs index ea76a088a328..180a1229faa5 100644 --- a/tests/source/struct_lits_visual.rs +++ b/tests/source/struct_lits_visual.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: VisualIndent +// rustfmt-struct_lit_style: Visual // Struct literal expressions. diff --git a/tests/target/fn-custom-6.rs b/tests/target/fn-custom-6.rs new file mode 100644 index 000000000000..bea50c6a3cec --- /dev/null +++ b/tests/target/fn-custom-6.rs @@ -0,0 +1,70 @@ +// rustfmt-fn_args_layout: Block +// rustfmt-where_indent: Inherit +// rustfmt-fn_brace_style: PreferSameLine +// Test different indents. + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) -> String { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) where T: UUUUUUUUUUU { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) where T: UUUUUUUUUUU { + bar(); +} + +fn foo( + a: Aaaaaaaaaaaaaa, b: Bbbbbbbbbbbbbb +) -> String +where T: UUUUUUUUUUU { + foo(); +} + +fn bar( + a: Aaaaaaaaaaaaaa, + b: Bbbbbbbbbbbbbb, + c: Cccccccccccccccccc, + d: Dddddddddddddddd, + e: Eeeeeeeeeeeeeee +) -> String +where T: UUUUUUUUUUU { + bar(); +} diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs index 77467a40ce7d..4274c9167773 100644 --- a/tests/target/struct_lits_visual.rs +++ b/tests/target/struct_lits_visual.rs @@ -1,4 +1,4 @@ -// rustfmt-struct_lit_style: VisualIndent +// rustfmt-struct_lit_style: Visual // Struct literal expressions.