Skip to content

Commit e9acbb5

Browse files
refactor: more control over chain item indents
1 parent c850ac7 commit e9acbb5

5 files changed

+682
-66
lines changed

src/chains.rs

Lines changed: 122 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -650,8 +650,12 @@ impl<'a> ChainFormatterShared<'a> {
650650
child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?
651651
};
652652

653-
let (format_last, is_long) = format_chain_item(last, context, last_shape)?;
654-
self.has_long_tail = is_long;
653+
let FormattedChainItem {
654+
rewrite: format_last,
655+
exceeds_max_width,
656+
..
657+
} = format_chain_item(last, context, last_shape);
658+
self.has_long_tail = exceeds_max_width;
655659
let last_rewrite = last_subexpr_str.unwrap_or(format_last);
656660
self.rewrites.push(last_rewrite);
657661
Some(())
@@ -695,22 +699,30 @@ impl<'a> ChainFormatterShared<'a> {
695699
struct ChainFormatterBlock<'a> {
696700
shared: ChainFormatterShared<'a>,
697701
root_ends_with_block: bool,
702+
parent_body_forced_indent: bool,
698703
}
699704

700705
impl<'a> ChainFormatterBlock<'a> {
701706
fn new(chain: &'a Chain) -> ChainFormatterBlock<'a> {
702707
ChainFormatterBlock {
703708
shared: ChainFormatterShared::new(chain),
704709
root_ends_with_block: false,
710+
parent_body_forced_indent: false,
705711
}
706712
}
707713
}
708714

715+
struct FormattedChainItem {
716+
rewrite: String,
717+
exceeds_max_width: bool,
718+
forced_indent: bool,
719+
}
720+
709721
fn format_chain_item(
710722
item: &ChainItem,
711723
context: &RewriteContext<'_>,
712724
shape: Shape,
713-
) -> Option<(String, bool)> {
725+
) -> FormattedChainItem {
714726
fn contains_multiline_args(
715727
exprs: &Vec<ptr::P<ast::Expr>>,
716728
context: &RewriteContext<'_>,
@@ -781,7 +793,13 @@ fn format_chain_item(
781793
.sub_width(shape.rhs_overhead(context.config))
782794
{
783795
Some(shape) => shape,
784-
None => return Some((context.snippet(item.span).to_owned(), false)),
796+
None => {
797+
return FormattedChainItem {
798+
rewrite: context.snippet(item.span).to_owned(),
799+
exceeds_max_width: false,
800+
forced_indent: false,
801+
};
802+
}
785803
};
786804
let next_line_result = item.rewrite(context, new_shape);
787805
let parent_indent_style = context.config.chains_block_parent_indent_parent_item();
@@ -790,58 +808,75 @@ fn format_chain_item(
790808
if !orig_result.contains('\n')
791809
&& utils::unicode_str_width(&orig_result) <= shape.width =>
792810
{
793-
Some((orig_result, false))
811+
FormattedChainItem {
812+
rewrite: orig_result,
813+
exceeds_max_width: false,
814+
forced_indent: false,
815+
}
794816
}
795817
(Some(orig_result), Some(next_line_result)) => match item.kind {
796818
ChainItemKind::Parent(ref expr) => match parent_indent_style {
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-
)),
819+
ChainsBlockParentElementIndent::Never => FormattedChainItem {
820+
rewrite: orig_result.clone(),
821+
exceeds_max_width: false,
822+
forced_indent: false,
823+
},
824+
ChainsBlockParentElementIndent::Always => FormattedChainItem {
825+
rewrite: next_line_result.clone(),
826+
exceeds_max_width: false,
827+
forced_indent: true,
828+
},
805829
ChainsBlockParentElementIndent::OnlySimpleCalls => {
806830
match is_simple_call_like(&expr.kind, &context, shape) {
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-
)),
831+
true => FormattedChainItem {
832+
rewrite: next_line_result.clone(),
833+
exceeds_max_width: false,
834+
forced_indent: true,
835+
},
836+
false => FormattedChainItem {
837+
rewrite: orig_result.clone(),
838+
exceeds_max_width: false,
839+
forced_indent: false,
840+
},
816841
}
817842
}
818843
ChainsBlockParentElementIndent::OnlyTupleLitsAndSimpleCalls => {
819844
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-
)),
845+
true => FormattedChainItem {
846+
rewrite: next_line_result.clone(),
847+
exceeds_max_width: false,
848+
forced_indent: true,
849+
},
850+
false => FormattedChainItem {
851+
rewrite: orig_result.clone(),
852+
exceeds_max_width: false,
853+
forced_indent: false,
854+
},
829855
}
830856
}
831857
},
832-
_ => Some((
833-
orig_result.clone(),
834-
wrap_str(orig_result, context.config.max_width(), shape).is_none(),
835-
)),
858+
_ => FormattedChainItem {
859+
rewrite: orig_result.clone(),
860+
exceeds_max_width: wrap_str(orig_result, context.config.max_width(), shape)
861+
.is_none(),
862+
forced_indent: false,
863+
},
864+
},
865+
(None, None) => FormattedChainItem {
866+
rewrite: context.snippet(item.span).to_owned(),
867+
exceeds_max_width: true,
868+
forced_indent: false,
869+
},
870+
(Some(orig_result), _) => FormattedChainItem {
871+
rewrite: orig_result.clone(),
872+
exceeds_max_width: false,
873+
forced_indent: false,
874+
},
875+
(None, Some(next_line_result)) => FormattedChainItem {
876+
rewrite: next_line_result.clone(),
877+
exceeds_max_width: false,
878+
forced_indent: true,
836879
},
837-
(None, None) => Some((context.snippet(item.span).to_owned(), true)),
838-
(Some(orig_result), _) => Some((
839-
orig_result.clone(),
840-
wrap_str(orig_result, context.config.max_width(), shape).is_none(),
841-
)),
842-
// This will only occur when the chain is part of the rhs and
843-
// will fit with an indent on the next line
844-
(None, Some(_)) => None,
845880
}
846881
}
847882

