diff --git a/src/closures.rs b/src/closures.rs index 69ffd888957..d3cc5a8ffb3 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -3,7 +3,7 @@ use syntax::{ast, ptr}; use crate::attr::get_attrs_from_stmt; use crate::config::lists::*; -use crate::config::Version; +use crate::config::{IndentStyle, SeparatorTactic, Version}; use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond}; use crate::items::{span_hi_for_param, span_lo_for_param}; use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; @@ -238,9 +238,16 @@ fn rewrite_closure_fn_decl( .shrink_left(is_async.len() + mover.len() + immovable.len())? .sub_width(4)?; + let indent_style = context.config.indent_style(); + // 1 = | let param_offset = nested_shape.indent + 1; - let param_shape = nested_shape.offset_left(1)?.visual_indent(0); + let param_shape = match indent_style { + IndentStyle::Block => { + Shape::indented(shape.indent.block_indent(context.config), context.config) + } + IndentStyle::Visual => nested_shape.offset_left(1)?.visual_indent(0), + }; let ret_str = fn_decl.output.rewrite(context, param_shape)?; let param_items = itemize_list( @@ -273,10 +280,31 @@ fn rewrite_closure_fn_decl( .tactic(tactic) .preserve_newline(true); let list_str = write_list(&item_vec, &fmt)?; - let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, list_str); + let one_line_budget = context.budget(param_shape.indent.width()); + let multi_line_params = match indent_style { + IndentStyle::Block => list_str.contains('\n') || list_str.len() > one_line_budget, + _ => false, + }; + let put_params_in_block = multi_line_params && !item_vec.is_empty(); + let param_str = if put_params_in_block { + let trailing_comma = match context.config.trailing_comma() { + SeparatorTactic::Never => "", + _ => ",", + }; + format!( + "{}{}{}{}", + param_shape.indent.to_string_with_newline(context.config), + &list_str, + trailing_comma, + shape.indent.to_string_with_newline(context.config) + ) + } else { + list_str + }; + let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, param_str); if !ret_str.is_empty() { - if prefix.contains('\n') { + if prefix.contains('\n') && !put_params_in_block { prefix.push('\n'); prefix.push_str(¶m_offset.to_string(context.config)); } else { diff --git a/tests/source/closure.rs b/tests/source/closure_block_style.rs similarity index 91% rename from tests/source/closure.rs rename to tests/source/closure_block_style.rs index e93cc3fb40f..90cb606afe6 100644 --- a/tests/source/closure.rs +++ b/tests/source/closure_block_style.rs @@ -1,3 +1,4 @@ +// rustfmt-indent_style: Block // rustfmt-normalize_comments: true // Closures @@ -211,3 +212,15 @@ fn issue2262() { slave: None, })?; } + +fn issue_3865() { + { +let write_status = |status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style, + show_hints: bool, + hints: &[&str]|-> Option { Some(true) };} + let baz = |foo: bool| -> Option { Some(true) }; + let write_status = |status: &mut Vec,diff: &Diff,heading: &str,color: &Style,| -> Option { Some(true) }; +} diff --git a/tests/source/closure_block_style_no_comma.rs b/tests/source/closure_block_style_no_comma.rs new file mode 100644 index 00000000000..a806f3efc8a --- /dev/null +++ b/tests/source/closure_block_style_no_comma.rs @@ -0,0 +1,17 @@ +// rustfmt-indent_style: Block +// rustfmt-trailing_comma: Never + +fn foo() { + { +let write_status = |status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style, + show_hints: bool, + hints: &[&str]|-> Option { Some(true) };} +} + +fn bar() { + let write_status = |status: &mut Vec,diff: &Diff,heading: &str,color: &Style,| -> Option { Some(true) }; + let baz = |foo: bool| -> Option { Some(true) }; +} diff --git a/tests/source/closure_visual_style.rs b/tests/source/closure_visual_style.rs new file mode 100644 index 00000000000..4fdefc0d7b2 --- /dev/null +++ b/tests/source/closure_visual_style.rs @@ -0,0 +1,70 @@ +// rustfmt-indent_style: Visual +// rustfmt-normalize_comments: true + +fn foo() { + { +let write_status = |status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style, + show_hints: bool, + hints: &[&str]|-> Option { Some(true) };} +} + +fn bar() { + let write_status = |status: &mut Vec,diff: &Diff,heading: &str,color: &Style,| -> Option { Some(true) }; + let baz = |foo: bool| -> Option { Some(true) }; +} + +fn main() { + let square = ( |i: i32 | i * i ); + + let commented = |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| { + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) + }; + + let commented2 = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ | + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // format comments. + if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo() + } else { + field.span.lo() + }}; + + let unblock_me = |trivial| { + closure() + }; + + let empty = |arg| {}; + + let simple = |arg| { /* comment formatting */ foo(arg) }; + + let test = | | { do_something(); do_something_else(); }; + + let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()}; + + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { + foo() + }; + + let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; + + |arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3; + arg2 * arg1 - temp }; + +} diff --git a/tests/target/closure.rs b/tests/target/closure_block_style.rs similarity index 86% rename from tests/target/closure.rs rename to tests/target/closure_block_style.rs index f3107d19c2f..077b8017a4b 100644 --- a/tests/target/closure.rs +++ b/tests/target/closure_block_style.rs @@ -1,25 +1,28 @@ +// rustfmt-indent_style: Block // rustfmt-normalize_comments: true // Closures fn main() { let square = (|i: i32| i * i); - let commented = |// first - a, // argument - // second - b: WithType, // argument - // ignored - _| { + let commented = | + // first + a, // argument + // second + b: WithType, // argument + // ignored + _, + | { ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ) }; - let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, - ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { - xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy - }; + let block_body = move | + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy, + | { xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy }; let loooooooooooooong_name = |field| { // format comments. @@ -248,3 +251,23 @@ fn issue2262() { slave: None, })?; } + +fn issue_3865() { + { + let write_status = | + status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style, + show_hints: bool, + hints: &[&str], + | -> Option { Some(true) }; + } + let baz = |foo: bool| -> Option { Some(true) }; + let write_status = | + status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style, + | -> Option { Some(true) }; +} diff --git a/tests/target/closure_block_style_no_comma.rs b/tests/target/closure_block_style_no_comma.rs new file mode 100644 index 00000000000..e320e4e8487 --- /dev/null +++ b/tests/target/closure_block_style_no_comma.rs @@ -0,0 +1,25 @@ +// rustfmt-indent_style: Block +// rustfmt-trailing_comma: Never + +fn foo() { + { + let write_status = | + status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style, + show_hints: bool, + hints: &[&str] + | -> Option { Some(true) }; + } +} + +fn bar() { + let write_status = | + status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style + | -> Option { Some(true) }; + let baz = |foo: bool| -> Option { Some(true) }; +} diff --git a/tests/target/closure_visual_style.rs b/tests/target/closure_visual_style.rs new file mode 100644 index 00000000000..a4593b12cfe --- /dev/null +++ b/tests/target/closure_visual_style.rs @@ -0,0 +1,90 @@ +// rustfmt-indent_style: Visual +// rustfmt-normalize_comments: true + +fn foo() { + { + let write_status = |status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style, + show_hints: bool, + hints: &[&str]| + -> Option { Some(true) }; + } +} + +fn bar() { + let write_status = |status: &mut Vec, + diff: &Diff, + heading: &str, + color: &Style| + -> Option { Some(true) }; + let baz = |foo: bool| -> Option { Some(true) }; +} + +fn main() { + let square = (|i: i32| i * i); + + let commented = |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| { + (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb) + }; + + let commented2 = + |// first + a, // argument + // second + b: WithType, // argument + // ignored + _| (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + + let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, + ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| { + xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy + }; + + let loooooooooooooong_name = |field| { + // format comments. + if field.node.attrs.len() > 0 { + field.node.attrs[0].span.lo() + } else { + field.span.lo() + } + }; + + let unblock_me = |trivial| closure(); + + let empty = |arg| {}; + + let simple = |arg| { + // comment formatting + foo(arg) + }; + + let test = || { + do_something(); + do_something_else(); + }; + + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let arg_test = + |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame(); + + let simple_closure = move || -> () {}; + + let closure = |input: Ty| -> Option { foo() }; + + let closure_with_return_type = + |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() }; + + |arg1, arg2, _, _, arg3, arg4| { + let temp = arg4 + arg3; + arg2 * arg1 - temp + }; +} diff --git a/tests/target/fn-param-attributes.rs b/tests/target/fn-param-attributes.rs index 829575518de..f4afe84c797 100644 --- a/tests/target/fn-param-attributes.rs +++ b/tests/target/fn-param-attributes.rs @@ -28,11 +28,13 @@ impl MutStruct { } fn main() { - let c = |#[allow(C)] a: u32, - #[cfg(something)] b: i32, - #[cfg_attr(something, cfg(nothing))] - #[deny(C)] - c: i32| {}; + let c = | + #[allow(C)] a: u32, + #[cfg(something)] b: i32, + #[cfg_attr(something, cfg(nothing))] + #[deny(C)] + c: i32, + | {}; let _ = c(1, 2); } diff --git a/tests/target/mulit-file.rs b/tests/target/multi-file.rs similarity index 68% rename from tests/target/mulit-file.rs rename to tests/target/multi-file.rs index 1f829b36f3f..c24b07397dd 100644 --- a/tests/target/mulit-file.rs +++ b/tests/target/multi-file.rs @@ -2,9 +2,9 @@ // crash. #[cfg(all(foo))] -#[path = "closure.rs"] +#[path = "closure_block_style.rs"] pub mod imp; #[cfg(all(bar))] -#[path = "closure.rs"] +#[path = "closure_block_style.rs"] pub mod imp;