Skip to content

Commit bf37e12

Browse files
fix: indenting chain elements with long parent
1 parent 6a3203e commit bf37e12

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

src/chains.rs

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -713,20 +713,69 @@ impl<'a> ChainFormatterBlock<'a> {
713713
}
714714
}
715715

716+
fn format_chain_item(
717+
item: &ChainItem,
718+
context: &RewriteContext<'_>,
719+
shape: Shape,
720+
) -> (String, bool) {
721+
let orig_result = item.rewrite(context, shape);
722+
let new_shape = match Shape::indented(shape.indent.block_indent(context.config), context.config)
723+
.sub_width(shape.rhs_overhead(context.config))
724+
{
725+
Some(shape) => shape,
726+
None => return (context.snippet(item.span).to_owned(), false),
727+
};
728+
let next_line_result = item.rewrite(context, new_shape);
729+
match (orig_result, next_line_result) {
730+
(Some(orig_result), _)
731+
if !orig_result.contains('\n')
732+
&& utils::unicode_str_width(&orig_result) <= shape.width =>
733+
{
734+
(orig_result, false)
735+
}
736+
(Some(orig_result), Some(next_line_result)) => match item.kind {
737+
ChainItemKind::Parent(ref expr) if next_line_result.contains('\n') => match expr.kind {
738+
ast::ExprKind::MethodCall(_, ref exprs) | ast::ExprKind::Call(_, ref exprs) => {
739+
let contains_non_indentable_args = exprs.iter().any(|e| match e.kind {
740+
ast::ExprKind::Closure(..)
741+
| ast::ExprKind::Lit(..)
742+
| ast::ExprKind::Struct(..) => true,
743+
ast::ExprKind::AddrOf(_, ref expr) => match expr.kind {
744+
ast::ExprKind::Struct(..) => true,
745+
_ => false,
746+
},
747+
_ => false,
748+
});
749+
if context.config.allow_chain_call_overflow() {
750+
if !contains_non_indentable_args {
751+
(next_line_result, true)
752+
} else {
753+
(orig_result, true)
754+
}
755+
} else {
756+
(orig_result, false)
757+
}
758+
}
759+
_ => (orig_result, context.config.allow_chain_call_overflow()),
760+
},
761+
_ => (orig_result, false),
762+
},
763+
(None, Some(next_line_result)) => (next_line_result, true),
764+
(Some(orig_result), None) => (orig_result, false),
765+
// This only occurs when the chain item exceeds the configured max_width.
766+
// Grab the original snippet so that the chain can still be wrapped.
767+
(None, None) => (context.snippet(item.span).to_owned(), false),
768+
}
769+
}
770+
716771
impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
717772
fn format_root(
718773
&mut self,
719774
parent: &ChainItem,
720775
context: &RewriteContext<'_>,
721776
shape: Shape,
722777
) -> Option<()> {
723-
let mut root_rewrite = if context.config.allow_chain_call_overflow() {
724-
parent
725-
.rewrite(context, shape)
726-
.unwrap_or_else(|| context.snippet(parent.span).to_owned())
727-
} else {
728-
parent.rewrite(context, shape)?
729-
};
778+
let (mut root_rewrite, forced_root_block) = format_chain_item(parent, context, shape);
730779

731780
let mut root_ends_with_block = parent.kind.is_block_like(context, &root_rewrite);
732781
let tab_width = context.config.tab_spaces().saturating_sub(shape.offset);
@@ -750,7 +799,8 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
750799
}
751800
}
752801
self.shared.rewrites.push(root_rewrite);
753-
self.root_ends_with_block = root_ends_with_block;
802+
self.root_ends_with_block = root_ends_with_block && !forced_root_block;
803+
754804
Some(())
755805
}
756806

src/expr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1897,7 +1897,8 @@ fn choose_rhs<R: Rewrite>(
18971897
if wrap_str(new_rhs.clone(), context.config.max_width(), new_shape)
18981898
.is_none() =>
18991899
{
1900-
Some(format!(" {}", orig_rhs))
1900+
let prefix = if orig_rhs.starts_with('\n') { "" } else { " " };
1901+
Some(format!("{}{}", prefix, orig_rhs))
19011902
}
19021903
(Some(ref orig_rhs), Some(ref new_rhs))
19031904
if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) =>

0 commit comments

Comments
 (0)