@@ -852,8 +887,13 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
852887
context: &RewriteContext<'_>,
853888
shape: Shape,
854889
) -> Option<()> {
855-
let (mut root_rewrite, long_parent) = format_chain_item(parent, context, shape)?;
856-
self.shared.has_long_inner_item = long_parent;
890+
let FormattedChainItem {
891+
rewrite: mut root_rewrite,
892+
exceeds_max_width,
893+
forced_indent,
894+
} = format_chain_item(parent, context, shape);
895+
self.shared.has_long_inner_item = exceeds_max_width;
896+
self.parent_body_forced_indent = forced_indent;
857897

858898
let mut root_ends_with_block = parent.kind.is_block_like(context, &root_rewrite);
859899
let tab_width = context.config.tab_spaces().saturating_sub(shape.offset);
@@ -886,7 +926,10 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
886926
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
887927
let always_indent_children = context.config.chains_block_parent_indent_children();
888928
Some(
889-
if !self.root_ends_with_block || always_indent_children {
929+
if !self.root_ends_with_block
930+
|| always_indent_children
931+
|| self.parent_body_forced_indent
932+
{
890933
shape.block_indent(context.config.tab_spaces())
891934
} else {
892935
shape.block_indent(0)
@@ -897,8 +940,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
897940

898941
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
899942
for item in &self.shared.children[..self.shared.children.len() - 1] {
900-
let (rewrite, is_long) = format_chain_item(&item, &context, child_shape)?;
901-
if is_long {
943+
let FormattedChainItem {
944+
rewrite,
945+
exceeds_max_width,
946+
..
947+
} = format_chain_item(&item, &context, child_shape);
948+
if exceeds_max_width {
902949
self.shared.has_long_inner_item = true;
903950
}
904951
self.shared.rewrites.push(rewrite);
@@ -920,9 +967,14 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
920967
&self,
921968
context: &RewriteContext<'_>,
922969
child_shape: Shape,
923-
_shape: Shape,
970+
shape: Shape,
924971
) -> Option<String> {
925-
self.shared.join_rewrites(context, child_shape)
972+
match self.shared.join_rewrites(context, child_shape) {
973+
Some(rewrite) if self.shared.has_long_item() => Some(rewrite),
974+
Some(rewrite) => wrap_str(rewrite, context.config.max_width(), shape),
975+
None => None,
976+
}
977+
// self.shared.join_rewrites(context, child_shape)
926978
}
927979

928980
fn pure_root(&mut self) -> Option<String> {
@@ -956,8 +1008,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
9561008
shape: Shape,
9571009
) -> Option<()> {
9581010
let parent_shape = shape.visual_indent(0);
959-
let (mut root_rewrite, parent_too_long) = format_chain_item(parent, context, parent_shape)?;
960-
self.shared.has_long_parent = parent_too_long;
1011+
let FormattedChainItem {
1012+
rewrite: mut root_rewrite,
1013+
exceeds_max_width: long_parent,
1014+
..
1015+
} = format_chain_item(parent, context, parent_shape);
1016+
self.shared.has_long_parent = long_parent;
9611017
let multiline = root_rewrite.contains('\n');
9621018
self.offset = if multiline {
9631019
last_line_width(&root_rewrite).saturating_sub(shape.used_width())
@@ -981,16 +1037,21 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
9811037
child_shape
9821038
};
9831039

984-
let (rewrite, first_child_too_long) = format_chain_item(item, context, child_shape)?;
1040+
let FormattedChainItem {
1041+
rewrite,
1042+
exceeds_max_width: first_child_too_long,
1043+
..
1044+
} = format_chain_item(item, context, child_shape);
9851045
self.has_long_first_child = first_child_too_long;
9861046

9871047
match wrap_str(rewrite, context.config.max_width(), shape) {
9881048
Some(rewrite) => root_rewrite.push_str(&rewrite),
9891049
None => {
9901050
// We couldn't fit in at the visual indent, try the last
9911051
// indent.
992-
let (rewrite, too_long) = format_chain_item(item, context, parent_shape)?;
993-
if too_long
1052+
let FormattedChainItem { rewrite, .. } =
1053+
format_chain_item(item, context, parent_shape);
1054+
if self.shared.has_long_parent
9941055
|| wrap_str(rewrite.clone(), context.config.max_width(), parent_shape)
9951056
.is_none()
9961057
{
@@ -1022,8 +1083,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
10221083

10231084
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
10241085
for item in &self.shared.children[..self.shared.children.len() - 1] {
1025-
let (rewrite, is_long) = format_chain_item(&item, &context, child_shape)?;
1026-
if is_long {
1086+
let FormattedChainItem {
1087+
rewrite,
1088+
exceeds_max_width,
1089+
..
1090+
} = format_chain_item(&item, &context, child_shape);
1091+
if exceeds_max_width {
10271092
self.shared.has_long_inner_item = true;
10281093
}
10291094
self.shared.rewrites.push(rewrite);

0 commit comments

Comments
 (0)