X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fexpr.rs;h=674f719b5c74ba8957aece1eb818d6805fb73f29;hb=4568c1a70f64d4ab77f9fd9553d532f0bcbe0d84;hp=4a877ad2487d451c0d527db263ed365555de1008;hpb=353816c596ac16fd1a2dfab88615df5a6b0053ad;p=rust.git diff --git a/src/expr.rs b/src/expr.rs index 4a877ad2487..674f719b5c7 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -12,13 +12,12 @@ use std::cmp::min; use config::lists::*; -use syntax::codemap::{BytePos, CodeMap, Span}; use syntax::parse::token::DelimToken; +use syntax::source_map::{BytePos, SourceMap, Span}; use syntax::{ast, ptr}; 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, CharClasses, FindUncommented, @@ -31,16 +30,18 @@ use macros::{rewrite_macro, MacroArg, MacroPosition}; use matches::rewrite_match; use overflow; +use pairs::{rewrite_all_pairs, rewrite_pair, PairParts}; use patterns::{can_be_overflowed_pat, is_short_pattern, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use shape::{Indent, Shape}; +use source_map::{LineRangeUtils, SpanUtils}; use spanned::Spanned; use string::{rewrite_string, StringFormat}; use types::{can_be_overflowed_type, rewrite_path, PathContext}; use utils::{ - colon_spaces, contains_skip, count_newlines, first_line_width, inner_attributes, - last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec, - semicolon_for_stmt, wrap_str, + colon_spaces, contains_skip, count_newlines, first_line_ends_with, first_line_width, + inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes, + ptr_vec_to_ref_vec, semicolon_for_stmt, wrap_str, }; use vertical::rewrite_with_alignment; use visitor::FmtVisitor; @@ -88,18 +89,18 @@ pub fn format_expr( ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span), ast::ExprKind::Binary(op, ref lhs, ref rhs) => { // FIXME: format comments between operands and operator - rewrite_simple_binaries(context, expr, shape, op).or_else(|| { + rewrite_all_pairs(expr, shape, context).or_else(|| { rewrite_pair( &**lhs, &**rhs, - PairParts::new("", &format!(" {} ", context.snippet(op.span)), ""), + PairParts::infix(&format!(" {} ", context.snippet(op.span))), context, shape, context.config.binop_separator(), ) }) } - ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), + ast::ExprKind::Unary(op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape), ast::ExprKind::Struct(ref path, ref fields, ref base) => rewrite_struct_lit( context, path, @@ -124,7 +125,7 @@ pub fn format_expr( if is_unsafe_block(block) { rewrite_block(block, Some(&expr.attrs), opt_label, context, shape) } else if let rw @ Some(_) = - rewrite_empty_block(context, block, Some(&expr.attrs), "", shape) + rewrite_empty_block(context, block, Some(&expr.attrs), opt_label, "", shape) { // Rewrite block without trying to put it in a single line. rw @@ -136,6 +137,7 @@ pub fn format_expr( &prefix, block, Some(&expr.attrs), + opt_label, shape, true, ) @@ -177,14 +179,16 @@ pub fn format_expr( Some(format!("break{}", id_str)) } } - ast::ExprKind::Yield(ref opt_expr) => if let Some(ref expr) = *opt_expr { - rewrite_unary_prefix(context, "yield ", &**expr, shape) - } else { - Some("yield".to_string()) - }, - ast::ExprKind::Closure(capture, movability, ref fn_decl, ref body, _) => { + ast::ExprKind::Yield(ref opt_expr) => { + if let Some(ref expr) = *opt_expr { + rewrite_unary_prefix(context, "yield ", &**expr, shape) + } else { + Some("yield".to_string()) + } + } + ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) => { closures::rewrite_closure( - capture, movability, fn_decl, body, expr.span, context, shape, + capture, asyncness, movability, fn_decl, body, expr.span, context, shape, ) } ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => { @@ -210,7 +214,7 @@ pub fn format_expr( ast::ExprKind::Cast(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - PairParts::new("", " as ", ""), + PairParts::infix(" as "), context, shape, SeparatorPlace::Front, @@ -218,7 +222,7 @@ pub fn format_expr( ast::ExprKind::Type(ref expr, ref ty) => rewrite_pair( &**expr, &**ty, - PairParts::new("", ": ", ""), + PairParts::infix(": "), context, shape, SeparatorPlace::Back, @@ -287,7 +291,7 @@ fn needs_space_after_range(rhs: &ast::Expr) -> bool { rewrite_pair( &*lhs, &*rhs, - PairParts::new("", &sp_delim, ""), + PairParts::infix(&sp_delim), context, shape, context.config.binop_separator(), @@ -315,17 +319,53 @@ fn needs_space_after_range(rhs: &ast::Expr) -> bool { // We do not format these expressions yet, but they should still // satisfy our width restrictions. ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()), - ast::ExprKind::Catch(ref block) => { + ast::ExprKind::TryBlock(ref block) => { if let rw @ Some(_) = - rewrite_single_line_block(context, "do catch ", block, Some(&expr.attrs), shape) + rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape) { rw } else { - // 9 = `do catch ` + // 9 = `try ` let budget = shape.width.saturating_sub(9); Some(format!( "{}{}", - "do catch ", + "try ", + rewrite_block( + block, + Some(&expr.attrs), + None, + context, + Shape::legacy(budget, shape.indent) + )? + )) + } + } + ast::ExprKind::ObsoleteInPlace(ref lhs, ref rhs) => lhs + .rewrite(context, shape) + .map(|s| s + " <-") + .and_then(|lhs| rewrite_assign_rhs(context, lhs, &**rhs, shape)), + ast::ExprKind::Async(capture_by, _node_id, ref block) => { + let mover = if capture_by == ast::CaptureBy::Value { + "move " + } else { + "" + }; + if let rw @ Some(_) = rewrite_single_line_block( + context, + format!("{}{}", "async ", mover).as_str(), + block, + Some(&expr.attrs), + None, + shape, + ) { + rw + } else { + // 6 = `async ` + let budget = shape.width.saturating_sub(6); + Some(format!( + "{}{}{}", + "async ", + mover, rewrite_block( block, Some(&expr.attrs), @@ -351,172 +391,6 @@ fn needs_space_after_range(rhs: &ast::Expr) -> bool { }) } -/// Collect operands that appears in the given binary operator in the opposite order. -/// e.g. `collect_binary_items(e, ||)` for `a && b || c || d` returns `[d, c, a && b]`. -fn collect_binary_items<'a>(mut expr: &'a ast::Expr, binop: ast::BinOp) -> Vec<&'a ast::Expr> { - let mut result = vec![]; - let mut prev_lhs = None; - loop { - match expr.node { - ast::ExprKind::Binary(inner_binop, ref lhs, ref rhs) - if inner_binop.node == binop.node => - { - result.push(&**rhs); - expr = lhs; - prev_lhs = Some(lhs); - } - _ => { - if let Some(lhs) = prev_lhs { - result.push(lhs); - } - break; - } - } - } - result -} - -/// Rewrites a binary expression whose operands fits within a single line. -fn rewrite_simple_binaries( - context: &RewriteContext, - expr: &ast::Expr, - shape: Shape, - op: ast::BinOp, -) -> Option { - let op_str = context.snippet(op.span); - - // 2 = spaces around a binary operator. - let sep_overhead = op_str.len() + 2; - let nested_overhead = sep_overhead - 1; - - let nested_shape = (match context.config.indent_style() { - IndentStyle::Visual => shape.visual_indent(0), - IndentStyle::Block => shape.block_indent(context.config.tab_spaces()), - }).with_max_width(context.config); - let nested_shape = match context.config.binop_separator() { - SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?, - SeparatorPlace::Front => nested_shape.offset_left(nested_overhead)?, - }; - - let opt_rewrites: Option> = collect_binary_items(expr, op) - .iter() - .rev() - .map(|e| e.rewrite(context, nested_shape)) - .collect(); - if let Some(rewrites) = opt_rewrites { - if rewrites.iter().all(|e| ::utils::is_single_line(e)) { - let total_width = rewrites.iter().map(|s| s.len()).sum::() - + sep_overhead * (rewrites.len() - 1); - - let sep_str = if total_width <= shape.width { - format!(" {} ", op_str) - } else { - let indent_str = nested_shape.indent.to_string_with_newline(context.config); - match context.config.binop_separator() { - SeparatorPlace::Back => format!(" {}{}", op_str.trim_right(), indent_str), - SeparatorPlace::Front => format!("{}{} ", indent_str, op_str.trim_left()), - } - }; - - return wrap_str(rewrites.join(&sep_str), context.config.max_width(), shape); - } - } - - None -} - -#[derive(new, Clone, Copy)] -pub struct PairParts<'a> { - prefix: &'a str, - infix: &'a str, - suffix: &'a str, -} - -pub fn rewrite_pair( - lhs: &LHS, - rhs: &RHS, - pp: PairParts, - context: &RewriteContext, - shape: Shape, - separator_place: SeparatorPlace, -) -> Option -where - LHS: Rewrite, - RHS: Rewrite, -{ - let lhs_overhead = match separator_place { - SeparatorPlace::Back => shape.used_width() + pp.prefix.len() + pp.infix.trim_right().len(), - SeparatorPlace::Front => shape.used_width(), - }; - let lhs_shape = Shape { - width: context.budget(lhs_overhead), - ..shape - }; - let lhs_result = lhs - .rewrite(context, lhs_shape) - .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?; - - // Try to put both lhs and rhs on the same line. - let rhs_orig_result = shape - .offset_left(last_line_width(&lhs_result) + pp.infix.len()) - .and_then(|s| s.sub_width(pp.suffix.len())) - .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape)); - if let Some(ref rhs_result) = rhs_orig_result { - // If the length of the lhs is equal to or shorter than the tab width or - // the rhs looks like block expression, we put the rhs on the same - // line with the lhs even if the rhs is multi-lined. - let allow_same_line = lhs_result.len() <= context.config.tab_spaces() - || rhs_result - .lines() - .next() - .map(|first_line| first_line.ends_with('{')) - .unwrap_or(false); - if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) - + pp.infix.len() - + first_line_width(rhs_result) - + pp.suffix.len(); - if one_line_width <= shape.width { - return Some(format!( - "{}{}{}{}", - lhs_result, pp.infix, rhs_result, pp.suffix - )); - } - } - } - - // We have to use multiple lines. - // Re-evaluate the rhs because we have more space now: - 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()), - 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) - .sub_width(rhs_overhead)? - } - }; - let infix = match separator_place { - SeparatorPlace::Back => pp.infix.trim_right(), - SeparatorPlace::Front => pp.infix.trim_left(), - }; - if separator_place == SeparatorPlace::Front { - rhs_shape = rhs_shape.offset_left(infix.len())?; - } - let rhs_result = rhs.rewrite(context, rhs_shape)?; - let indent_str = rhs_shape.indent.to_string_with_newline(context.config); - let infix_with_sep = match separator_place { - SeparatorPlace::Back => format!("{}{}", infix, indent_str), - SeparatorPlace::Front => format!("{}{}", indent_str, infix), - }; - Some(format!( - "{}{}{}{}", - lhs_result, infix_with_sep, rhs_result, pp.suffix - )) -} - pub fn rewrite_array( name: &str, exprs: &[&T], @@ -541,16 +415,20 @@ fn rewrite_empty_block( context: &RewriteContext, block: &ast::Block, attrs: Option<&[ast::Attribute]>, + label: Option, prefix: &str, shape: Shape, ) -> Option { + let label_str = rewrite_label(label); if attrs.map_or(false, |a| !inner_attributes(a).is_empty()) { return None; } - if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) && shape.width >= 2 + if block.stmts.is_empty() + && !block_contains_comment(block, context.source_map) + && shape.width >= 2 { - return Some(format!("{}{{}}", prefix)); + return Some(format!("{}{}{{}}", prefix, label_str)); } // If a block contains only a single-line comment, then leave it on one line. @@ -563,7 +441,7 @@ fn rewrite_empty_block( && !comment_str.starts_with("//") && comment_str.len() + 4 <= shape.width { - return Some(format!("{}{{ {} }}", prefix, comment_str)); + return Some(format!("{}{}{{ {} }}", prefix, label_str, comment_str)); } } @@ -603,12 +481,14 @@ fn rewrite_single_line_block( prefix: &str, block: &ast::Block, attrs: Option<&[ast::Attribute]>, + label: Option, shape: Shape, ) -> Option { - if is_simple_block(block, attrs, context.codemap) { + if is_simple_block(block, attrs, context.source_map) { let expr_shape = shape.offset_left(last_line_width(prefix))?; let expr_str = block.stmts[0].rewrite(context, expr_shape)?; - let result = format!("{}{{ {} }}", prefix, expr_str); + let label_str = rewrite_label(label); + let result = format!("{}{}{{ {} }}", prefix, label_str, expr_str); if result.len() <= shape.width && !result.contains('\n') { return Some(result); } @@ -621,10 +501,11 @@ pub fn rewrite_block_with_visitor( prefix: &str, block: &ast::Block, attrs: Option<&[ast::Attribute]>, + label: Option, shape: Shape, has_braces: bool, ) -> Option { - if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, prefix, shape) { + if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, label, prefix, shape) { return rw; } @@ -641,8 +522,9 @@ pub fn rewrite_block_with_visitor( } let inner_attrs = attrs.map(inner_attributes); + let label_str = rewrite_label(label); visitor.visit_block(block, inner_attrs.as_ref().map(|a| &**a), has_braces); - Some(format!("{}{}", prefix, visitor.buffer)) + Some(format!("{}{}{}", prefix, label_str, visitor.buffer)) } impl Rewrite for ast::Block { @@ -658,20 +540,20 @@ fn rewrite_block( context: &RewriteContext, shape: Shape, ) -> Option { - let unsafe_string = block_prefix(context, block, shape)?; - let label_string = rewrite_label(label); - let prefix = format!("{}{}", unsafe_string, label_string); + let prefix = block_prefix(context, block, shape)?; // shape.width is used only for the single line case: either the empty block `{}`, // or an unsafe expression `unsafe { e }`. - if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, &prefix, shape) { + if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, label, &prefix, shape) { return rw; } - let result = rewrite_block_with_visitor(context, &prefix, block, attrs, shape, true); + let result = rewrite_block_with_visitor(context, &prefix, block, attrs, label, 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, block, attrs, shape) { + if let rw @ Some(_) = + rewrite_single_line_block(context, &prefix, block, attrs, label, shape) + { return rw; } } @@ -888,8 +770,8 @@ fn rewrite_single_line( let fixed_cost = self.keyword.len() + " { } else { }".len(); if let ast::ExprKind::Block(ref else_node, _) = else_block.node { - if !is_simple_block(self.block, None, context.codemap) - || !is_simple_block(else_node, None, context.codemap) + if !is_simple_block(self.block, None, context.source_map) + || !is_simple_block(else_node, None, context.source_map) || pat_expr_str.contains('\n') { return None; @@ -1012,16 +894,16 @@ fn rewrite_cond( && context .config .width_heuristics() - .single_line_if_else_max_width > 0 + .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 - .width_heuristics() - .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)); } @@ -1123,7 +1005,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { let block_str = { let old_val = context.is_if_else_block.replace(self.else_block.is_some()); let result = - rewrite_block_with_visitor(context, "", self.block, None, block_shape, true); + rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true); context.is_if_else_block.replace(old_val); result? }; @@ -1147,7 +1029,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { false, true, mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) + ) + .rewrite(context, shape) } ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => { ControlFlow::new_if( @@ -1158,7 +1041,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { false, true, mk_sp(else_block.span.lo(), self.span.hi()), - ).rewrite(context, shape) + ) + .rewrite(context, shape) } _ => { last_in_chain = true; @@ -1232,8 +1116,8 @@ fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option } } -pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { - let snippet = codemap.span_to_snippet(block.span).unwrap(); +pub fn block_contains_comment(block: &ast::Block, source_map: &SourceMap) -> bool { + let snippet = source_map.span_to_snippet(block.span).unwrap(); contains_comment(&snippet) } @@ -1244,11 +1128,11 @@ pub fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool { pub fn is_simple_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, - codemap: &CodeMap, + source_map: &SourceMap, ) -> bool { (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) - && !block_contains_comment(block, codemap) + && !block_contains_comment(block, source_map) && attrs.map_or(true, |a| a.is_empty())) } @@ -1257,10 +1141,10 @@ pub fn is_simple_block( pub fn is_simple_block_stmt( block: &ast::Block, attrs: Option<&[ast::Attribute]>, - codemap: &CodeMap, + source_map: &SourceMap, ) -> bool { block.stmts.len() <= 1 - && !block_contains_comment(block, codemap) + && !block_contains_comment(block, source_map) && attrs.map_or(true, |a| a.is_empty()) } @@ -1269,10 +1153,10 @@ pub fn is_simple_block_stmt( pub fn is_empty_block( block: &ast::Block, attrs: Option<&[ast::Attribute]>, - codemap: &CodeMap, + source_map: &SourceMap, ) -> bool { block.stmts.is_empty() - && !block_contains_comment(block, codemap) + && !block_contains_comment(block, source_map) && attrs.map_or(true, |a| inner_attributes(a).is_empty()) } @@ -1316,16 +1200,11 @@ pub fn rewrite_multiple_patterns( shape.width, ) }; - let fmt = ListFormatting { - tactic, - separator: " |", - trailing_separator: SeparatorTactic::Never, - separator_place: context.config.binop_separator(), - shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; + let fmt = ListFormatting::new(shape, context.config) + .tactic(tactic) + .separator(" |") + .separator_place(context.config.binop_separator()) + .ends_with_newline(false); write_list(&items, &fmt) } @@ -1377,7 +1256,6 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt rewrite_string( str_lit, &StringFormat::new(shape.visual_indent(0), context.config), - None, ) } @@ -1611,7 +1489,12 @@ fn rewrite_index( .offset_left(offset) .and_then(|shape| shape.sub_width(1 + rhs_overhead)) } else { - shape.visual_indent(offset).sub_width(offset + 1) + match context.config.indent_style() { + IndentStyle::Block => shape + .offset_left(offset) + .and_then(|shape| shape.sub_width(1)), + IndentStyle::Visual => shape.visual_indent(offset).sub_width(offset + 1), + } }; let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s)); @@ -1646,7 +1529,7 @@ fn rewrite_index( } } -fn struct_lit_can_be_aligned(fields: &[ast::Field], base: &Option<&ast::Expr>) -> bool { +fn struct_lit_can_be_aligned(fields: &[ast::Field], base: Option<&ast::Expr>) -> bool { if base.is_some() { return false; } @@ -1682,7 +1565,7 @@ enum StructLitField<'a> { let one_line_width = h_shape.map_or(0, |shape| shape.width); let body_lo = context.snippet_provider.span_after(span, "{"); - let fields_str = if struct_lit_can_be_aligned(fields, &base) + let fields_str = if struct_lit_can_be_aligned(fields, base) && context.config.struct_field_align_threshold() > 0 { rewrite_with_alignment( @@ -1801,9 +1684,9 @@ pub fn rewrite_field( if !attrs_str.is_empty() { attrs_str.push_str(&shape.indent.to_string_with_newline(context.config)); }; - let name = &field.ident.name.to_string(); + let name = context.snippet(field.ident.span); if field.is_shorthand { - Some(attrs_str + &name) + Some(attrs_str + name) } else { let mut separator = String::from(struct_lit_field_separator(context.config)); for _ in 0..prefix_max_width.saturating_sub(name.len()) { @@ -1815,7 +1698,7 @@ pub fn rewrite_field( match expr { Some(ref e) if e.as_str() == name && context.config.use_field_init_shorthand() => { - Some(attrs_str + &name) + Some(attrs_str + name) } Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)), None => { @@ -1880,16 +1763,9 @@ fn rewrite_tuple_in_visual_indent_style<'a, T>( Separator::Comma, nested_shape.width, ); - let fmt = ListFormatting { - tactic, - separator: ",", - trailing_separator: SeparatorTactic::Never, - separator_place: SeparatorPlace::Back, - shape, - ends_with_newline: false, - preserve_newline: false, - config: context.config, - }; + let fmt = ListFormatting::new(nested_shape, context.config) + .tactic(tactic) + .ends_with_newline(false); let list_str = write_list(&item_vec, &fmt)?; Some(format!("({})", list_str)) @@ -1961,12 +1837,12 @@ pub fn rewrite_unary_suffix( fn rewrite_unary_op( context: &RewriteContext, - op: &ast::UnOp, + op: ast::UnOp, expr: &ast::Expr, shape: Shape, ) -> Option { // For some reason, an UnOp is not spanned like BinOp! - let operator_str = match *op { + let operator_str = match op { ast::UnOp::Deref => "*", ast::UnOp::Not => "!", ast::UnOp::Neg => "-", @@ -1998,8 +1874,8 @@ fn rewrite_assignment( pub enum RhsTactics { /// Use heuristics. Default, - /// Put the rhs on the next line if it uses multiple line. - ForceNextLine, + /// Put the rhs on the next line if it uses multiple line, without extra indentation. + ForceNextLineWithoutIndent, } // The left hand side must contain everything up to, and including, the @@ -2056,11 +1932,12 @@ fn choose_rhs( _ => { // Expression did not fit on the same line as the identifier. // Try splitting the line and see if that works better. - let new_shape = - Shape::indented(shape.indent.block_indent(context.config), context.config) - .sub_width(shape.rhs_overhead(context.config))?; + let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics)?; let new_rhs = expr.rewrite(context, new_shape); - let new_indent_str = &new_shape.indent.to_string_with_newline(context.config); + let new_indent_str = &shape + .indent + .block_indent(context.config) + .to_string_with_newline(context.config); match (orig_rhs, new_rhs) { (Some(ref orig_rhs), Some(ref new_rhs)) @@ -2076,16 +1953,33 @@ fn choose_rhs( } (None, Some(ref new_rhs)) => Some(format!("{}{}", new_indent_str, new_rhs)), (None, None) => None, - (Some(ref orig_rhs), _) => Some(format!(" {}", orig_rhs)), + (Some(orig_rhs), _) => Some(format!(" {}", orig_rhs)), } } } } +fn shape_from_rhs_tactic( + context: &RewriteContext, + shape: Shape, + rhs_tactic: RhsTactics, +) -> Option { + match rhs_tactic { + RhsTactics::ForceNextLineWithoutIndent => Some(shape.with_max_width(context.config)), + RhsTactics::Default => { + Shape::indented(shape.indent.block_indent(context.config), context.config) + .sub_width(shape.rhs_overhead(context.config)) + } + } +} + pub fn prefer_next_line(orig_rhs: &str, next_line_rhs: &str, rhs_tactics: RhsTactics) -> bool { - rhs_tactics == RhsTactics::ForceNextLine + rhs_tactics == RhsTactics::ForceNextLineWithoutIndent || !next_line_rhs.contains('\n') || count_newlines(orig_rhs) > count_newlines(next_line_rhs) + 1 + || first_line_ends_with(orig_rhs, '(') && !first_line_ends_with(next_line_rhs, '(') + || first_line_ends_with(orig_rhs, '{') && !first_line_ends_with(next_line_rhs, '{') + || first_line_ends_with(orig_rhs, '[') && !first_line_ends_with(next_line_rhs, '[') } fn rewrite_expr_addrof(