Skip to content

Commit e0077aa

Browse files
calebcartwrighttopecongiro
authored andcommitted
support closure block indent_style (#3867)
1 parent 031e029 commit e0077aa

9 files changed

+289
-21
lines changed

src/closures.rs

+32-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use syntax::{ast, ptr};
33

44
use crate::attr::get_attrs_from_stmt;
55
use crate::config::lists::*;
6-
use crate::config::Version;
6+
use crate::config::{IndentStyle, SeparatorTactic, Version};
77
use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond};
88
use crate::items::{span_hi_for_param, span_lo_for_param};
99
use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
@@ -238,9 +238,16 @@ fn rewrite_closure_fn_decl(
238238
.shrink_left(is_async.len() + mover.len() + immovable.len())?
239239
.sub_width(4)?;
240240

241+
let indent_style = context.config.indent_style();
242+
241243
// 1 = |
242244
let param_offset = nested_shape.indent + 1;
243-
let param_shape = nested_shape.offset_left(1)?.visual_indent(0);
245+
let param_shape = match indent_style {
246+
IndentStyle::Block => {
247+
Shape::indented(shape.indent.block_indent(context.config), context.config)
248+
}
249+
IndentStyle::Visual => nested_shape.offset_left(1)?.visual_indent(0),
250+
};
244251
let ret_str = fn_decl.output.rewrite(context, param_shape)?;
245252

246253
let param_items = itemize_list(
@@ -273,10 +280,31 @@ fn rewrite_closure_fn_decl(
273280
.tactic(tactic)
274281
.preserve_newline(true);
275282
let list_str = write_list(&item_vec, &fmt)?;
276-
let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, list_str);
283+
let one_line_budget = context.budget(param_shape.indent.width());
284+
let multi_line_params = match indent_style {
285+
IndentStyle::Block => list_str.contains('\n') || list_str.len() > one_line_budget,
286+
_ => false,
287+
};
288+
let put_params_in_block = multi_line_params && !item_vec.is_empty();
289+
let param_str = if put_params_in_block {
290+
let trailing_comma = match context.config.trailing_comma() {
291+
SeparatorTactic::Never => "",
292+
_ => ",",
293+
};
294+
format!(
295+
"{}{}{}{}",
296+
param_shape.indent.to_string_with_newline(context.config),
297+
&list_str,
298+
trailing_comma,
299+
shape.indent.to_string_with_newline(context.config)
300+
)
301+
} else {
302+
list_str
303+
};
304+
let mut prefix = format!("{}{}{}|{}|", is_async, immovable, mover, param_str);
277305

278306
if !ret_str.is_empty() {
279-
if prefix.contains('\n') {
307+
if prefix.contains('\n') && !put_params_in_block {
280308
prefix.push('\n');
281309
prefix.push_str(&param_offset.to_string(context.config));
282310
} else {

tests/source/closure.rs renamed to tests/source/closure_block_style.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// rustfmt-indent_style: Block
12
// rustfmt-normalize_comments: true
23
// Closures
34

@@ -211,3 +212,15 @@ fn issue2262() {
211212
slave: None,
212213
})?;
213214
}
215+
216+
fn issue_3865() {
217+
{
218+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,
219+
diff: &Diff,
220+
heading: &str,
221+
color: &Style,
222+
show_hints: bool,
223+
hints: &[&str]|-> Option<bool> { Some(true) };}
224+
let baz = |foo: bool| -> Option<bool> { Some(true) };
225+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,diff: &Diff,heading: &str,color: &Style,| -> Option<bool> { Some(true) };
226+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// rustfmt-indent_style: Block
2+
// rustfmt-trailing_comma: Never
3+
4+
fn foo() {
5+
{
6+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,
7+
diff: &Diff,
8+
heading: &str,
9+
color: &Style,
10+
show_hints: bool,
11+
hints: &[&str]|-> Option<bool> { Some(true) };}
12+
}
13+
14+
fn bar() {
15+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,diff: &Diff,heading: &str,color: &Style,| -> Option<bool> { Some(true) };
16+
let baz = |foo: bool| -> Option<bool> { Some(true) };
17+
}

tests/source/closure_visual_style.rs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// rustfmt-indent_style: Visual
2+
// rustfmt-normalize_comments: true
3+
4+
fn foo() {
5+
{
6+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,
7+
diff: &Diff,
8+
heading: &str,
9+
color: &Style,
10+
show_hints: bool,
11+
hints: &[&str]|-> Option<bool> { Some(true) };}
12+
}
13+
14+
fn bar() {
15+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,diff: &Diff,heading: &str,color: &Style,| -> Option<bool> { Some(true) };
16+
let baz = |foo: bool| -> Option<bool> { Some(true) };
17+
}
18+
19+
fn main() {
20+
let square = ( |i: i32 | i * i );
21+
22+
let commented = |// first
23+
a, // argument
24+
// second
25+
b: WithType, // argument
26+
// ignored
27+
_| {
28+
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)
29+
};
30+
31+
let commented2 = |/* first */ a /*argument*/, /* second*/ b: WithType /* argument*/, /* ignored */ _ |
32+
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);
33+
34+
let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx, ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| {
35+
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
36+
};
37+
38+
let loooooooooooooong_name = |field| {
39+
// format comments.
40+
if field.node.attrs.len() > 0 { field.node.attrs[0].span.lo()
41+
} else {
42+
field.span.lo()
43+
}};
44+
45+
let unblock_me = |trivial| {
46+
closure()
47+
};
48+
49+
let empty = |arg| {};
50+
51+
let simple = |arg| { /* comment formatting */ foo(arg) };
52+
53+
let test = | | { do_something(); do_something_else(); };
54+
55+
let arg_test = |big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame();
56+
57+
let arg_test = |big_argument_name, test123| {looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame()};
58+
59+
let simple_closure = move || -> () {};
60+
61+
let closure = |input: Ty| -> Option<String> {
62+
foo()
63+
};
64+
65+
let closure_with_return_type = |aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() };
66+
67+
|arg1, arg2, _, _, arg3, arg4| { let temp = arg4 + arg3;
68+
arg2 * arg1 - temp };
69+
70+
}

tests/target/closure.rs renamed to tests/target/closure_block_style.rs

+33-10
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
1+
// rustfmt-indent_style: Block
12
// rustfmt-normalize_comments: true
23
// Closures
34

45
fn main() {
56
let square = (|i: i32| i * i);
67

7-
let commented = |// first
8-
a, // argument
9-
// second
10-
b: WithType, // argument
11-
// ignored
12-
_| {
8+
let commented = |
9+
// first
10+
a, // argument
11+
// second
12+
b: WithType, // argument
13+
// ignored
14+
_,
15+
| {
1316
(
1417
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
1518
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
1619
)
1720
};
1821

19-
let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
20-
ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| {
21-
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
22-
};
22+
let block_body = move |
23+
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
24+
ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,
25+
| { xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy };
2326

2427
let loooooooooooooong_name = |field| {
2528
// format comments.
@@ -248,3 +251,23 @@ fn issue2262() {
248251
slave: None,
249252
})?;
250253
}
254+
255+
fn issue_3865() {
256+
{
257+
let write_status = |
258+
status: &mut Vec<ansi_term::ANSIString>,
259+
diff: &Diff,
260+
heading: &str,
261+
color: &Style,
262+
show_hints: bool,
263+
hints: &[&str],
264+
| -> Option<bool> { Some(true) };
265+
}
266+
let baz = |foo: bool| -> Option<bool> { Some(true) };
267+
let write_status = |
268+
status: &mut Vec<ansi_term::ANSIString>,
269+
diff: &Diff,
270+
heading: &str,
271+
color: &Style,
272+
| -> Option<bool> { Some(true) };
273+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// rustfmt-indent_style: Block
2+
// rustfmt-trailing_comma: Never
3+
4+
fn foo() {
5+
{
6+
let write_status = |
7+
status: &mut Vec<ansi_term::ANSIString>,
8+
diff: &Diff,
9+
heading: &str,
10+
color: &Style,
11+
show_hints: bool,
12+
hints: &[&str]
13+
| -> Option<bool> { Some(true) };
14+
}
15+
}
16+
17+
fn bar() {
18+
let write_status = |
19+
status: &mut Vec<ansi_term::ANSIString>,
20+
diff: &Diff,
21+
heading: &str,
22+
color: &Style
23+
| -> Option<bool> { Some(true) };
24+
let baz = |foo: bool| -> Option<bool> { Some(true) };
25+
}

tests/target/closure_visual_style.rs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// rustfmt-indent_style: Visual
2+
// rustfmt-normalize_comments: true
3+
4+
fn foo() {
5+
{
6+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,
7+
diff: &Diff,
8+
heading: &str,
9+
color: &Style,
10+
show_hints: bool,
11+
hints: &[&str]|
12+
-> Option<bool> { Some(true) };
13+
}
14+
}
15+
16+
fn bar() {
17+
let write_status = |status: &mut Vec<ansi_term::ANSIString>,
18+
diff: &Diff,
19+
heading: &str,
20+
color: &Style|
21+
-> Option<bool> { Some(true) };
22+
let baz = |foo: bool| -> Option<bool> { Some(true) };
23+
}
24+
25+
fn main() {
26+
let square = (|i: i32| i * i);
27+
28+
let commented = |// first
29+
a, // argument
30+
// second
31+
b: WithType, // argument
32+
// ignored
33+
_| {
34+
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb)
35+
};
36+
37+
let commented2 =
38+
|// first
39+
a, // argument
40+
// second
41+
b: WithType, // argument
42+
// ignored
43+
_| (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);
44+
45+
let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
46+
ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| {
47+
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
48+
};
49+
50+
let loooooooooooooong_name = |field| {
51+
// format comments.
52+
if field.node.attrs.len() > 0 {
53+
field.node.attrs[0].span.lo()
54+
} else {
55+
field.span.lo()
56+
}
57+
};
58+
59+
let unblock_me = |trivial| closure();
60+
61+
let empty = |arg| {};
62+
63+
let simple = |arg| {
64+
// comment formatting
65+
foo(arg)
66+
};
67+
68+
let test = || {
69+
do_something();
70+
do_something_else();
71+
};
72+
73+
let arg_test =
74+
|big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame();
75+
76+
let arg_test =
77+
|big_argument_name, test123| looooooooooooooooooong_function_naaaaaaaaaaaaaaaaame();
78+
79+
let simple_closure = move || -> () {};
80+
81+
let closure = |input: Ty| -> Option<String> { foo() };
82+
83+
let closure_with_return_type =
84+
|aaaaaaaaaaaaaaaaaaaaaaarg1, aaaaaaaaaaaaaaaaaaaaaaarg2| -> Strong { "sup".to_owned() };
85+
86+
|arg1, arg2, _, _, arg3, arg4| {
87+
let temp = arg4 + arg3;
88+
arg2 * arg1 - temp
89+
};
90+
}

tests/target/fn-param-attributes.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@ impl MutStruct {
2828
}
2929

3030
fn main() {
31-
let c = |#[allow(C)] a: u32,
32-
#[cfg(something)] b: i32,
33-
#[cfg_attr(something, cfg(nothing))]
34-
#[deny(C)]
35-
c: i32| {};
31+
let c = |
32+
#[allow(C)] a: u32,
33+
#[cfg(something)] b: i32,
34+
#[cfg_attr(something, cfg(nothing))]
35+
#[deny(C)]
36+
c: i32,
37+
| {};
3638
let _ = c(1, 2);
3739
}
3840

tests/target/mulit-file.rs renamed to tests/target/multi-file.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
// crash.
33

44
#[cfg(all(foo))]
5-
#[path = "closure.rs"]
5+
#[path = "closure_block_style.rs"]
66
pub mod imp;
77

88
#[cfg(all(bar))]
9-
#[path = "closure.rs"]
9+
#[path = "closure_block_style.rs"]
1010
pub mod imp;

0 commit comments

Comments
 (0)