Skip to content

Commit 065dbaf

Browse files
refactor: support tuple lit chain parent indent
1 parent 0a8b110 commit 065dbaf

13 files changed

+308
-22
lines changed

Configurations.md

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -428,30 +428,118 @@ fn example() {
428428
Determines whether block-like chain parents are indented
429429

430430
- **Default value**: `"Never"`
431-
- **Possible values**: `"Always"`, `"Never"`, `"OnlySimpleCalls"`
431+
- **Possible values**: `"Always"`, `"Never"`, `"OnlySimpleCalls"`, `"OnlyTupleLitsAndSimpleCalls"`
432432
- **Stable**: No (tracking issue: ...)
433433

434434
#### `"Never"` (default):
435+
The body of block-like parent chain elements are never indented.
435436

436437
```rust
437438
#![rustfmt::skip]
438-
439439
fn example() {
440+
let all = very_very_very_very_very_long_fun_name(
441+
very_very_very_very_very_very_very_very_very_long_var_name,
442+
)
443+
.iter()
444+
.map(|x| x + very_very_very_very_very_very_long_var_name);
445+
440446
StructA {
441447
test_test: some_value,
442448
}
443-
.foo()
449+
.do_stuff(StructB {
450+
test_test_b: other_value,
451+
})
452+
.aaa_aaa()
453+
.do_stuff(
454+
StructB {
455+
test_test_b: other_value,
456+
}
457+
.ddd_ddd()
458+
.eee_eee(),
459+
)
460+
.bbb_bbb()
461+
.ccc_ccc();
462+
463+
foo(|x| {
464+
// ....
465+
})
466+
.bar()
467+
.baz()
468+
.unwrap();
469+
}
470+
```
471+
472+
#### `"Always"`:
473+
The body of block-like parent chain elements are always indented.
474+
475+
```rust
476+
#![rustfmt::skip]
477+
// chains_block_parent_indent_children: true
478+
479+
fn example() {
480+
let all = very_very_very_very_very_long_fun_name(
481+
very_very_very_very_very_very_very_very_very_long_var_name,
482+
)
483+
.iter()
484+
.map(|x| x + very_very_very_very_very_very_long_var_name);
485+
486+
StructA {
487+
test_test: some_value,
488+
}
489+
.do_stuff(StructB {
490+
test_test_b: other_value,
491+
})
492+
.aaa_aaa()
493+
.do_stuff(
494+
StructB {
495+
test_test_b: other_value,
496+
}
497+
.ddd_ddd()
498+
.eee_eee(),
499+
)
500+
.bbb_bbb()
501+
.ccc_ccc();
502+
503+
foo(|x| {
504+
// ....
505+
})
444506
.bar()
445507
.baz()
446-
.qux();
508+
.unwrap();
509+
}
510+
```
447511

448-
let very_very_very_very_very_very_very_very_very_long_var_name = 13;
512+
#### `"OnlySimpleCalls"`:
513+
The body of block-like parent chain elements are only indented when the parent is a simple call-like chain item, such as a method call with no multiline block like arguments (like a closure).
514+
515+
```rust
516+
#![rustfmt::skip]
517+
// chains_block_parent_indent_children: true
518+
519+
fn example() {
449520
let all = very_very_very_very_very_long_fun_name(
450-
very_very_very_very_very_very_very_very_very_long_var_name,
451-
)
521+
very_very_very_very_very_very_very_very_very_long_var_name,
522+
)
452523
.iter()
453524
.map(|x| x + very_very_very_very_very_very_long_var_name);
454525

526+
StructA {
527+
test_test: some_value,
528+
}
529+
.do_stuff(StructB {
530+
test_test_b: other_value,
531+
})
532+
.aaa_aaa()
533+
.do_stuff(
534+
StructB {
535+
test_test_b: other_value,
536+
}
537+
.ddd_ddd()
538+
.eee_eee(),
539+
)
540+
.bbb_bbb()
541+
.ccc_ccc();
542+
455543
foo(|x| {
456544
// ....
457545
})
@@ -461,19 +549,43 @@ fn example() {
461549
}
462550
```
463551

464-
#### `"Always"`:
552+
#### `"OnlyTupleLitsAndSimpleCalls"`:
553+
The body of block-like parent chain elements are only indented when the parent is a tuple literal, or a simple call-like chain item, such as a method call with no multiline block like arguments (like a closure).
465554

466555
```rust
467556
#![rustfmt::skip]
557+
// chains_block_parent_indent_children: true
468558

469559
fn example() {
560+
let all = very_very_very_very_very_long_fun_name(
561+
very_very_very_very_very_very_very_very_very_long_var_name,
562+
)
563+
.iter()
564+
.map(|x| x + very_very_very_very_very_very_long_var_name);
565+
470566
StructA {
471567
test_test: some_value,
472568
}
473-
.foo()
569+
.do_stuff(StructB {
570+
test_test_b: other_value,
571+
})
572+
.aaa_aaa()
573+
.do_stuff(
574+
StructB {
575+
test_test_b: other_value,
576+
}
577+
.ddd_ddd()
578+
.eee_eee(),
579+
)
580+
.bbb_bbb()
581+
.ccc_ccc();
582+
583+
foo(|x| {
584+
// ....
585+
})
474586
.bar()
475587
.baz()
476-
.qux();
588+
.unwrap();
477589
}
478590
```
479591

src/chains.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,17 @@ fn format_chain_item(
765765
}
766766
}
767767

