Add a new config option to control the placement of a binary operator

This commit is contained in:
topecongiro 2017-09-15 12:10:30 +09:00
parent 7e309a4ad8
commit 45e48ec424
4 changed files with 115 additions and 34 deletions

View File

@ -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)]

View File

@ -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>(

View File

@ -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));

View File

@ -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())