about summary refs log tree commit diff
diff options
context:
space:
mode:
authorChristoph Burgdorf <christoph.burgdorf@bvsn.org>2015-09-05 01:31:39 +0200
committerChristoph Burgdorf <christoph.burgdorf@bvsn.org>2015-09-08 01:25:44 +0200
commit33c5776d30723e68d40a84dca57f7895feadb1c4 (patch)
tree19f0ed9adb654fb2fd9fd353badd860dfb07c573
parentc838b00d540d6e85b7a4ead656ff37d8b9e641cc (diff)
Implements struct_lit_force_multiline
With struct_lit_force_multiline set to true
rustfmt won't ever mangle multiple struct properties
into one line.

Fixes #253
-rw-r--r--src/config.rs22
-rw-r--r--src/expr.rs23
-rw-r--r--tests/source/struct_lits_multiline.rs72
-rw-r--r--tests/source/struct_lits_visual_multiline.rs42
-rw-r--r--tests/target/struct_lits_multiline.rs108
-rw-r--r--tests/target/struct_lits_visual_multiline.rs61
6 files changed, 320 insertions, 8 deletions
diff --git a/src/config.rs b/src/config.rs
index c7525e930ec..95994531950 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -45,6 +45,26 @@ impl Density {
     }
 }
 
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub enum MultilineStyle {
+    // Use horizontal layout if it fits in one line, fall back to vertical
+    PreferSingle,
+    // Use vertical layout
+    ForceMulti,
+}
+
+
+impl_enum_decodable!(MultilineStyle, PreferSingle, ForceMulti);
+
+impl MultilineStyle {
+    pub fn to_list_tactic(self) -> ListTactic {
+        match self {
+            MultilineStyle::PreferSingle => ListTactic::HorizontalVertical,
+            MultilineStyle::ForceMulti => ListTactic::Vertical,
+        }
+    }
+}
+
 macro_rules! create_config {
     ($($i:ident: $ty:ty),+ $(,)*) => (
         #[derive(RustcDecodable, Clone)]
@@ -122,6 +142,7 @@ create_config! {
     struct_trailing_comma: SeparatorTactic,
     struct_lit_trailing_comma: SeparatorTactic,
     struct_lit_style: StructLitStyle,
+    struct_lit_multiline_style: MultilineStyle,
     enum_trailing_comma: bool,
     report_todo: ReportTactic,
     report_fixme: ReportTactic,
@@ -155,6 +176,7 @@ impl Default for Config {
             struct_trailing_comma: SeparatorTactic::Vertical,
             struct_lit_trailing_comma: SeparatorTactic::Vertical,
             struct_lit_style: StructLitStyle::Block,
+            struct_lit_multiline_style: MultilineStyle::PreferSingle,
             enum_trailing_comma: true,
             report_todo: ReportTactic::Always,
             report_fixme: ReportTactic::Never,
diff --git a/src/expr.rs b/src/expr.rs
index e11c6e470f6..3e26f8b46b4 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -14,7 +14,7 @@ use string::{StringFormat, rewrite_string};
 use StructLitStyle;
 use utils::{span_after, make_indent, extra_offset, first_line_width, last_line_width};
 use visitor::FmtVisitor;
-use config::BlockIndentStyle;
+use config::{BlockIndentStyle, MultilineStyle};
 use comment::{FindUncommented, rewrite_comment, contains_comment};
 use types::rewrite_path;
 use items::{span_lo_for_arg, span_hi_for_arg, rewrite_fn_input};
@@ -997,7 +997,10 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
                              span.hi);
 
     let fmt = ListFormatting {
-        tactic: ListTactic::HorizontalVertical,
+        tactic: match (context.config.struct_lit_style, fields.len()) {
+            (StructLitStyle::Visual, 1) => ListTactic::HorizontalVertical,
+            _ => context.config.struct_lit_multiline_style.to_list_tactic(),
+        },
         separator: ",",
         trailing_separator: if base.is_some() {
             SeparatorTactic::Never
@@ -1011,12 +1014,16 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
     };
     let fields_str = write_list(&items.collect::<Vec<_>>(), &fmt);
 
-    match context.config.struct_lit_style {
-        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))
-        }
+    let format_on_newline = || {
+                                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))
+                            };
+
+    match (context.config.struct_lit_style, context.config.struct_lit_multiline_style) {
+        (StructLitStyle::Block, _) if fields_str.contains('\n') => format_on_newline(),
+        (StructLitStyle::Block, MultilineStyle::ForceMulti) => format_on_newline(),
         _ => Some(format!("{} {{ {} }}", path_str, fields_str)),
     }
 
