From 8bca85c4b6203dbbb3524dd2139d07621a7a449e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 28 Mar 2017 10:43:46 +1300 Subject: [PATCH] Support block indent for function calls Uses the `fn_call_style` option. Fixes #1358 --- rfc-rustfmt.toml | 1 + src/config.rs | 1 + src/expr.rs | 56 ++++++++++++++++++++++-------------- tests/config/small_tabs.toml | 1 - tests/source/expr-block.rs | 33 +++++++++++++++++++++ tests/target/expr-block.rs | 55 +++++++++++++++++++++++++++++++---- 6 files changed, 119 insertions(+), 28 deletions(-) diff --git a/rfc-rustfmt.toml b/rfc-rustfmt.toml index a46692917b8..914d19d6cb2 100644 --- a/rfc-rustfmt.toml +++ b/rfc-rustfmt.toml @@ -2,3 +2,4 @@ fn_args_layout = "Block" array_layout = "Block" where_style = "Rfc" generics_indent = "Block" +fn_call_style = "Block" diff --git a/src/config.rs b/src/config.rs index 3793e1fd290..11816945f71 100644 --- a/src/config.rs +++ b/src/config.rs @@ -366,6 +366,7 @@ fn default() -> Config { struct_lit_style: IndentStyle, IndentStyle::Block, "Style of struct definition"; struct_lit_multiline_style: MultilineStyle, MultilineStyle::PreferSingle, "Multiline style on literal structs"; + fn_call_style: IndentStyle, IndentStyle::Visual, "Indentation for function calls, etc."; report_todo: ReportTactic, ReportTactic::Never, "Report all, none or unnumbered occurrences of TODO in source file comments"; report_fixme: ReportTactic, ReportTactic::Never, diff --git a/src/expr.rs b/src/expr.rs index 6ab9e1c3393..5af8742c3b2 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -367,7 +367,7 @@ pub fn rewrite_array<'a, I>(expr_iter: I, let tactic = match context.config.array_layout { IndentStyle::Block => { - // TODO wrong shape in one-line case + // FIXME wrong shape in one-line case match shape.width.checked_sub(2 * bracket_size) { Some(width) => definitive_tactic(&items, ListTactic::HorizontalVertical, width), None => DefinitiveListTactic::Vertical, @@ -1102,7 +1102,7 @@ fn rewrite_match_arm_comment(context: &RewriteContext, let first = missed_str.find(|c: char| !c.is_whitespace()).unwrap_or(missed_str.len()); if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 { // Excessive vertical whitespace before comment should be preserved - // TODO handle vertical whitespace better + // FIXME handle vertical whitespace better result.push('\n'); } let missed_str = missed_str[first..].trim(); @@ -1607,13 +1607,20 @@ fn rewrite_call_inner(context: &RewriteContext, let span = mk_sp(span_lo, span.hi); let used_width = extra_offset(&callee_str, shape); - // 2 is for parens. - let remaining_width = match shape.width.checked_sub(used_width + 2) { + + let nested_shape = match context.config.fn_call_style { + IndentStyle::Block => { + shape.block() + .block_indent(context.config.tab_spaces) + .sub_width(context.config.tab_spaces) + } + // 1 = (, 2 = (). + IndentStyle::Visual => shape.visual_indent(used_width + 1).sub_width(used_width + 2), + }; + let nested_shape = match nested_shape { Some(s) => s, None => return Err(Ordering::Greater), }; - // 1 = ( - let nested_shape = shape.visual_indent(used_width + 1); let arg_count = args.len(); let items = itemize_list(context.codemap, @@ -1621,13 +1628,7 @@ fn rewrite_call_inner(context: &RewriteContext, ")", |item| item.span.lo, |item| item.span.hi, - |item| { - item.rewrite(context, - Shape { - width: remaining_width, - ..nested_shape - }) - }, + |item| item.rewrite(context, nested_shape), span.lo, span.hi); let mut item_vec: Vec<_> = items.collect(); @@ -1648,7 +1649,6 @@ fn rewrite_call_inner(context: &RewriteContext, // first arguments. if overflow_last { let nested_shape = Shape { - width: remaining_width, indent: nested_shape.indent.block_only(), ..nested_shape }; @@ -1666,7 +1666,7 @@ fn rewrite_call_inner(context: &RewriteContext, let tactic = definitive_tactic(&item_vec, ListTactic::LimitedHorizontalVertical(context.config.fn_call_width), - remaining_width); + nested_shape.width); // Replace the stub with the full overflowing last argument if the rewrite // succeeded and its first line fits with the other arguments. @@ -1683,7 +1683,10 @@ fn rewrite_call_inner(context: &RewriteContext, let fmt = ListFormatting { tactic: tactic, separator: ",", - trailing_separator: SeparatorTactic::Never, + trailing_separator: match context.config.fn_call_style { + IndentStyle::Visual => SeparatorTactic::Never, + IndentStyle::Block => context.config.trailing_comma, + }, shape: nested_shape, ends_with_newline: false, config: context.config, @@ -1694,11 +1697,22 @@ fn rewrite_call_inner(context: &RewriteContext, None => return Err(Ordering::Less), }; - Ok(if context.config.spaces_within_parens && list_str.len() > 0 { - format!("{}( {} )", callee_str, list_str) - } else { - format!("{}({})", callee_str, list_str) - }) + let result = if context.config.fn_call_style == IndentStyle::Visual || + !list_str.contains('\n') { + if context.config.spaces_within_parens && list_str.len() > 0 { + format!("{}( {} )", callee_str, list_str) + } else { + format!("{}({})", callee_str, list_str) + } + } else { + format!("{}(\n{}{}\n{})", + callee_str, + nested_shape.indent.to_string(context.config), + list_str, + shape.block().indent.to_string(context.config)) + }; + + Ok(result) } fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option { diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml index 25b2dcf7383..57319012bc3 100644 --- a/tests/config/small_tabs.toml +++ b/tests/config/small_tabs.toml @@ -7,7 +7,6 @@ fn_return_indent = "WithArgs" fn_args_paren_newline = true fn_args_density = "Tall" fn_args_layout = "Visual" -fn_arg_indent = "Visual" where_density = "Tall" where_indent = "Block" where_layout = "Vertical" diff --git a/tests/source/expr-block.rs b/tests/source/expr-block.rs index 5e120b8604c..54132ea862a 100644 --- a/tests/source/expr-block.rs +++ b/tests/source/expr-block.rs @@ -1,4 +1,5 @@ // rustfmt-array_layout: Block +// rustfmt-fn_call_style: Block // Test expressions with block formatting. fn arrays() { @@ -76,3 +77,35 @@ fn arrays() { [ 1 + 3, 4 , 5, 6, 7, 7, fncall::>(3-1)] } + +fn function_calls() { + let items = itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo, + span.hi); + + itemize_list(context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite(context, + Shape { + width: remaining_width, + ..nested_shape + }) + }, + span.lo, + span.hi) +} diff --git a/tests/target/expr-block.rs b/tests/target/expr-block.rs index 6f0bbeb3212..fe393dcad73 100644 --- a/tests/target/expr-block.rs +++ b/tests/target/expr-block.rs @@ -1,4 +1,5 @@ // rustfmt-array_layout: Block +// rustfmt-fn_call_style: Block // Test expressions with block formatting. fn arrays() { @@ -94,15 +95,57 @@ fn arrays() { 1, ]; - let a = WeightedChoice::new(&mut [ - Weighted { weight: x, item: 0 }, - Weighted { weight: 1, item: 1 }, - Weighted { weight: x, item: 2 }, - Weighted { weight: 1, item: 3 }, - ]); + let a = WeightedChoice::new( + &mut [ + Weighted { weight: x, item: 0 }, + Weighted { weight: 1, item: 1 }, + Weighted { weight: x, item: 2 }, + Weighted { weight: 1, item: 3 }, + ], + ); let z = [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, yyyyyyyyyyyyyyyyyyyyyyyyyyy, zzzzzzzzzzzzzzzzz, q]; [1 + 3, 4, 5, 6, 7, 7, fncall::>(3 - 1)] } + +fn function_calls() { + let items = itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo, + span.hi, + ); + + itemize_list( + context.codemap, + args.iter(), + ")", + |item| item.span.lo, + |item| item.span.hi, + |item| { + item.rewrite( + context, + Shape { + width: remaining_width, + ..nested_shape + }, + ) + }, + span.lo, + span.hi, + ) +} -- 2.44.0