about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authortopecongiro <seuchida@gmail.com>2017-09-15 12:10:30 +0900
committertopecongiro <seuchida@gmail.com>2017-09-15 12:10:30 +0900
commit45e48ec424b2e1db489db860581aaf7e684fbae0 (patch)
tree36820db5886a53726d5d8519a55b245e566450c9 /src
parent7e309a4ad83e1403d7bd23c4a1ee2c02cf4e273d (diff)
Add a new config option to control the placement of a binary operator
Diffstat (limited to 'src')
-rw-r--r--src/config.rs2
-rw-r--r--src/expr.rs112
-rw-r--r--src/patterns.rs24
-rw-r--r--src/types.rs11
4 files changed, 115 insertions, 34 deletions
diff --git a/src/config.rs b/src/config.rs
index 30d79cdc562..04020d1aeee 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -620,6 +620,8 @@ create_config! {
     multiline_match_arm_forces_block: bool, false,
         "Force multiline match arm bodies to be wrapped in a block";
     merge_derives: bool, true, "Merge multiple `#[derive(...)]` into a single one";
+    binop_sep: SeparatorPlace, SeparatorPlace::Front,
+        "Where to put a binary operator when a binary expression goes multiline.";
 }
 
 #[cfg(test)]
diff --git a/src/expr.rs b/src/expr.rs
index 0b9511e02ce..dc11edde95f 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -101,6 +101,7 @@ pub fn format_expr(
                 "",
                 context,
                 shape,
+                context.config.binop_sep(),
             )
         }
         ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape),
@@ -213,12 +214,26 @@ pub fn format_expr(
         ast::ExprKind::AddrOf(mutability, ref expr) => {
             rewrite_expr_addrof(context, mutability, expr, shape)
         }
-        ast::ExprKind::Cast(ref expr, ref ty) => {
-            rewrite_pair(&**expr, &**ty, "", " as ", "", context, shape)
-        }
-        ast::ExprKind::Type(ref expr, ref ty) => {
-            rewrite_pair(&**expr, &**ty, "", ": ", "", context, shape)
-        }
+        ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair(
+            &**expr,
+            &**ty,
+            "",
+            " as ",
+            "",
+            context,
+            shape,
+            SeparatorPlace::Front,
+        ),
+        ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair(
+            &**expr,
+            &**ty,
+            "",
+            ": ",
+            "",
+            context,
+            shape,
+            SeparatorPlace::Front,
+        ),
         ast::ExprKind::Index(ref expr, ref index) => {
             rewrite_index(&**expr, &**index, context, shape)
         }
@@ -228,7 +243,16 @@ pub fn format_expr(
             } else {
                 ("[", "]")
             };
-            rewrite_pair(&**expr, &**repeats, lbr, "; ", rbr, context, shape)
+            rewrite_pair(
+                &**expr,
+                &**repeats,
+                lbr,
+                "; ",
+                rbr,
+                context,
+                shape,
+                SeparatorPlace::Back,
+            )
         }
         ast::ExprKind::Range(ref lhs, ref rhs, limits) => {
             let delim = match limits {
@@ -257,7 +281,16 @@ pub fn format_expr(
                     } else {
                         delim.into()
                     };
-                    rewrite_pair(&*lhs, &*rhs, "", &sp_delim, "", context, shape)
+                    rewrite_pair(
+                        &*lhs,
+                        &*rhs,
+                        "",
+                        &sp_delim,
+                        "",
+                        context,
+                        shape,
+                        SeparatorPlace::Front,
+                    )
                 }
                 (None, Some(rhs)) => {
                     let sp_delim = if context.config.spaces_around_ranges() {
@@ -323,26 +356,29 @@ pub fn rewrite_pair<LHS, RHS>(
     suffix: &str,
     context: &RewriteContext,
     shape: Shape,
+    separator_place: SeparatorPlace,
 ) -> Option<String>
 where
     LHS: Rewrite,
     RHS: Rewrite,
 {
-    let sep = if infix.ends_with(' ') { " " } else { "" };
-    let infix = infix.trim_right();
-    let lhs_overhead = shape.used_width() + prefix.len() + infix.len();
+    let lhs_overhead = match separator_place {
+        SeparatorPlace::Back => shape.used_width() + prefix.len() + infix.trim_right().len(),
+        SeparatorPlace::Front => shape.used_width(),
+    };
     let lhs_shape = Shape {
-        width: try_opt!(context.config.max_width().checked_sub(lhs_overhead)),
+        width: context.budget(lhs_overhead),
         ..shape
     };
     let lhs_result = try_opt!(
         lhs.rewrite(context, lhs_shape)
-            .map(|lhs_str| format!("{}{}{}", prefix, lhs_str, infix))
+            .map(|lhs_str| format!("{}{}", prefix, lhs_str))
     );
 
     // Try to the both lhs and rhs on the same line.
     let rhs_orig_result = shape
-        .offset_left(last_line_width(&lhs_result) + suffix.len() + sep.len())
+        .offset_left(last_line_width(&lhs_result) + infix.len())
+        .and_then(|s| s.sub_width(suffix.len()))
         .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape));
     if let Some(ref rhs_result) = rhs_orig_result {
         // If the rhs looks like block expression, we allow it to stay on the same line
@@ -353,33 +389,49 @@ where
             .map(|first_line| first_line.ends_with('{'))
             .unwrap_or(false);
         if !rhs_result.contains('\n') || allow_same_line {
-            return Some(format!("{}{}{}{}", lhs_result, sep, rhs_result, suffix));
+            return Some(format!("{}{}{}{}", lhs_result, infix, rhs_result, suffix));
         }
     }
 
     // We have to use multiple lines.
     // Re-evaluate the rhs because we have more space now:
-    let rhs_shape = match context.config.control_style() {
-        Style::Legacy => {
-            try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len())
-        }
+    let mut rhs_shape = try_opt!(match context.config.control_style() {
+        Style::Legacy => shape
+            .sub_width(suffix.len() + prefix.len())
+            .map(|s| s.visual_indent(prefix.len())),
         Style::Rfc => {
             // Try to calculate the initial constraint on the right hand side.
             let rhs_overhead = shape.rhs_overhead(context.config);
-            try_opt!(
-                Shape::indented(shape.indent.block_indent(context.config), context.config)
-                    .sub_width(rhs_overhead)
-            )
+            Shape::indented(shape.indent.block_indent(context.config), context.config)
+                .sub_width(rhs_overhead)
         }
+    });
+    let infix = match separator_place {
+        SeparatorPlace::Back => infix.trim_right(),
+        SeparatorPlace::Front => infix.trim_left(),
     };
+    if separator_place == SeparatorPlace::Front {
+        rhs_shape = try_opt!(rhs_shape.offset_left(infix.len()));
+    }
     let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape));