diff --git a/tests/source/struct_lits_multiline.rs b/tests/source/struct_lits_multiline.rs
new file mode 100644
index 00000000000..d0cf7d4069f
--- /dev/null
+++ b/tests/source/struct_lits_multiline.rs
@@ -0,0 +1,72 @@
+// rustfmt-struct_lit_multiline_style: ForceMulti
+
+// Struct literal expressions.
+
+fn main() {
+    let x = Bar;
+
+    // Comment
+    let y = Foo {a: x };
+
+    Foo { a: foo() /* comment*/, /* comment*/ b: bar(), ..something };
+
+    Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), };
+
+    Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo { a: foo(), b: bar(), };
+
+    Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo {
+        // Comment
+        a: foo(), // Comment
+        // Comment
+        b: bar(), // Comment
+    };
+
+    Foo { a:Bar,
+          b:foo() };
+
+    Quux { x: if cond { bar(); }, y: baz() };
+
+    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
+    };
+
+    Some(Data::MethodCallData(MethodCallData {
+        span: sub_span.unwrap(),
+        scope: self.enclosing_scope(id),
+        ref_id: def_id,
+        decl_id: Some(decl_id),
+    }));
+
+    Diagram { /*                 o        This graph demonstrates how
+               *                / \       significant whitespace is
+               *               o   o      preserved.
+               *              /|\   \
+               *             o o o   o */
+              graph: G, }
+}
+
+fn matcher() {
+    TagTerminatedByteMatcher {
+        matcher: ByteMatcher {
+        pattern: b"<HTML",
+        mask: b"\xFF\xDF\xDF\xDF\xDF\xFF",
+    },
+    };
+}
+
+fn issue177() {
+    struct Foo<T> { memb: T }
+    let foo = Foo::<i64> { memb: 10 };
+}
+
+fn issue201() {
+    let s = S{a:0, ..  b};
+}
+
+fn issue201_2() {
+    let s = S{a: S2{    .. c}, ..  b};
+}
diff --git a/tests/source/struct_lits_visual_multiline.rs b/tests/source/struct_lits_visual_multiline.rs
new file mode 100644
index 00000000000..192d88a3903
--- /dev/null
+++ b/tests/source/struct_lits_visual_multiline.rs
@@ -0,0 +1,42 @@
+// rustfmt-struct_lit_style: Visual
+// rustfmt-struct_lit_multiline_style: ForceMulti
+
+// 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() };
+
+    Quux { x: if cond { bar(); }, y: baz() };
+
+    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_multiline.rs b/tests/target/struct_lits_multiline.rs
new file mode 100644
index 00000000000..2670ef6de1d
--- /dev/null
+++ b/tests/target/struct_lits_multiline.rs
@@ -0,0 +1,108 @@
+// rustfmt-struct_lit_multiline_style: ForceMulti
+
+// Struct literal expressions.
+
+fn main() {
+    let x = Bar;
+
+    // Comment
+    let y = Foo {
+        a: x,
+    };
+
+    Foo {
+        a: foo(), // comment
+        // comment
+        b: bar(),
+        ..something
+    };
+
+    Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo {
+        a: foo(),
+        b: bar(),
+    };
+
+    Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo {
+        a: foo(),
+        b: bar(),
+    };
+
+    Foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo {
+        // Comment
+        a: foo(), // Comment
+        // Comment
+        b: bar(), /* Comment */
+    };
+
+    Foo {
+        a: Bar,
+        b: foo(),
+    };
+
+    Quux {
+        x: if cond {
+            bar();
+        },
+        y: baz(),
+    };
+
+    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,
+    };
+
+    Some(Data::MethodCallData(MethodCallData {
+        span: sub_span.unwrap(),
+        scope: self.enclosing_scope(id),
+        ref_id: def_id,
+        decl_id: Some(decl_id),
+    }));
+
+    Diagram {
+        //                 o        This graph demonstrates how
+        //                / \       significant whitespace is
+        //               o   o      preserved.
+        //              /|\   \
+        //             o o o   o
+        graph: G,
+    }
+}
+
+fn matcher() {
+    TagTerminatedByteMatcher {
+        matcher: ByteMatcher {
+            pattern: b"<HTML",
+            mask: b"\xFF\xDF\xDF\xDF\xDF\xFF",
+        },
+    };
+}
+
+fn issue177() {
+    struct Foo<T> {
+        memb: T,
+    }
+    let foo = Foo::<i64> {
+        memb: 10,
+    };
+}
+
+fn issue201() {
+    let s = S {
+        a: 0,
+        ..b
+    };
+}
+
+fn issue201_2() {
+    let s = S {
+        a: S2 {
+            ..c
+        },
+        ..b
+    };
+}
diff --git a/tests/target/struct_lits_visual_multiline.rs b/tests/target/struct_lits_visual_multiline.rs
new file mode 100644
index 00000000000..94aa121b7a4
--- /dev/null
+++ b/tests/target/struct_lits_visual_multiline.rs
@@ -0,0 +1,61 @@
+// rustfmt-struct_lit_style: Visual
+// rustfmt-struct_lit_multiline_style: ForceMulti
+
+// 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 { // Commen
+                                                                                        // t
+                                                                                        a: foo(), /* C
+                                                                                                   * o
+                                                                                                   * m
+                                                                                                   * m
+                                                                                                   * e
+                                                                                                   * n
+                                                                                                   * t */
+                                                                                        // Commen
+                                                                                        // t
+                                                                                        b: bar(), /* C
+                                                                                                   * o
+                                                                                                   * m
+                                                                                                   * m
+                                                                                                   * e
+                                                                                                   * n
+                                                                                                   * t */ };
+
+    Foo { a: Bar,
+          b: foo(), };
+
+    Quux { x: if cond {
+               bar();
+           },
+           y: baz(), };
+
+    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, }
+}