768+
fn is_tup_lit_or_simple_call_like(
769+
parent_expr_kind: &ast::ExprKind,
770+
context: &RewriteContext<'_>,
771+
shape: Shape,
772+
) -> bool {
773+
match parent_expr_kind {
774+
ast::ExprKind::Struct(..) => true,
775+
_ => is_simple_call_like(parent_expr_kind, context, shape),
776+
}
777+
}
778+
768779
let orig_result = item.rewrite(context, shape);
769780
let new_shape = match Shape::indented(shape.indent.block_indent(context.config), context.config)
770781
.sub_width(shape.rhs_overhead(context.config))
@@ -783,12 +794,38 @@ fn format_chain_item(
783794
}
784795
(Some(orig_result), Some(next_line_result)) => match item.kind {
785796
ChainItemKind::Parent(ref expr) => match parent_indent_style {
786-
ChainsBlockParentElementIndent::Never => Some((orig_result, false)),
787-
ChainsBlockParentElementIndent::Always => Some((next_line_result, false)),
797+
ChainsBlockParentElementIndent::Never => Some((
798+
orig_result.clone(),
799+
wrap_str(orig_result, context.config.max_width(), shape).is_none(),
800+
)),
801+
ChainsBlockParentElementIndent::Always => Some((
802+
next_line_result.clone(),
803+
wrap_str(next_line_result, context.config.max_width(), new_shape).is_none(),
804+
)),
788805
ChainsBlockParentElementIndent::OnlySimpleCalls => {
789806
match is_simple_call_like(&expr.kind, &context, shape) {
790-
true => Some((next_line_result, false)),
791-
false => Some((orig_result, false)),
807+
true => Some((
808+
next_line_result.clone(),
809+
wrap_str(next_line_result, context.config.max_width(), new_shape)
810+
.is_none(),
811+
)),
812+
false => Some((
813+
orig_result.clone(),
814+
wrap_str(orig_result, context.config.max_width(), shape).is_none(),
815+
)),
816+
}
817+
}
818+
ChainsBlockParentElementIndent::OnlyTupleLitsAndSimpleCalls => {
819+
match is_tup_lit_or_simple_call_like(&expr.kind, &context, shape) {
820+
true => Some((
821+
next_line_result.clone(),
822+
wrap_str(next_line_result, context.config.max_width(), new_shape)
823+
.is_none(),
824+
)),
825+
false => Some((
826+
orig_result.clone(),
827+
wrap_str(orig_result, context.config.max_width(), shape).is_none(),
828+
)),
792829
}
793830
}
794831
},
@@ -798,7 +835,10 @@ fn format_chain_item(
798835
)),
799836
},
800837
(None, None) => Some((context.snippet(item.span).to_owned(), true)),
801-
(Some(orig_result), _) => Some((orig_result, false)),
838+
(Some(orig_result), _) => Some((
839+
orig_result.clone(),
840+
wrap_str(orig_result, context.config.max_width(), shape).is_none(),
841+
)),
802842
// This will only occur when the chain is part of the rhs and
803843
// will fit with an indent on the next line
804844
(None, Some(_)) => None,

