diff --git a/src/config.rs b/src/config.rs index 0ea13768457..a01d3e64689 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,7 +10,7 @@ extern crate toml; -use {NewlineStyle, BraceStyle, ReturnIndent}; +use {NewlineStyle, BraceStyle, ReturnIndent, StructLitStyle}; use lists::SeparatorTactic; use issues::ReportTactic; @@ -26,6 +26,7 @@ pub struct Config { pub fn_args_paren_newline: bool, pub struct_trailing_comma: SeparatorTactic, pub struct_lit_trailing_comma: SeparatorTactic, + pub struct_lit_style: StructLitStyle, pub enum_trailing_comma: bool, pub report_todo: ReportTactic, pub report_fixme: ReportTactic, @@ -35,6 +36,14 @@ pub struct Config { impl Config { pub fn from_toml(toml: &str) -> Config { let parsed = toml.parse().unwrap(); - toml::decode(parsed).unwrap() + match toml::decode(parsed) { + Some(decoded) => decoded, + None => { + println!("Decoding config file failed. Config:\n{}", toml); + let parsed: toml::Value = toml.parse().unwrap(); + println!("\n\nParsed:\n{:?}", parsed); + panic!(); + } + } } } diff --git a/src/default.toml b/src/default.toml index 951fde9d665..e31a0f257e9 100644 --- a/src/default.toml +++ b/src/default.toml @@ -7,6 +7,7 @@ fn_brace_style = "SameLineWhere" fn_return_indent = "WithArgs" fn_args_paren_newline = true struct_trailing_comma = "Vertical" +struct_lit_style = "BlockIndent" struct_lit_trailing_comma = "Vertical" enum_trailing_comma = true report_todo = "Always" diff --git a/src/expr.rs b/src/expr.rs index 33a82da0f29..c6e9a84421a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -11,6 +11,7 @@ use rewrite::{Rewrite, RewriteContext}; use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic}; use string::{StringFormat, rewrite_string}; +use StructLitStyle; use utils::{span_after, make_indent}; use visitor::FmtVisitor; @@ -188,8 +189,15 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, let path_str = pprust::path_to_string(path); // Foo { a: Foo } - indent is +3, width is -5. - let indent = offset + path_str.len() + 3; - let budget = width - (path_str.len() + 5); + let (indent, budget) = match context.config.struct_lit_style { + StructLitStyle::VisualIndent => { + (offset + path_str.len() + 3, width - (path_str.len() + 5)) + } + StructLitStyle::BlockIndent => { + let indent = context.block_indent + context.config.tab_spaces; + (indent, width - indent) + } + }; let field_iter = fields.into_iter().map(StructLitField::Regular) .chain(base.into_iter().map(StructLitField::Base)); @@ -243,12 +251,18 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext, v_width: budget, ends_with_newline: true, }; let fields_str = write_list(&items, &fmt); - Some(format!("{} {{ {} }}", path_str, fields_str)) - // FIXME if the usual multi-line layout is too wide, we should fall back to - // Foo { - // a: ..., - // } + match context.config.struct_lit_style { + StructLitStyle::BlockIndent 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)) + } + _ => Some(format!("{} {{ {} }}", path_str, fields_str)), + } + + // FIXME if context.config.struct_lit_style == VisualIndent, but we run out + // of space, we should fall back to BlockIndent. } fn rewrite_field(context: &RewriteContext, diff --git a/src/lib.rs b/src/lib.rs index 252b3ad05b7..296a462ed38 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -111,6 +111,19 @@ pub enum ReturnIndent { impl_enum_decodable!(ReturnIndent, WithArgs, WithWhereClause); +// How to stle a struct literal. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub enum StructLitStyle { + // First line on the same line as the opening brace, all lines aligned with + // the first line. + VisualIndent, + // First line is on a new line and all lines align with block indent. + BlockIndent, + // FIXME Maybe we should also have an option to align types. +} + +impl_enum_decodable!(StructLitStyle, VisualIndent, BlockIndent); + enum ErrorKind { // Line has exceeded character limit LineOverflow, diff --git a/tests/config/reorder_imports.toml b/tests/config/reorder_imports.toml index 31b0e2c6217..ddab2479f2c 100644 --- a/tests/config/reorder_imports.toml +++ b/tests/config/reorder_imports.toml @@ -8,6 +8,7 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" +struct_lit_style = "BlockIndent" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 35477559e43..303433dbcc1 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -8,6 +8,7 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true struct_trailing_comma = "Vertical" struct_lit_trailing_comma = "Vertical" +struct_lit_style = "BlockIndent" enum_trailing_comma = true report_todo = "Always" report_fixme = "Never" diff --git a/tests/config/visual_struct_lits.toml b/tests/config/visual_struct_lits.toml new file mode 100644 index 00000000000..cf601303e9b --- /dev/null +++ b/tests/config/visual_struct_lits.toml @@ -0,0 +1,15 @@ +max_width = 100 +ideal_width = 80 +leeway = 5 +tab_spaces = 4 +newline_style = "Unix" +fn_brace_style = "SameLineWhere" +fn_return_indent = "WithArgs" +fn_args_paren_newline = true +struct_trailing_comma = "Vertical" +struct_lit_style = "VisualIndent" +struct_lit_trailing_comma = "Vertical" +enum_trailing_comma = true +report_todo = "Always" +report_fixme = "Never" +reorder_imports = false diff --git a/tests/source/struct_lits_visual.rs b/tests/source/struct_lits_visual.rs new file mode 100644 index 00000000000..b629ffa1263 --- /dev/null +++ b/tests/source/struct_lits_visual.rs @@ -0,0 +1,39 @@ +// rustfmt-config: visual_struct_lits.toml + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo {a: x }; + + Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + // Comment + a: foo(), // Comment + // Comment + b: bar(), // Comment + }; + + Foo { a:Bar, + b:foo() }; + + A { + // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item + }; + + Diagram { /* o This graph demonstrates how + * / \ significant whitespace is + * o o preserved. + * /|\ \ + * o o o o */ + graph: G, } +} diff --git a/tests/target/struct_lits.rs b/tests/target/struct_lits.rs index c46909825a1..befeede14df 100644 --- a/tests/target/struct_lits.rs +++ b/tests/target/struct_lits.rs @@ -6,30 +6,35 @@ fn main() { // Comment let y = Foo { a: x }; - Foo { a: foo(), // comment - // comment - b: bar(), - ..something }; + Foo { + a: foo(), // comment + // comment + b: bar(), + ..something + }; - Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), - b: bar(), }; + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { + a: foo(), + b: bar(), + }; Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment - a: foo(), /* C - * o - * m - * m - * e - * n - * t */ - // Comment - b: bar(), /* C - * o - * m - * m - * e - * n - * t */ }; + a: foo(), /* C + * o + * m + * m + * e + * n + * t */ + // Comment + b: bar(), /* C + * o + * m + * m + * e + * n + * t */ + }; Foo { a: Bar, b: foo() }; @@ -39,12 +44,14 @@ fn main() { first: item(), // Praesent et diam eget libero egestas mattis sit amet vitae augue. // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. - second: Item, }; + second: Item, + }; Diagram { // o This graph demonstrates how // / \ significant whitespace is // o o preserved. // /|\ \ // o o o o - graph: G, } + graph: G, + } } diff --git a/tests/target/struct_lits_visual.rs b/tests/target/struct_lits_visual.rs new file mode 100644 index 00000000000..651cd2b883b --- /dev/null +++ b/tests/target/struct_lits_visual.rs @@ -0,0 +1,52 @@ +// rustfmt-config: visual_struct_lits.toml + +// Struct literal expressions. + +fn main() { + let x = Bar; + + // Comment + let y = Foo { a: x }; + + Foo { a: foo(), // comment + // comment + b: bar(), + ..something }; + + Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), + b: bar(), }; + + Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { // Comment + a: foo(), /* C + * o + * m + * m + * e + * n + * t */ + // Comment + b: bar(), /* C + * o + * m + * m + * e + * n + * t */ }; + + Foo { a: Bar, b: foo() }; + + A { // Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit + // amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante + // hendrerit. Donec et mollis dolor. + first: item(), + // Praesent et diam eget libero egestas mattis sit amet vitae augue. + // Nam tincidunt congue enim, ut porta lorem lacinia consectetur. + second: Item, }; + + Diagram { // o This graph demonstrates how + // / \ significant whitespace is + // o o preserved. + // /|\ \ + // o o o o + graph: G, } +}