From 45e48ec424b2e1db489db860581aaf7e684fbae0 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 15 Sep 2017 12:10:30 +0900 Subject: [PATCH] Add a new config option to control the placement of a binary operator --- src/config.rs | 2 + src/expr.rs | 112 +++++++++++++++++++++++++++++++++++------------- src/patterns.rs | 24 +++++++++-- src/types.rs | 11 ++++- 4 files changed, 115 insertions(+), 34 deletions(-) diff --git a/src/config.rs b/src/config.rs index 30d79cdc5629..04020d1aeee7 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 0b9511e02cea..dc11edde95f4 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( suffix: &str, context: &RewriteContext, shape: Shape, + separator_place: SeparatorPlace, ) -> Option 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 c3475dfba73a..ab61df22b682 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 ceca0417aa8e..535b71c94025 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())