src/config/options.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,13 @@ pub enum ChainsBlockParentElementIndent {
178178
/// Always indent the contents of a block-like parent element.
179179
Always,
180180
/// Only indent the contents of a block-like parent element if
181-
/// it is call-like, such as a function call that does not include
181+
/// it is a simple call-like, such as a function call that does not include
182182
/// any block-like arguments.
183183
OnlySimpleCalls,
184+
/// Only indent the contents of a block-like parent element if
185+
/// it is a tuple lit or a simple call-like, such as a function call that does not include
186+
/// any block-like arguments.
187+
OnlyTupleLitsAndSimpleCalls,
184188
}
185189

186190
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]

tests/source/chains_long_items_block.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,25 @@ fn long_tail() {
5454
bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff();
5555

5656
let foo = bar().xxxxxxx.map(|x| x + 5).map(|x| x / 2).fold(0, |acc, x| acc + x).doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff();
57+
}
5758

59+
fn raw_str_lit() {
60+
fpo.foo().bar.baz.quz.adfasdfasdfasdfasdfasdfasdfasffffffffffffffffffffffffffffffffffdfasf(r#"
61+
if foo {
62+
a();
63+
}
64+
else {
65+
b();
66+
}
67+
"#.trim());
68+
69+
70+
fpo.foo().bar.baz.quz.a999999999999999999999999999999999999999999999999999999999999999(r#"
71+
if foo {
72+
a();
73+
}
74+
else {
75+
b();
76+
}
77+
"#.trim().foo().bar.baz.qux().unwrap());
5878
}

tests/source/chains_multiline_parent_always.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ fn main() {
2929
})
3030
.bar()
3131
.baz()
32-
.unwrap()
32+
.unwrap();
3333
}

tests/source/chains_multiline_parent_never.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ fn main() {
2828
})
2929
.bar()
3030
.baz()
31-
.unwrap()
31+
.unwrap();
3232
}

tests/source/chains_multiline_parent_simple_calls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ fn main() {
2929
})
3030
.bar()
3131
.baz()
32-
.unwrap()
32+
.unwrap();
3333
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// rustfmt-chains_block_parent_indent_children: true
2+
// rustfmt-chains_block_parent_indent_parent_item: OnlyTupleLitsAndSimpleCalls
3+
4+
fn main() {
5+
let very_very_very_very_very_very_very_very_very_long_var_name = 13;
6+
let all = very_very_very_very_very_long_fun_name(
7+
very_very_very_very_very_very_very_very_very_long_var_name,
8+
)
9+
.iter()
10+
.map(|x| x + very_very_very_very_very_very_long_var_name);
11+
StructA {
12+
test_test: some_value,
13+
}
14+
.do_stuff(StructB {
15+
test_test_b: other_value,
16+
})
17+
.aaa_aaa()
18+
.do_stuff(StructB {
19+
test_test_b: other_value,
20+
}.ddd_ddd().eee_eee())
21+
.bbb_bbb()
22+
.ccc_ccc();
23+
let more = 13;
24+
let other = vec![1, 2, 3].iter()
25+
.map(|x| x + very_very_very_very_very_very_long_var_name);
26+
27+
foo(|x| {
28+
// ....
29+
})
30+
.bar()
31+
.baz()
32+
.unwrap();
33+
}

tests/target/chains_long_items_block.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,42 @@ fn long_tail() {
143143
.doooooooooooooooooooooooooooooooooooooooooooooooooooooo_stufffffffffffffffffffffffffffffffffffffff(
144144
);
145145
}
146+
147+
fn raw_str_lit() {
148+
fpo.foo()
149+
.bar
150+
.baz
151+
.quz
152+
.adfasdfasdfasdfasdfasdfasdfasffffffffffffffffffffffffffffffffffdfasf(
153+
r#"
154+
if foo {
155+
a();
156+
}
157+
else {
158+
b();
159+
}
160+
"#
161+
.trim(),
162+
);
163+
164+
fpo.foo()
165+
.bar
166+
.baz
167+
.quz
168+
.a999999999999999999999999999999999999999999999999999999999999999(
169+
r#"
170+
if foo {
171+
a();
172+
}
173+
else {
174+
b();
175+
}
176+
"#
177+
.trim()
178+
.foo()
179+
.bar
180+
.baz
181+
.qux()
182+
.unwrap(),
183+
);
184+
}

tests/target/chains_multiline_parent_always.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ fn main() {
3434
})
3535
.bar()
3636
.baz()
37-
.unwrap()
37+
.unwrap();
3838
}

0 commit comments

Comments
 (0)