-    Some(format!(
-        "{}\n{}{}{}",
-        lhs_result,
-        rhs_shape.indent.to_string(context.config),
-        rhs_result,
-        suffix
-    ))
+    match separator_place {
+        SeparatorPlace::Back => Some(format!(
+            "{}{}\n{}{}{}",
+            lhs_result,
+            infix,
+            rhs_shape.indent.to_string(context.config),
+            rhs_result,
+            suffix
+        )),
+        SeparatorPlace::Front => Some(format!(
+            "{}\n{}{}{}{}",
+            lhs_result,
+            rhs_shape.indent.to_string(context.config),
+            infix,
+            rhs_result,
+            suffix
+        )),
+    }
 }
 
 pub fn rewrite_array<'a, I>(
diff --git a/src/patterns.rs b/src/patterns.rs
index c3475dfba73..ab61df22b68 100644
--- a/src/patterns.rs
+++ b/src/patterns.rs
@@ -18,7 +18,7 @@ use comment::FindUncommented;
 use expr::{can_be_overflowed_expr, rewrite_call_inner, rewrite_pair, rewrite_unary_prefix,
            wrap_struct_field};
 use lists::{itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
-            struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorTactic};
+            struct_lit_tactic, write_list, DefinitiveListTactic, SeparatorPlace, SeparatorTactic};
 use rewrite::{Rewrite, RewriteContext};
 use types::{rewrite_path, PathContext};
 use utils::{format_mutability, mk_sp, wrap_str};
@@ -59,8 +59,26 @@ impl Rewrite for Pat {
                 None
             },
             PatKind::Range(ref lhs, ref rhs, ref end_kind) => match *end_kind {
-                RangeEnd::Included => rewrite_pair(&**lhs, &**rhs, "", "...", "", context, shape),
-                RangeEnd::Excluded => rewrite_pair(&**lhs, &**rhs, "", "..", "", context, shape),
+                RangeEnd::Included => rewrite_pair(
+                    &**lhs,
+                    &**rhs,
+                    "",
+                    "...",
+                    "",
+                    context,
+                    shape,
+                    SeparatorPlace::Front,
+                ),
+                RangeEnd::Excluded => rewrite_pair(
+                    &**lhs,
+                    &**rhs,
+                    "",
+                    "..",
+                    "",
+                    context,
+                    shape,
+                    SeparatorPlace::Front,
+                ),
             },
             PatKind::Ref(ref pat, mutability) => {
                 let prefix = format!("&{}", format_mutability(mutability));
diff --git a/src/types.rs b/src/types.rs
index ceca0417aa8..535b71c9402 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -738,7 +738,16 @@ impl Rewrite for ast::Ty {
                 let use_spaces = context.config.spaces_within_square_brackets();
                 let lbr = if use_spaces { "[ " } else { "[" };
                 let rbr = if use_spaces { " ]" } else { "]" };
-                rewrite_pair(&**ty, &**repeats, lbr, "; ", rbr, context, shape)
+                rewrite_pair(
+                    &**ty,
+                    &**repeats,
+                    lbr,
+                    "; ",
+                    rbr,
+                    context,
+                    shape,
+                    SeparatorPlace::Back,
+                )
             }
             ast::TyKind::Infer => if shape.width >= 1 {
                 Some("_".to_owned())