use syntax::{ast, ptr};
use syntax::codemap::{BytePos, CodeMap, Span};
-use syntax::parse::classify;
use spanned::Spanned;
use chains::rewrite_chain;
+use closures;
use codemap::{LineRangeUtils, SpanUtils};
use comment::{combine_strs_with_missing_comments, contains_comment, recover_comment_removed,
rewrite_comment, rewrite_missing_comment, FindUncommented};
-use config::{Config, ControlBraceStyle, IndentStyle, MultilineStyle, Style};
-use items::{span_hi_for_arg, span_lo_for_arg};
+use config::{Config, ControlBraceStyle, IndentStyle};
use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting,
struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting,
ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic};
use string::{rewrite_string, StringFormat};
use types::{can_be_overflowed_type, rewrite_path, PathContext};
use utils::{colon_spaces, contains_skip, extra_offset, first_line_width, inner_attributes,
- last_line_extendable, last_line_width, left_most_sub_expr, mk_sp, outer_attributes,
- paren_overhead, ptr_vec_to_ref_vec, semicolon_for_stmt, stmt_expr,
- trimmed_last_line_width, wrap_str};
+ last_line_extendable, last_line_width, mk_sp, outer_attributes, paren_overhead,
+ ptr_vec_to_ref_vec, semicolon_for_stmt, trimmed_last_line_width, wrap_str};
use vertical::rewrite_with_alignment;
use visitor::FmtVisitor;
let expr_rw = match expr.node {
ast::ExprKind::Array(ref expr_vec) => rewrite_array(
- expr_vec.iter().map(|e| &**e),
+ &ptr_vec_to_ref_vec(expr_vec),
mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi()),
context,
shape,
ast::ExprKind::Tup(ref items) => {
rewrite_tuple(context, &ptr_vec_to_ref_vec(items), expr.span, shape)
}
- ast::ExprKind::If(..) |
- ast::ExprKind::IfLet(..) |
- ast::ExprKind::ForLoop(..) |
- ast::ExprKind::Loop(..) |
- ast::ExprKind::While(..) |
- ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type)
+ ast::ExprKind::If(..)
+ | ast::ExprKind::IfLet(..)
+ | ast::ExprKind::ForLoop(..)
+ | ast::ExprKind::Loop(..)
+ | ast::ExprKind::While(..)
+ | ast::ExprKind::WhileLet(..) => to_control_flow(expr, expr_type)
.and_then(|control_flow| control_flow.rewrite(context, shape)),
ast::ExprKind::Block(ref block) => {
match expr_type {
rw
} else {
let prefix = block_prefix(context, block, shape)?;
- rewrite_block_with_visitor(context, &prefix, block, shape)
+ rewrite_block_with_visitor(context, &prefix, block, shape, true)
}
}
ExprType::SubExpression => block.rewrite(context, shape),
Some("yield".to_string())
},
ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => {
- rewrite_closure(capture, fn_decl, body, expr.span, context, shape)
+ closures::rewrite_closure(capture, fn_decl, body, expr.span, context, shape)
}
- ast::ExprKind::Try(..) |
- ast::ExprKind::Field(..) |
- ast::ExprKind::TupField(..) |
- ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape),
+ ast::ExprKind::Try(..)
+ | ast::ExprKind::Field(..)
+ | ast::ExprKind::TupField(..)
+ | ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape),
ast::ExprKind::Mac(ref mac) => {
rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| {
wrap_str(
rewrite_index(&**expr, &**index, context, shape)
}
ast::ExprKind::Repeat(ref expr, ref repeats) => {
- let (lbr, rbr) = if context.config.spaces_within_square_brackets() {
+ let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() {
("[ ", " ]")
} else {
("[", "]")
};
expr_rw
- .and_then(|expr_str| {
- recover_comment_removed(expr_str, expr.span, context)
- })
+ .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context))
.and_then(|expr_str| {
let attrs = outer_attributes(&expr.attrs);
let attrs_str = attrs.rewrite(context, shape)?;
// We have to use multiple lines.
// Re-evaluate the rhs because we have more space now:
- let mut rhs_shape = match context.config.control_style() {
- Style::Legacy => shape
+ let mut rhs_shape = match context.config.indent_style() {
+ IndentStyle::Visual => shape
.sub_width(pp.suffix.len() + pp.prefix.len())?
.visual_indent(pp.prefix.len()),
- Style::Rfc => {
+ IndentStyle::Block => {
// Try to calculate the initial constraint on the right hand side.
let rhs_overhead = shape.rhs_overhead(context.config);
Shape::indented(shape.indent.block_indent(context.config), context.config)
))
}
-pub fn rewrite_array<'a, I>(
- expr_iter: I,
+pub fn rewrite_array<T: Rewrite + Spanned + ToExpr>(
+ exprs: &[&T],
span: Span,
context: &RewriteContext,
shape: Shape,
trailing_comma: bool,
-) -> Option<String>
-where
- I: Iterator<Item = &'a ast::Expr>,
-{
- let bracket_size = if context.config.spaces_within_square_brackets() {
+) -> Option<String> {
+ let bracket_size = if context.config.spaces_within_parens_and_brackets() {
2 // "[ "
} else {
1 // "["
};
- let nested_shape = match context.config.array_indent() {
+ let nested_shape = match context.config.indent_style() {
IndentStyle::Block => shape
.block()
.block_indent(context.config.tab_spaces())
let items = itemize_list(
context.codemap,
- expr_iter,
+ exprs.iter(),
"]",
- |item| item.span.lo(),
- |item| item.span.hi(),
+ ",",
+ |item| item.span().lo(),
+ |item| item.span().hi(),
|item| item.rewrite(context, nested_shape),
span.lo(),
span.hi(),
).collect::<Vec<_>>();
if items.is_empty() {
- if context.config.spaces_within_square_brackets() {
+ if context.config.spaces_within_parens_and_brackets() {
return Some("[ ]".to_string());
} else {
return Some("[]".to_string());
.iter()
.any(|li| li.item.as_ref().map(|s| s.len() > 10).unwrap_or(false));
- let mut tactic = match context.config.array_indent() {
+ let tactic = match context.config.indent_style() {
IndentStyle::Block => {
// FIXME wrong shape in one-line case
match shape.width.checked_sub(2 * bracket_size) {
Some(width) => {
- let tactic =
- ListTactic::LimitedHorizontalVertical(context.config.array_width());
+ let tactic = ListTactic::LimitedHorizontalVertical(
+ context.config.width_heuristics().array_width,
+ );
definitive_tactic(&items, tactic, Separator::Comma, width)
}
None => DefinitiveListTactic::Vertical,
}
}
- IndentStyle::Visual => if has_long_item || items.iter().any(ListItem::is_multiline) {
- definitive_tactic(
- &items,
- ListTactic::LimitedHorizontalVertical(context.config.array_width()),
- Separator::Comma,
- nested_shape.width,
- )
- } else {
- DefinitiveListTactic::Mixed
- },
+ IndentStyle::Visual => {
+ if has_long_item || items.iter().any(ListItem::is_multiline) {
+ definitive_tactic(
+ &items,
+ ListTactic::LimitedHorizontalVertical(
+ context.config.width_heuristics().array_width,
+ ),
+ Separator::Comma,
+ nested_shape.width,
+ )
+ } else {
+ DefinitiveListTactic::Mixed
+ }
+ }
};
- let ends_with_newline = tactic.ends_with_newline(context.config.array_indent());
- if context.config.array_horizontal_layout_threshold() > 0
- && items.len() > context.config.array_horizontal_layout_threshold()
- {
- tactic = DefinitiveListTactic::Mixed;
- }
+ let ends_with_newline = tactic.ends_with_newline(context.config.indent_style());
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
trailing_separator: if trailing_comma {
SeparatorTactic::Always
- } else if context.inside_macro || context.config.array_indent() == IndentStyle::Visual {
+ } else if context.inside_macro && !exprs.is_empty() {
+ let ends_with_bracket = context.snippet(span).ends_with(']');
+ let bracket_offset = if ends_with_bracket { 1 } else { 0 };
+ let snippet = context.snippet(mk_sp(span.lo(), span.hi() - BytePos(bracket_offset)));
+ let last_char_index = snippet.rfind(|c: char| !c.is_whitespace())?;
+ if &snippet[last_char_index..last_char_index + 1] == "," {
+ SeparatorTactic::Always
+ } else {
+ SeparatorTactic::Never
+ }
+ } else if context.config.indent_style() == IndentStyle::Visual {
SeparatorTactic::Never
} else {
SeparatorTactic::Vertical
};
let list_str = write_list(&items, &fmt)?;
- let result = if context.config.array_indent() == IndentStyle::Visual
+ let result = if context.config.indent_style() == IndentStyle::Visual
|| tactic == DefinitiveListTactic::Horizontal
{
- if context.config.spaces_within_square_brackets() && !list_str.is_empty() {
+ if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() {
format!("[ {} ]", list_str)
} else {
format!("[{}]", list_str)
Some(result)
}
-// Return type is (prefix, extra_offset)
-fn rewrite_closure_fn_decl(
- capture: ast::CaptureBy,
- fn_decl: &ast::FnDecl,
- body: &ast::Expr,
- span: Span,
- context: &RewriteContext,
- shape: Shape,
-) -> Option<(String, usize)> {
- let mover = if capture == ast::CaptureBy::Value {
- "move "
- } else {
- ""
- };
- // 4 = "|| {".len(), which is overconservative when the closure consists of
- // a single expression.
- let nested_shape = shape.shrink_left(mover.len())?.sub_width(4)?;
-
- // 1 = |
- let argument_offset = nested_shape.indent + 1;
- let arg_shape = nested_shape.offset_left(1)?.visual_indent(0);
- let ret_str = fn_decl.output.rewrite(context, arg_shape)?;
-
- let arg_items = itemize_list(
- context.codemap,
- fn_decl.inputs.iter(),
- "|",
- |arg| span_lo_for_arg(arg),
- |arg| span_hi_for_arg(context, arg),
- |arg| arg.rewrite(context, arg_shape),
- context.codemap.span_after(span, "|"),
- body.span.lo(),
- false,
- );
- let item_vec = arg_items.collect::<Vec<_>>();
- // 1 = space between arguments and return type.
- let horizontal_budget = nested_shape
- .width
- .checked_sub(ret_str.len() + 1)
- .unwrap_or(0);
- let tactic = definitive_tactic(
- &item_vec,
- ListTactic::HorizontalVertical,
- Separator::Comma,
- horizontal_budget,
- );
- let arg_shape = match tactic {
- DefinitiveListTactic::Horizontal => arg_shape.sub_width(ret_str.len() + 1)?,
- _ => arg_shape,
- };
-
- let fmt = ListFormatting {
- tactic: tactic,
- separator: ",",
- trailing_separator: SeparatorTactic::Never,
- separator_place: SeparatorPlace::Back,
- shape: arg_shape,
- ends_with_newline: false,
- preserve_newline: true,
- config: context.config,
- };
- let list_str = write_list(&item_vec, &fmt)?;
- let mut prefix = format!("{}|{}|", mover, list_str);
-
- if !ret_str.is_empty() {
- if prefix.contains('\n') {
- prefix.push('\n');
- prefix.push_str(&argument_offset.to_string(context.config));
- } else {
- prefix.push(' ');
- }
- prefix.push_str(&ret_str);
- }
- // 1 = space between `|...|` and body.
- let extra_offset = last_line_width(&prefix) + 1;
-
- Some((prefix, extra_offset))
-}
-
-// This functions is pretty messy because of the rules around closures and blocks:
-// FIXME - the below is probably no longer true in full.
-// * if there is a return type, then there must be braces,
-// * given a closure with braces, whether that is parsed to give an inner block
-// or not depends on if there is a return type and if there are statements
-// in that block,
-// * if the first expression in the body ends with a block (i.e., is a
-// statement without needing a semi-colon), then adding or removing braces
-// can change whether it is treated as an expression or statement.
-fn rewrite_closure(
- capture: ast::CaptureBy,
- fn_decl: &ast::FnDecl,
- body: &ast::Expr,
- span: Span,
- context: &RewriteContext,
- shape: Shape,
-) -> Option<String> {
- let (prefix, extra_offset) =
- rewrite_closure_fn_decl(capture, fn_decl, body, span, context, shape)?;
- // 1 = space between `|...|` and body.
- let body_shape = shape.offset_left(extra_offset)?;
-
- if let ast::ExprKind::Block(ref block) = body.node {
- // The body of the closure is an empty block.
- if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) {
- return Some(format!("{} {{}}", prefix));
- }
-
- // Figure out if the block is necessary.
- let needs_block = is_unsafe_block(block) || block.stmts.len() > 1 || context.inside_macro
- || block_contains_comment(block, context.codemap)
- || prefix.contains('\n');
-
- let no_return_type = if let ast::FunctionRetTy::Default(_) = fn_decl.output {
- true
- } else {
- false
- };
- if no_return_type && !needs_block {
- // block.stmts.len() == 1
- if let Some(expr) = stmt_expr(&block.stmts[0]) {
- if let Some(rw) = if is_block_closure_forced(expr) {
- rewrite_closure_with_block(context, shape, &prefix, expr)
- } else {
- rewrite_closure_expr(expr, &prefix, context, body_shape)
- } {
- return Some(rw);
- }
- }
- }
-
- // Either we require a block, or tried without and failed.
- rewrite_closure_block(block, &prefix, context, body_shape)
- } else {
- rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| {
- // The closure originally had a non-block expression, but we can't fit on
- // one line, so we'll insert a block.
- rewrite_closure_with_block(context, body_shape, &prefix, body)
- })
- }
-}
-
-// Rewrite closure with a single expression wrapping its body with block.
-fn rewrite_closure_with_block(
- context: &RewriteContext,
- shape: Shape,
- prefix: &str,
- body: &ast::Expr,
-) -> Option<String> {
- let block = ast::Block {
- stmts: vec![
- ast::Stmt {
- id: ast::NodeId::new(0),
- node: ast::StmtKind::Expr(ptr::P(body.clone())),
- span: body.span,
- },
- ],
- id: ast::NodeId::new(0),
- rules: ast::BlockCheckMode::Default,
- span: body.span,
- };
- rewrite_closure_block(&block, prefix, context, shape)
-}
-
-// Rewrite closure with a single expression without wrapping its body with block.
-fn rewrite_closure_expr(
- expr: &ast::Expr,
- prefix: &str,
- context: &RewriteContext,
- shape: Shape,
-) -> Option<String> {
- let mut rewrite = expr.rewrite(context, shape);
- if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) {
- rewrite = and_one_line(rewrite);
- }
- rewrite = rewrite.and_then(|rw| {
- if context.config.multiline_closure_forces_block() && rw.contains('\n') {
- None
- } else {
- Some(rw)
- }
- });
- rewrite.map(|rw| format!("{} {}", prefix, rw))
-}
-
-// Rewrite closure whose body is block.
-fn rewrite_closure_block(
- block: &ast::Block,
- prefix: &str,
- context: &RewriteContext,
- shape: Shape,
-) -> Option<String> {
- // Start with visual indent, then fall back to block indent if the
- // closure is large.
- let block_threshold = context.config.closure_block_indent_threshold();
- if block_threshold >= 0 {
- if let Some(block_str) = block.rewrite(context, shape) {
- if block_str.matches('\n').count() <= block_threshold as usize
- && !need_block_indent(&block_str, shape)
- {
- return Some(format!("{} {}", prefix, block_str));
- }
- }
- }
-
- // The body of the closure is big enough to be block indented, that
- // means we must re-format.
- let block_shape = shape.block();
- let block_str = block.rewrite(context, block_shape)?;
- Some(format!("{} {}", prefix, block_str))
-}
-
-fn and_one_line(x: Option<String>) -> Option<String> {
- x.and_then(|x| if x.contains('\n') { None } else { Some(x) })
-}
-
fn nop_block_collapse(block_str: Option<String>, budget: usize) -> Option<String> {
debug!("nop_block_collapse {:?} {}", block_str, budget);
block_str.map(|block_str| {
None
}
-fn rewrite_block_with_visitor(
+pub fn rewrite_block_with_visitor(
context: &RewriteContext,
prefix: &str,
block: &ast::Block,
shape: Shape,
+ has_braces: bool,
) -> Option<String> {
if let rw @ Some(_) = rewrite_empty_block(context, block, shape) {
return rw;
ast::BlockCheckMode::Default => visitor.last_pos = block.span.lo(),
}
- visitor.visit_block(block, None);
+ visitor.visit_block(block, None, has_braces);
Some(format!("{}{}", prefix, visitor.buffer))
}
}
let prefix = block_prefix(context, self, shape)?;
+ let shape = shape.offset_left(last_line_width(&prefix))?;
- let result = rewrite_block_with_visitor(context, &prefix, self, shape);
+ let result = rewrite_block_with_visitor(context, &prefix, self, shape, true);
if let Some(ref result_str) = result {
if result_str.lines().count() <= 3 {
if let rw @ Some(_) = rewrite_single_line_block(context, &prefix, self, shape) {
}
// Rewrite condition if the given expression has one.
-fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option<String> {
+pub fn rewrite_cond(context: &RewriteContext, expr: &ast::Expr, shape: Shape) -> Option<String> {
match expr.node {
ast::ExprKind::Match(ref cond, _) => {
// `match `cond` {`
- let cond_shape = match context.config.control_style() {
- Style::Legacy => shape.shrink_left(6).and_then(|s| s.sub_width(2))?,
- Style::Rfc => shape.offset_left(8)?,
+ let cond_shape = match context.config.indent_style() {
+ IndentStyle::Visual => shape.shrink_left(6).and_then(|s| s.sub_width(2))?,
+ IndentStyle::Block => shape.offset_left(8)?,
};
cond.rewrite(context, cond_shape)
}
let pat_expr_string = match self.cond {
Some(cond) => {
- let cond_shape = match context.config.control_style() {
- Style::Legacy => constr_shape.shrink_left(offset)?,
- Style::Rfc => constr_shape.offset_left(offset)?,
+ let cond_shape = match context.config.indent_style() {
+ IndentStyle::Visual => constr_shape.shrink_left(offset)?,
+ IndentStyle::Block => constr_shape.offset_left(offset)?,
};
rewrite_pat_expr(
context,
.max_width()
.checked_sub(constr_shape.used_width() + offset + brace_overhead)
.unwrap_or(0);
- let force_newline_brace = context.config.control_style() == Style::Rfc
+ let force_newline_brace = context.config.indent_style() == IndentStyle::Block
&& (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget)
&& !last_line_extendable(&pat_expr_string);
// Try to format if-else on single line.
- if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 {
+ if self.allow_single_line
+ && context
+ .config
+ .width_heuristics()
+ .single_line_if_else_max_width > 0
+ {
let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width);
if let Some(cond_str) = trial {
- if cond_str.len() <= context.config.single_line_if_else_max_width() {
+ if cond_str.len()
+ <= context
+ .config
+ .width_heuristics()
+ .single_line_if_else_max_width
+ {
return Some((cond_str, 0));
}
}
};
let mut block_context = context.clone();
block_context.is_if_else_block = self.else_block.is_some();
- let block_str = rewrite_block_with_visitor(&block_context, "", self.block, block_shape)?;
+ let block_str =
+ rewrite_block_with_visitor(&block_context, "", self.block, block_shape, true)?;
let mut result = format!("{}{}", cond_str, block_str);
}
}
-fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool {
+pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool {
let snippet = codemap.span_to_snippet(block.span).unwrap();
contains_comment(&snippet)
}
}
}
-fn is_unsafe_block(block: &ast::Block) -> bool {
+pub fn is_unsafe_block(block: &ast::Block) -> bool {
if let ast::BlockCheckMode::Unsafe(..) = block.rules {
true
} else {
..shape
};
// 6 = `match `
- let cond_shape = match context.config.control_style() {
- Style::Legacy => cond_shape.shrink_left(6)?,
- Style::Rfc => cond_shape.offset_left(6)?,
+ let cond_shape = match context.config.indent_style() {
+ IndentStyle::Visual => cond_shape.shrink_left(6)?,
+ IndentStyle::Block => cond_shape.offset_left(6)?,
};
let cond_str = cond.rewrite(context, cond_shape)?;
let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config);
inner_attrs[inner_attrs.len() - 1].span().hi()
};
- let arm_indent_str = if context.config.indent_match_arms() {
- nested_indent_str
- } else {
- shape.indent.to_string(context.config)
- };
-
if arms.is_empty() {
let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1)));
if snippet.trim().is_empty() {
cond_str,
block_sep,
inner_attrs_str,
- arm_indent_str,
+ nested_indent_str,
rewrite_match_arms(context, arms, shape, span, open_brace_pos)?,
shape.indent.to_string(context.config),
))
span: Span,
open_brace_pos: BytePos,
) -> Option<String> {
- let arm_shape = if context.config.indent_match_arms() {
- shape.block_indent(context.config.tab_spaces())
- } else {
- shape.block_indent(0)
- }.with_max_width(context.config);
+ let arm_shape = shape
+ .block_indent(context.config.tab_spaces())
+ .with_max_width(context.config);
let arm_len = arms.len();
let is_last_iter = repeat(false)
.zip(is_last_iter)
.map(|(arm, is_last)| ArmWrapper::new(arm, is_last)),
"}",
+ "|",
|arm| arm.arm.span().lo(),
|arm| arm.arm.span().hi(),
|arm| arm.rewrite(context, arm_shape),
arm_comma(context.config, body, is_last),
));
}
- (
- mk_sp(
- arm.attrs[arm.attrs.len() - 1].span.hi(),
- arm.pats[0].span.lo(),
- ),
- arm.attrs.rewrite(context, shape)?,
- )
+ let missing_span = mk_sp(
+ arm.attrs[arm.attrs.len() - 1].span.hi(),
+ arm.pats[0].span.lo(),
+ );
+ (missing_span, arm.attrs.rewrite(context, shape)?)
} else {
(mk_sp(arm.span().lo(), arm.span().lo()), String::new())
};
)
}
+/// Returns true if the given pattern is short. A short pattern is defined by the following grammer:
+///
+/// [small, ntp]:
+/// - single token
+/// - `&[single-line, ntp]`
+///
+/// [small]:
+/// - `[small, ntp]`
+/// - unary tuple constructor `([small, ntp])`
+/// - `&[small]`
+fn is_short_pattern(pat: &ast::Pat, pat_str: &str) -> bool {
+ // We also require that the pattern is reasonably 'small' with its literal width.
+ pat_str.len() <= 20 && !pat_str.contains('\n') && is_short_pattern_inner(pat)
+}
+
+fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
+ match pat.node {
+ ast::PatKind::Wild | ast::PatKind::Lit(_) => true,
+ ast::PatKind::Ident(_, _, ref pat) => pat.is_none(),
+ ast::PatKind::Struct(..)
+ | ast::PatKind::Mac(..)
+ | ast::PatKind::Slice(..)
+ | ast::PatKind::Path(..)
+ | ast::PatKind::Range(..) => false,
+ ast::PatKind::Tuple(ref subpats, _) => subpats.len() <= 1,
+ ast::PatKind::TupleStruct(ref path, ref subpats, _) => {
+ path.segments.len() <= 1 && subpats.len() <= 1
+ }
+ ast::PatKind::Box(ref p) | ast::PatKind::Ref(ref p, _) => is_short_pattern_inner(&*p),
+ }
+}
+
fn rewrite_match_pattern(
context: &RewriteContext,
pats: &[ptr::P<ast::Pat>],
.map(|p| p.rewrite(context, pat_shape))
.collect::<Option<Vec<_>>>()?;
+ let use_mixed_layout = pats.iter()
+ .zip(pat_strs.iter())
+ .all(|(pat, pat_str)| is_short_pattern(pat, pat_str));
let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect();
- let tactic = definitive_tactic(
- &items,
- ListTactic::HorizontalVertical,
- Separator::VerticalBar,
- pat_shape.width,
- );
+ let tactic = if use_mixed_layout {
+ DefinitiveListTactic::Mixed
+ } else {
+ definitive_tactic(
+ &items,
+ ListTactic::HorizontalVertical,
+ Separator::VerticalBar,
+ pat_shape.width,
+ )
+ };
let fmt = ListFormatting {
tactic: tactic,
separator: " |",
trailing_separator: SeparatorTactic::Never,
- separator_place: context.config.match_pattern_separator_break_point(),
+ separator_place: context.config.binop_separator(),
shape: pat_shape,
ends_with_newline: false,
preserve_newline: false,
{
if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node {
(
- !context.config.multiline_match_arm_forces_block()
- && expr.can_be_overflowed(context, 1),
- &**expr,
+ !context.config.force_multiline_blocks() && can_extend_match_arm_body(expr),
+ &*expr,
)
} else {
(false, &*body)
}
}
_ => (
- !context.config.multiline_match_arm_forces_block()
- && body.can_be_overflowed(context, 1),
+ !context.config.force_multiline_blocks() && body.can_be_overflowed(context, 1),
&*body,
),
}
} else {
(false, false)
};
- let extend = if context.config.match_arm_forces_newline() {
- is_block
- } else {
- extend
- };
let comma = arm_comma(context.config, body, is_last);
let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config);
};
let forbid_same_line = has_guard && pats_str.contains('\n') && !is_empty_block;
- let next_line_indent = if is_block {
- if is_empty_block {
- shape.indent.block_indent(context.config)
- } else {
- shape.indent
- }
- } else {
+ let next_line_indent = if !is_block || is_empty_block {
shape.indent.block_indent(context.config)
+ } else {
+ shape.indent
};
let combine_next_line_body = |body_str: &str| {
if is_block {
let indent_str = shape.indent.to_string(context.config);
let nested_indent_str = next_line_indent.to_string(context.config);
- let (body_prefix, body_suffix) = if context.config.wrap_match_arms() {
+ let (body_prefix, body_suffix) = if context.config.match_arm_blocks() {
let comma = if context.config.match_block_trailing_comma() {
","
} else {
match rewrite {
Some(ref body_str)
- if !forbid_same_line && !context.config.match_arm_forces_newline()
+ if !forbid_same_line
&& (is_block
|| (!body_str.contains('\n') && body_str.len() <= body_shape.width)) =>
{
.map(|expr_rw| format!("\n{}{}", nested_indent_str, expr_rw))
}
+fn can_extend_match_arm_body(body: &ast::Expr) -> bool {
+ match body.node {
+ // We do not allow `if` to stay on the same line, since we could easily mistake
+ // `pat => if cond { ... }` and `pat if cond => { ... }`.
+ ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => false,
+ ast::ExprKind::ForLoop(..)
+ | ast::ExprKind::Loop(..)
+ | ast::ExprKind::While(..)
+ | ast::ExprKind::WhileLet(..)
+ | ast::ExprKind::Match(..)
+ | ast::ExprKind::Block(..)
+ | ast::ExprKind::Closure(..)
+ | ast::ExprKind::Array(..)
+ | ast::ExprKind::Call(..)
+ | ast::ExprKind::MethodCall(..)
+ | ast::ExprKind::Mac(..)
+ | ast::ExprKind::Struct(..)
+ | ast::ExprKind::Tup(..) => true,
+ ast::ExprKind::AddrOf(_, ref expr)
+ | ast::ExprKind::Box(ref expr)
+ | ast::ExprKind::Try(ref expr)
+ | ast::ExprKind::Unary(_, ref expr)
+ | ast::ExprKind::Cast(ref expr, _) => can_extend_match_arm_body(expr),
+ _ => false,
+ }
+}
+
pub fn rewrite_literal(context: &RewriteContext, l: &ast::Lit, shape: Shape) -> Option<String> {
match l.node {
ast::LitKind::Str(_, ast::StrStyle::Cooked) => rewrite_string_lit(context, l.span, shape),
- _ => Some(context.snippet(l.span)),
+ _ => wrap_str(context.snippet(l.span), context.config.max_width(), shape),
}
}
fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option<String> {
let string_lit = context.snippet(span);
- if !context.config.format_strings() && !context.config.force_format_strings() {
+ if !context.config.format_strings() {
if string_lit
.lines()
.rev()
.all(|line| line.ends_with('\\'))
{
let new_indent = shape.visual_indent(1).indent;
- return Some(String::from(
+ let indented_string_lit = String::from(
string_lit
.lines()
.map(|line| {
.collect::<Vec<_>>()
.join("\n")
.trim_left(),
- ));
+ );
+ return wrap_str(indented_string_lit, context.config.max_width(), shape);
} else {
- return Some(string_lit);
+ return wrap_str(string_lit, context.config.max_width(), shape);
}
}
- if !context.config.force_format_strings()
- && !string_requires_rewrite(context, span, &string_lit, shape)
- {
- return Some(string_lit);
- }
-
// Remove the quote characters.
let str_lit = &string_lit[1..string_lit.len() - 1];
)
}
-fn string_requires_rewrite(
- context: &RewriteContext,
- span: Span,
- string: &str,
- shape: Shape,
-) -> bool {
- if context.codemap.lookup_char_pos(span.lo()).col.0 != shape.indent.width() {
- return true;
- }
+const FORMAT_LIKE_WHITELIST: &[&str] = &[
+ "eprint!",
+ "eprintln!",
+ "format!",
+ "format_args!",
+ "panic!",
+ "println!",
+ "unreachable!",
+];
- for (i, line) in string.lines().enumerate() {
- if i == 0 {
- if line.len() > shape.width {
- return true;
- }
- } else if line.len() > shape.width + shape.indent.width() {
- return true;
- }
- }
-
- false
-}
+const WRITE_LIKE_WHITELIST: &[&str] = &["assert!", "write!", "writeln!"];
pub fn rewrite_call(
context: &RewriteContext,
&ptr_vec_to_ref_vec(args),
span,
shape,
- context.config.fn_call_width(),
+ context.config.width_heuristics().fn_call_width,
force_trailing_comma,
)
}
T: Rewrite + Spanned + ToExpr + 'a,
{
// 2 = `( `, 1 = `(`
- let paren_overhead = if context.config.spaces_within_parens() {
+ let paren_overhead = if context.config.spaces_within_parens_and_brackets() {
2
} else {
1
let used_width = extra_offset(callee_str, shape);
let one_line_width = shape.width.checked_sub(used_width + 2 * paren_overhead)?;
- let nested_shape = shape_from_fn_call_indent(
+ // 1 = "(" or ")"
+ let one_line_shape = shape
+ .offset_left(last_line_width(callee_str) + 1)?
+ .sub_width(1)?;
+ let nested_shape = shape_from_indent_style(
context,
shape,
used_width + 2 * paren_overhead,
context,
args,
args_span,
+ one_line_shape,
nested_shape,
one_line_width,
args_max_width,
force_trailing_comma,
+ callee_str,
)?;
if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable {
context: &RewriteContext,
args: &[&T],
span: Span,
- shape: Shape,
+ one_line_shape: Shape,
+ nested_shape: Shape,
one_line_width: usize,
args_max_width: usize,
force_trailing_comma: bool,
+ callee_str: &str,
) -> Option<(bool, String)>
where
T: Rewrite + Spanned + ToExpr + 'a,
context.codemap,
args.iter(),
")",
+ ",",
|item| item.span().lo(),
|item| item.span().hi(),
- |item| item.rewrite(context, shape),
+ |item| item.rewrite(context, nested_shape),
span.lo(),
span.hi(),
true,
context,
&mut item_vec,
&args[..],
- shape,
+ one_line_shape,
+ nested_shape,
one_line_width,
args_max_width,
+ callee_str,
);
let fmt = ListFormatting {
context.config.trailing_comma()
},
separator_place: SeparatorPlace::Back,
- shape: shape,
+ shape: nested_shape,
ends_with_newline: context.use_block_indent() && tactic == DefinitiveListTactic::Vertical,
preserve_newline: false,
config: context.config,
};
- write_list(&item_vec, &fmt).map(|args_str| {
- (tactic != DefinitiveListTactic::Vertical, args_str)
- })
+ write_list(&item_vec, &fmt)
+ .map(|args_str| (tactic == DefinitiveListTactic::Horizontal, args_str))
}
fn try_overflow_last_arg<'a, T>(
context: &RewriteContext,
item_vec: &mut Vec<ListItem>,
args: &[&T],
- shape: Shape,
+ one_line_shape: Shape,
+ nested_shape: Shape,
one_line_width: usize,
args_max_width: usize,
+ callee_str: &str,
) -> DefinitiveListTactic
where
T: Rewrite + Spanned + ToExpr + 'a,
{
- let overflow_last = can_be_overflowed(context, args);
+ // 1 = "("
+ let combine_arg_with_callee =
+ callee_str.len() + 1 <= context.config.tab_spaces() && args.len() == 1;
+ let overflow_last = combine_arg_with_callee || can_be_overflowed(context, args);
// Replace the last item with its first line to see if it fits with
// first arguments.
let placeholder = if overflow_last {
let mut context = context.clone();
- if let Some(expr) = args[args.len() - 1].to_expr() {
- if let ast::ExprKind::MethodCall(..) = expr.node {
- context.force_one_line_chain = true;
+ if !combine_arg_with_callee {
+ if let Some(expr) = args[args.len() - 1].to_expr() {
+ if let ast::ExprKind::MethodCall(..) = expr.node {
+ context.force_one_line_chain = true;
+ }
}
}
- last_arg_shape(&context, item_vec, shape, args_max_width).and_then(|arg_shape| {
+ last_arg_shape(args, item_vec, one_line_shape, args_max_width).and_then(|arg_shape| {
rewrite_last_arg_with_overflow(&context, args, &mut item_vec[args.len() - 1], arg_shape)
})
} else {
}
_ if args.len() >= 1 => {
item_vec[args.len() - 1].item = args.last()
- .and_then(|last_arg| last_arg.rewrite(context, shape));
+ .and_then(|last_arg| last_arg.rewrite(context, nested_shape));
+
+ let default_tactic = || {
+ definitive_tactic(
+ &*item_vec,
+ ListTactic::LimitedHorizontalVertical(args_max_width),
+ Separator::Comma,
+ one_line_width,
+ )
+ };
+
// Use horizontal layout for a function with a single argument as long as
// everything fits in a single line.
if args.len() == 1
{
tactic = DefinitiveListTactic::Horizontal;
} else {
- tactic = definitive_tactic(
- &*item_vec,
- ListTactic::LimitedHorizontalVertical(args_max_width),
- Separator::Comma,
- one_line_width,
- );
+ tactic = default_tactic();
+ let is_simple_enough =
+ tactic == DefinitiveListTactic::Vertical && is_every_args_simple(args);
+ if is_simple_enough
+ && FORMAT_LIKE_WHITELIST
+ .iter()
+ .find(|s| **s == callee_str)
+ .is_some()
+ {
+ let args_tactic = definitive_tactic(
+ &item_vec[1..],
+ ListTactic::HorizontalVertical,
+ Separator::Comma,
+ nested_shape.width,
+ );
+ tactic = if args_tactic == DefinitiveListTactic::Horizontal {
+ DefinitiveListTactic::FormatCall
+ } else {
+ default_tactic()
+ };
+ } else if is_simple_enough && item_vec.len() >= 2
+ && WRITE_LIKE_WHITELIST
+ .iter()
+ .find(|s| **s == callee_str)
+ .is_some()
+ {
+ let args_tactic = definitive_tactic(
+ &item_vec[2..],
+ ListTactic::HorizontalVertical,
+ Separator::Comma,
+ nested_shape.width,
+ );
+ tactic = if args_tactic == DefinitiveListTactic::Horizontal {
+ DefinitiveListTactic::WriteCall
+ } else {
+ default_tactic()
+ };
+ }
}
}
_ => (),
tactic
}
-fn last_arg_shape(
- context: &RewriteContext,
- items: &[ListItem],
- shape: Shape,
- args_max_width: usize,
-) -> Option<Shape> {
- let overhead = items.iter().rev().skip(1).fold(0, |acc, i| {
- acc + i.item.as_ref().map_or(0, |s| first_line_width(s))
- });
- let max_width = min(args_max_width, shape.width);
- let arg_indent = if context.use_block_indent() {
- shape.block().indent.block_unindent(context.config)
- } else {
- shape.block().indent
- };
- Some(Shape {
- width: max_width.checked_sub(overhead)?,
- indent: arg_indent,
- offset: 0,
- })
-}
-
-// Rewriting closure which is placed at the end of the function call's arg.
-// Returns `None` if the reformatted closure 'looks bad'.
-fn rewrite_last_closure(
- context: &RewriteContext,
- expr: &ast::Expr,
- shape: Shape,
-) -> Option<String> {
- if let ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) = expr.node {
- let body = match body.node {
- ast::ExprKind::Block(ref block) if is_simple_block(block, context.codemap) => {
- stmt_expr(&block.stmts[0]).unwrap_or(body)
- }
- _ => body,
- };
- let (prefix, extra_offset) =
- rewrite_closure_fn_decl(capture, fn_decl, body, expr.span, context, shape)?;
- // If the closure goes multi line before its body, do not overflow the closure.
- if prefix.contains('\n') {
- return None;
- }
- // If we are inside macro, we do not want to add or remove block from closure body.
- if context.inside_macro {
- return expr.rewrite(context, shape);
- }
-
- let body_shape = shape.offset_left(extra_offset)?;
-
- // We force to use block for the body of the closure for certain kinds of expressions.
- if is_block_closure_forced(body) {
- return rewrite_closure_with_block(context, body_shape, &prefix, body).and_then(
- |body_str| {
- // If the expression can fit in a single line, we need not force block closure.
- if body_str.lines().count() <= 7 {
- match rewrite_closure_expr(body, &prefix, context, shape) {
- Some(ref single_line_body_str)
- if !single_line_body_str.contains('\n') =>
- {
- Some(single_line_body_str.clone())
- }
- _ => Some(body_str),
- }
- } else {
- Some(body_str)
- }
- },
- );
- }
-
- // When overflowing the closure which consists of a single control flow expression,
- // force to use block if its condition uses multi line.
- let is_multi_lined_cond = rewrite_cond(context, body, body_shape)
- .map(|cond| cond.contains('\n') || cond.len() > body_shape.width)
- .unwrap_or(false);
- if is_multi_lined_cond {
- return rewrite_closure_with_block(context, body_shape, &prefix, body);
+fn is_simple_arg(expr: &ast::Expr) -> bool {
+ match expr.node {
+ ast::ExprKind::Lit(..) => true,
+ ast::ExprKind::Path(ref qself, ref path) => qself.is_none() && path.segments.len() <= 1,
+ ast::ExprKind::AddrOf(_, ref expr)
+ | ast::ExprKind::Box(ref expr)
+ | ast::ExprKind::Cast(ref expr, _)
+ | ast::ExprKind::Field(ref expr, _)
+ | ast::ExprKind::Try(ref expr)
+ | ast::ExprKind::TupField(ref expr, _)
+ | ast::ExprKind::Unary(_, ref expr) => is_simple_arg(expr),
+ ast::ExprKind::Index(ref lhs, ref rhs) | ast::ExprKind::Repeat(ref lhs, ref rhs) => {
+ is_simple_arg(lhs) && is_simple_arg(rhs)
}
-
- // Seems fine, just format the closure in usual manner.
- return expr.rewrite(context, shape);
+ _ => false,
}
- None
}
-fn is_block_closure_forced(expr: &ast::Expr) -> bool {
- match expr.node {
- ast::ExprKind::If(..) |
- ast::ExprKind::IfLet(..) |
- ast::ExprKind::Loop(..) |
- ast::ExprKind::While(..) |
- ast::ExprKind::WhileLet(..) |
- ast::ExprKind::ForLoop(..) => true,
- ast::ExprKind::AddrOf(_, ref expr) |
- ast::ExprKind::Box(ref expr) |
- ast::ExprKind::Try(ref expr) |
- ast::ExprKind::Unary(_, ref expr) |
- ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced(expr),
- _ => false,
- }
+fn is_every_args_simple<T: ToExpr>(lists: &[&T]) -> bool {
+ lists
+ .iter()
+ .all(|arg| arg.to_expr().map_or(false, is_simple_arg))
+}
+
+/// Returns a shape for the last argument which is going to be overflowed.
+fn last_arg_shape<T>(
+ lists: &[&T],
+ items: &[ListItem],
+ shape: Shape,
+ args_max_width: usize,
+) -> Option<Shape>
+where
+ T: Rewrite + Spanned + ToExpr,
+{
+ let is_nested_call = lists
+ .iter()
+ .next()
+ .and_then(|item| item.to_expr())
+ .map_or(false, is_nested_call);
+ if items.len() == 1 && !is_nested_call {
+ return Some(shape);
+ }
+ let offset = items.iter().rev().skip(1).fold(0, |acc, i| {
+ // 2 = ", "
+ acc + 2 + i.inner_as_ref().len()
+ });
+ Shape {
+ width: min(args_max_width, shape.width),
+ ..shape
+ }.offset_left(offset)
}
fn rewrite_last_arg_with_overflow<'a, T>(
ast::ExprKind::Closure(..) => {
// If the argument consists of multiple closures, we do not overflow
// the last closure.
- if args_have_many_closure(args) {
+ if closures::args_have_many_closure(args) {
None
} else {
- rewrite_last_closure(context, expr, shape)
+ closures::rewrite_last_closure(context, expr, shape)
}
}
_ => expr.rewrite(context, shape),
}
}
-/// Returns true if the given vector of arguments has more than one `ast::ExprKind::Closure`.
-fn args_have_many_closure<T>(args: &[&T]) -> bool
-where
- T: ToExpr,
-{
- args.iter()
- .filter(|arg| {
- arg.to_expr()
- .map(|e| match e.node {
- ast::ExprKind::Closure(..) => true,
- _ => false,
- })
- .unwrap_or(false)
- })
- .count() > 1
-}
-
fn can_be_overflowed<'a, T>(context: &RewriteContext, args: &[&T]) -> bool
where
T: Rewrite + Spanned + ToExpr + 'a,
match expr.node {
ast::ExprKind::Match(..) => {
(context.use_block_indent() && args_len == 1)
- || (context.config.fn_call_indent() == IndentStyle::Visual && args_len > 1)
- }
- ast::ExprKind::If(..) |
- ast::ExprKind::IfLet(..) |
- ast::ExprKind::ForLoop(..) |
- ast::ExprKind::Loop(..) |
- ast::ExprKind::While(..) |
- ast::ExprKind::WhileLet(..) => {
+ || (context.config.indent_style() == IndentStyle::Visual && args_len > 1)
+ }
+ ast::ExprKind::If(..)
+ | ast::ExprKind::IfLet(..)
+ | ast::ExprKind::ForLoop(..)
+ | ast::ExprKind::Loop(..)
+ | ast::ExprKind::While(..)
+ | ast::ExprKind::WhileLet(..) => {
context.config.combine_control_expr() && context.use_block_indent() && args_len == 1
}
ast::ExprKind::Block(..) | ast::ExprKind::Closure(..) => {
context.use_block_indent()
- || context.config.fn_call_indent() == IndentStyle::Visual && args_len > 1
- }
- ast::ExprKind::Array(..) |
- ast::ExprKind::Call(..) |
- ast::ExprKind::Mac(..) |
- ast::ExprKind::MethodCall(..) |
- ast::ExprKind::Struct(..) |
- ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1,
- ast::ExprKind::AddrOf(_, ref expr) |
- ast::ExprKind::Box(ref expr) |
- ast::ExprKind::Try(ref expr) |
- ast::ExprKind::Unary(_, ref expr) |
- ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len),
+ || context.config.indent_style() == IndentStyle::Visual && args_len > 1
+ }
+ ast::ExprKind::Array(..)
+ | ast::ExprKind::Call(..)
+ | ast::ExprKind::Mac(..)
+ | ast::ExprKind::MethodCall(..)
+ | ast::ExprKind::Struct(..)
+ | ast::ExprKind::Tup(..) => context.use_block_indent() && args_len == 1,
+ ast::ExprKind::AddrOf(_, ref expr)
+ | ast::ExprKind::Box(ref expr)
+ | ast::ExprKind::Try(ref expr)
+ | ast::ExprKind::Unary(_, ref expr)
+ | ast::ExprKind::Cast(ref expr, _) => can_be_overflowed_expr(context, expr, args_len),
+ _ => false,
+ }
+}
+
+fn is_nested_call(expr: &ast::Expr) -> bool {
+ match expr.node {
+ ast::ExprKind::Call(..) | ast::ExprKind::Mac(..) => true,
+ ast::ExprKind::AddrOf(_, ref expr)
+ | ast::ExprKind::Box(ref expr)
+ | ast::ExprKind::Try(ref expr)
+ | ast::ExprKind::Unary(_, ref expr)
+ | ast::ExprKind::Cast(ref expr, _) => is_nested_call(expr),
_ => false,
}
}
|| (context.inside_macro && !args_str.contains('\n')
&& args_str.len() + paren_overhead(context) <= shape.width) || is_extendable
{
- if context.config.spaces_within_parens() && !args_str.is_empty() {
+ if context.config.spaces_within_parens_and_brackets() && !args_str.is_empty() {
format!("( {} )", args_str)
} else {
format!("({})", args_str)
.offset_left(paren_overhead)
.and_then(|s| s.sub_width(paren_overhead))?;
- let paren_wrapper = |s: &str| if context.config.spaces_within_parens() && !s.is_empty() {
- format!("( {} )", s)
- } else {
- format!("({})", s)
- };
+ let paren_wrapper =
+ |s: &str| if context.config.spaces_within_parens_and_brackets() && !s.is_empty() {
+ format!("( {} )", s)
+ } else {
+ format!("({})", s)
+ };
let subexpr_str = subexpr.rewrite(context, sub_shape)?;
debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str);
) -> Option<String> {
let expr_str = expr.rewrite(context, shape)?;
- let (lbr, rbr) = if context.config.spaces_within_square_brackets() {
+ let (lbr, rbr) = if context.config.spaces_within_parens_and_brackets() {
("[ ", " ]")
} else {
("[", "]")
context.codemap,
field_iter,
"}",
+ ",",
span_lo,
span_hi,
rewrite,
let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width);
Some(format!("{} {{{}}}", path_str, fields_str))
- // FIXME if context.config.struct_lit_indent() == Visual, but we run out
+ // FIXME if context.config.indent_style() == Visual, but we run out
// of space, we should fall back to BlockIndent.
}
nested_shape: Shape,
one_line_width: usize,
) -> String {
- if context.config.struct_lit_indent() == IndentStyle::Block
- && (fields_str.contains('\n')
- || context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti
+ if context.config.indent_style() == IndentStyle::Block
+ && (fields_str.contains('\n') || !context.config.struct_lit_single_line()
|| fields_str.len() > one_line_width)
{
format!(
}
pub fn struct_lit_field_separator(config: &Config) -> &str {
- colon_spaces(
- config.space_before_struct_lit_field_colon(),
- config.space_after_struct_lit_field_colon(),
- )
+ colon_spaces(config.space_before_colon(), config.space_after_colon())
}
pub fn rewrite_field(
}
}
-fn shape_from_fn_call_indent(
+fn shape_from_indent_style(
context: &RewriteContext,
shape: Shape,
overhead: usize,
.unwrap()
.rewrite(context, nested_shape)
.map(|s| {
- if context.config.spaces_within_parens() {
+ if context.config.spaces_within_parens_and_brackets() {
format!("( {}, )", s)
} else {
format!("({},)", s)
context.codemap,
items,
")",
+ ",",
|item| item.span().lo(),
|item| item.span().hi(),
|item| item.rewrite(context, nested_shape),
};
let list_str = write_list(&item_vec, &fmt)?;
- if context.config.spaces_within_parens() && !list_str.is_empty() {
+ if context.config.spaces_within_parens_and_brackets() && !list_str.is_empty() {
Some(format!("( {} )", list_str))
} else {
Some(format!("({})", list_str))
items,
span,
shape,
- context.config.fn_call_width(),
+ context.config.width_heuristics().fn_call_width,
force_trailing_comma,
)
} else {
// The left hand side must contain everything up to, and including, the
// assignment operator.
-pub fn rewrite_assign_rhs<S: Into<String>>(
+pub fn rewrite_assign_rhs<S: Into<String>, R: Rewrite>(
context: &RewriteContext,
lhs: S,
- ex: &ast::Expr,
+ ex: &R,
shape: Shape,
) -> Option<String> {
let lhs = lhs.into();
Some(lhs + &rhs)
}
-fn choose_rhs(
+pub fn choose_rhs<R: Rewrite>(
context: &RewriteContext,
- expr: &ast::Expr,
+ expr: &R,
shape: Shape,
orig_rhs: Option<String>,
) -> Option<String> {
let new_indent_str = &new_shape.indent.to_string(context.config);
match (orig_rhs, new_rhs) {
+ (Some(ref orig_rhs), Some(ref new_rhs))
+ if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape)
+ .is_none() =>
+ {
+ Some(format!(" {}", orig_rhs))
+ }
(Some(ref orig_rhs), Some(ref new_rhs)) if prefer_next_line(orig_rhs, new_rhs) => {
Some(format!("\n{}{}", new_indent_str, new_rhs))
}