Skip to content

Commit 05641ad

Browse files
committed
Add fn_call_layout configuration option
Closes 5218 The `fn_call_layout` was added to give users more control over how function calls are formatted. This change will only impact function calls, and will not have any affect on method calls. The values are identical to those for `fn_args_layout`, which is a stable option that controls how function declarations are laid out.
1 parent c65ba14 commit 05641ad

File tree

16 files changed

+544
-2
lines changed

16 files changed

+544
-2
lines changed

Configurations.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,75 @@ trait Lorem {
753753
}
754754
```
755755

756+
## `fn_call_layout`
757+
758+
Control the layout of arguments in function calls
759+
760+
- **Default value**: `"Tall"`
761+
- **Possible values**: `"Compressed"`, `"Tall"`, `"Vertical"`
762+
- **Stable**: No (tracking issue: N/A)
763+
764+
#### `"Tall"` (default):
765+
766+
```rust
767+
fn main() {
768+
lorem(ipsum, dolor, sit, amet);
769+
ipsum(
770+
dolor,
771+
sit,
772+
amet,
773+
consectetur,
774+
adipiscing,
775+
elit,
776+
vivamus,
777+
ipsum,
778+
orci,
779+
rhoncus,
780+
vel,
781+
imperdiet,
782+
);
783+
}
784+
```
785+
786+
#### `"Compressed"`:
787+
788+
```rust
789+
fn main() {
790+
lorem(ipsum, dolor, sit, amet);
791+
ipsum(
792+
dolor, sit, amet, consectetur, adipiscing, elit, vivamus, ipsum, orci, rhoncus, vel,
793+
imperdiet,
794+
);
795+
}
796+
```
797+
798+
#### `"Vertical"`:
799+
800+
```rust
801+
fn main() {
802+
lorem(
803+
ipsum,
804+
dolor,
805+
sit,
806+
amet,
807+
);
808+
ipsum(
809+
dolor,
810+
sit,
811+
amet,
812+
consectetur,
813+
adipiscing,
814+
elit,
815+
vivamus,
816+
ipsum,
817+
orci,
818+
rhoncus,
819+
vel,
820+
imperdiet,
821+
);
822+
}
823+
```
824+
756825
## `fn_call_width`
757826

758827
Maximum width of the args of a function call before falling back to vertical formatting.

src/attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ impl Rewrite for ast::MetaItem {
309309
} else {
310310
SeparatorTactic::Never
311311
}),
312+
None,
312313
)?
313314
}
314315
ast::MetaItemKind::NameValue(ref literal) => {

src/chains.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ impl ChainItem {
253253
format!("::<{}>", type_list.join(", "))
254254
};
255255
let callee_str = format!(".{}{}", rewrite_ident(context, method_name), type_str);
256-
rewrite_call(context, &callee_str, &args[1..], span, shape)
256+
rewrite_call(context, &callee_str, &args[1..], None, span, shape)
257257
}
258258
}
259259

src/config/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ create_config! {
122122
"Force multiline closure bodies and match arms to be wrapped in a block";
123123
fn_args_layout: Density, Density::Tall, true,
124124
"Control the layout of arguments in a function";
125+
fn_call_layout: Density, Density::Tall, false,
126+
"Control the layout of arguments in a function call";
125127
brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items";
126128
control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false,
127129
"Brace style for control flow constructs";
@@ -601,6 +603,7 @@ match_arm_blocks = true
601603
match_arm_leading_pipes = "Never"
602604
force_multiline_blocks = false
603605
fn_args_layout = "Tall"
606+
fn_call_layout = "Tall"
604607
brace_style = "SameLineWhere"
605608
control_brace_style = "AlwaysSameLine"
606609
trailing_semicolon = true

src/expr.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,19 @@ fn format_expr_inner(
138138
ast::ExprKind::Call(ref callee, ref args) => {
139139
let inner_span = mk_sp(callee.span.hi(), expr.span.hi());
140140
let callee_str = callee.rewrite(context, shape)?;
141-
rewrite_call(context, &callee_str, args, inner_span, shape)
141+
let force_list_tactic = if context.config.was_set().fn_call_layout() {
142+
Some(context.config.fn_call_layout().to_list_tactic(args.len()))
143+
} else {
144+
None
145+
};
146+
rewrite_call(
147+
context,
148+
&callee_str,
149+
args,
150+
force_list_tactic,
151+
inner_span,
152+
shape,
153+
)
142154
}
143155
ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span),
144156
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
@@ -1309,6 +1321,7 @@ pub(crate) fn rewrite_call(
13091321
context: &RewriteContext<'_>,
13101322
callee: &str,
13111323
args: &[ptr::P<ast::Expr>],
1324+
force_list_tactic: Option<ListTactic>,
13121325
span: Span,
13131326
shape: Shape,
13141327
) -> Option<String> {
@@ -1320,6 +1333,7 @@ pub(crate) fn rewrite_call(
13201333
span,
13211334
context.config.fn_call_width(),
13221335
choose_separator_tactic(context, span),
1336+
force_list_tactic,
13231337
)
13241338
}
13251339

@@ -1857,6 +1871,7 @@ pub(crate) fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>(
18571871
span,
18581872
context.config.fn_call_width(),
18591873
force_tactic,
1874+
None,
18601875
)
18611876
} else {
18621877
rewrite_tuple_in_visual_indent_style(context, items, span, shape, is_singleton_tuple)

src/items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,7 @@ fn format_tuple_struct(
14851485
mk_sp(lo, span.hi()),
14861486
context.config.fn_call_width(),
14871487
None,
1488+
None,
14881489
)?;
14891490
}
14901491

src/macros.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ fn rewrite_macro_inner(
279279
} else {
280280
Some(SeparatorTactic::Never)
281281
},
282+
None,
282283
)
283284
.map(|rw| match position {
284285
MacroPosition::Item => format!("{};", rw),

src/overflow.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>(
252252
span: Span,
253253
item_max_width: usize,
254254
force_separator_tactic: Option<SeparatorTactic>,
255+
force_list_tactic: Option<ListTactic>,
255256
) -> Option<String> {
256257
Context::new(
257258
context,
@@ -263,6 +264,7 @@ pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>(
263264
")",
264265
item_max_width,
265266
force_separator_tactic,
267+
force_list_tactic,
266268
None,
267269
)
268270
.rewrite(shape)
@@ -286,6 +288,7 @@ pub(crate) fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>(
286288
context.config.max_width(),
287289
None,
288290
None,
291+
None,
289292
)
290293
.rewrite(shape)
291294
}
@@ -314,6 +317,7 @@ pub(crate) fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>>
314317
rhs,
315318
context.config.array_width(),
316319
force_separator_tactic,
320+
None,
317321
Some(("[", "]")),
318322
)
319323
.rewrite(shape)
@@ -331,6 +335,7 @@ struct Context<'a> {
331335
item_max_width: usize,
332336
one_line_width: usize,
333337
force_separator_tactic: Option<SeparatorTactic>,
338+
force_list_tactic: Option<ListTactic>,
334339
custom_delims: Option<(&'a str, &'a str)>,
335340
}
336341

@@ -345,6 +350,7 @@ impl<'a> Context<'a> {
345350
suffix: &'static str,
346351
item_max_width: usize,
347352
force_separator_tactic: Option<SeparatorTactic>,
353+
force_list_tactic: Option<ListTactic>,
348354
custom_delims: Option<(&'a str, &'a str)>,
349355
) -> Context<'a> {
350356
let used_width = extra_offset(ident, shape);
@@ -369,6 +375,7 @@ impl<'a> Context<'a> {
369375
item_max_width,
370376
one_line_width,
371377
force_separator_tactic,
378+
force_list_tactic,
372379
custom_delims,
373380
}
374381
}
@@ -584,6 +591,25 @@ impl<'a> Context<'a> {
584591
_ => (),
585592
}
586593

594+
match self.force_list_tactic {
595+
Some(list_tactic) if list_tactic == ListTactic::Mixed => {
596+
if tactic != DefinitiveListTactic::Horizontal {
597+
tactic = DefinitiveListTactic::Mixed
598+
}
599+
}
600+
// If we need to force a tactic (like Vertical), we should only do it if there are
601+
// at least 2 items for us to format. Otherwise, use the tactic already determined.
602+
Some(list_tactic) if self.items.len() > 1 => {
603+
tactic = definitive_tactic(
604+
&*list_items,
605+
list_tactic,
606+
Separator::Comma,
607+
self.one_line_width,
608+
)
609+
}
610+
_ => {}
611+
};
612+
587613
tactic
588614
}
589615

src/patterns.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ fn rewrite_tuple_pat(
494494
} else {
495495
None
496496
},
497+
None,
497498
)
498499
}
499500

src/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ impl Rewrite for ast::Ty {
844844
context,
845845
"typeof",
846846
&[anon_const.value.clone()],
847+
None,
847848
self.span,
848849
shape,
849850
),
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// rustfmt-fn_call_layout:Compressed
2+
// rustfmt-version:Two
3+
4+
fn main() {
5+
lorem(ipsum, dolor, sit, amet);
6+
lorem(ipsum, // some inine comment
7+
dolor, sit, amet);
8+
lorem(ipsum, /* some inine comment */
9+
dolor, sit, amet);
10+
ipsum(dolor, sit, amet, consectetur, adipiscing, elit, vivamus, ipsum, orci, rhoncus, vel, imperdiet);
11+
12+
// issue 2010
13+
let a = i8x32::new(
14+
0, 1, -1, 2,
15+
-2, 3, -3, 4,
16+
-4, 5, -5, std::i8::MAX,
17+
std::i8::MIN + 1, 100, -100, -32,
18+
0, 1, -1, 2,
19+
-2, 3, -3, 4,
20+
-4, 5, -5, std::i8::MAX,
21+
std::i8::MIN + 1, 100, -100, -32);
22+
23+
// issue 4146
24+
return_monitor_err(
25+
e,
26+
channel_state,
27+
chan,
28+
order,
29+
commitment_update.is_some(),
30+
revoke_and_ack.is_some(),
31+
);
32+
33+
34+
// other examples with more complex args
35+
more_complex_args(
36+
|a, b, c| {if a == 998765390 {- b * 3 } else {c} },
37+
std::ops::Range { start: 3, end: 5 },
38+
std::i8::MAX, String::from(" hello world!!").as_bytes(),
39+
thread::Builder::new()
40+
.name("thread1".to_string())
41+
.spawn(move || {
42+
use std::sync::Arc;
43+
44+
let mut values = Arc::<[u32]>::new_uninit_slice(3);
45+
46+
// Deferred initialization:
47+
let data = Arc::get_mut(&mut values).unwrap();
48+
data[0].write(1);
49+
data[1].write(2);
50+
data[2].write(3);
51+
52+
let values = unsafe { values.assume_init() };
53+
}), "another argument"
54+
)
55+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// rustfmt-fn_call_layout:Tall
2+
// rustfmt-version:Two
3+
4+
fn main() {
5+
lorem(ipsum, dolor, sit, amet);
6+
lorem(ipsum, // some inine comment
7+
dolor, sit, amet);
8+
lorem(ipsum, /* some inine comment */
9+
dolor, sit, amet);
10+
ipsum(dolor, sit, amet, consectetur, adipiscing, elit, vivamus, ipsum, orci, rhoncus, vel, imperdiet);
11+
12+
// issue 2010
13+
let a = i8x32::new(
14+
0, 1, -1, 2,
15+
-2, 3, -3, 4,
16+
-4, 5, -5, std::i8::MAX,
17+
std::i8::MIN + 1, 100, -100, -32,
18+
0, 1, -1, 2,
19+
-2, 3, -3, 4,
20+
-4, 5, -5, std::i8::MAX,
21+
std::i8::MIN + 1, 100, -100, -32);
22+
23+
// issue 4146
24+
return_monitor_err(
25+
e,
26+
channel_state,
27+
chan,
28+
order,
29+
commitment_update.is_some(),
30+
revoke_and_ack.is_some(),
31+
);
32+
33+
34+
// other examples with more complex args
35+
more_complex_args(
36+
|a, b, c| {if a == 998765390 {- b * 3 } else {c} },
37+
std::ops::Range { start: 3, end: 5 },
38+
std::i8::MAX, String::from(" hello world!!").as_bytes(),
39+
thread::Builder::new()
40+
.name("thread1".to_string())
41+
.spawn(move || {
42+
use std::sync::Arc;
43+
44+
let mut values = Arc::<[u32]>::new_uninit_slice(3);
45+
46+
// Deferred initialization:
47+
let data = Arc::get_mut(&mut values).unwrap();
48+
data[0].write(1);
49+
data[1].write(2);
50+
data[2].write(3);
51+
52+
let values = unsafe { values.assume_init() };
53+
}), "another argument"
54+
)
55+
}

0 commit comments

Comments
 (0)