Skip to content

Commit fbe0424

Browse files
ding-youngytmimi
authored andcommitted
update rewrite_chain to return RewriteResult
1 parent caaa612 commit fbe0424

File tree

2 files changed

+107
-56
lines changed

2 files changed

+107
-56
lines changed

src/chains.rs

+106-55
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ use thin_vec::ThinVec;
7979
/// Provides the original input contents from the span
8080
/// of a chain element with trailing spaces trimmed.
8181
fn format_overflow_style(span: Span, context: &RewriteContext<'_>) -> Option<String> {
82+
// TODO(ding-young): Currently returning None when the given span is out of the range
83+
// covered by the snippet provider. If this is a common cause for internal
84+
// rewrite failure, add a new enum variant and return RewriteError instead of None
8285
context.snippet_provider.span_to_snippet(span).map(|s| {
8386
s.lines()
8487
.map(|l| l.trim_end())
@@ -92,12 +95,16 @@ fn format_chain_item(
9295
context: &RewriteContext<'_>,
9396
rewrite_shape: Shape,
9497
allow_overflow: bool,
95-
) -> Option<String> {
98+
) -> RewriteResult {
9699
if allow_overflow {
97-
item.rewrite(context, rewrite_shape)
98-
.or_else(|| format_overflow_style(item.span, context))
100+
// TODO(ding-young): Consider calling format_overflow_style()
101+
// only when item.rewrite_result() returns RewriteError::ExceedsMaxWidth.
102+
// It may be inappropriate to call format_overflow_style on other RewriteError
103+
// since the current approach retries formatting if allow_overflow is true
104+
item.rewrite_result(context, rewrite_shape)
105+
.or_else(|_| format_overflow_style(item.span, context).unknown_error())
99106
} else {
100-
item.rewrite(context, rewrite_shape)
107+
item.rewrite_result(context, rewrite_shape)
101108
}
102109
}
103110

@@ -134,17 +141,17 @@ pub(crate) fn rewrite_chain(
134141
expr: &ast::Expr,
135142
context: &RewriteContext<'_>,
136143
shape: Shape,
137-
) -> Option<String> {
144+
) -> RewriteResult {
138145
let chain = Chain::from_ast(expr, context);
139146
debug!("rewrite_chain {:?} {:?}", chain, shape);
140147

141148
// If this is just an expression with some `?`s, then format it trivially and
142149
// return early.
143150
if chain.children.is_empty() {
144-
return chain.parent.rewrite(context, shape);
151+
return chain.parent.rewrite_result(context, shape);
145152
}
146153

147-
chain.rewrite(context, shape)
154+
chain.rewrite_result(context, shape)
148155
}
149156

150157
#[derive(Debug)]
@@ -524,6 +531,10 @@ impl Chain {
524531

525532
impl Rewrite for Chain {
526533
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
534+
self.rewrite_result(context, shape).ok()
535+
}
536+
537+
fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
527538
debug!("rewrite chain {:?} {:?}", self, shape);
528539

529540
let mut formatter = match context.config.indent_style() {
@@ -537,17 +548,25 @@ impl Rewrite for Chain {
537548

538549
formatter.format_root(&self.parent, context, shape)?;
539550
if let Some(result) = formatter.pure_root() {
540-
return wrap_str(result, context.config.max_width(), shape);
551+
return wrap_str(result, context.config.max_width(), shape)
552+
.max_width_error(shape.width, self.parent.span);
541553
}
542554

555+
let first = self.children.first().unwrap_or(&self.parent);
556+
let last = self.children.last().unwrap_or(&self.parent);
557+
let children_span = mk_sp(first.span.lo(), last.span.hi());
558+
let full_span = self.parent.span.with_hi(children_span.hi());
559+
543560
// Decide how to layout the rest of the chain.
544-
let child_shape = formatter.child_shape(context, shape)?;
561+
let child_shape = formatter
562+
.child_shape(context, shape)
563+
.max_width_error(shape.width, children_span)?;
545564

546565
formatter.format_children(context, child_shape)?;
547566
formatter.format_last_child(context, shape, child_shape)?;
548567

549568
let result = formatter.join_rewrites(context, child_shape)?;
550-
wrap_str(result, context.config.max_width(), shape)
569+
wrap_str(result, context.config.max_width(), shape).max_width_error(shape.width, full_span)
551570
}
552571
}
553572

@@ -569,16 +588,20 @@ trait ChainFormatter {
569588
parent: &ChainItem,
570589
context: &RewriteContext<'_>,
571590
shape: Shape,
572-
) -> Option<()>;
591+
) -> Result<(), RewriteError>;
573592
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape>;
574-
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()>;
593+
fn format_children(
594+
&mut self,
595+
context: &RewriteContext<'_>,
596+
child_shape: Shape,
597+
) -> Result<(), RewriteError>;
575598
fn format_last_child(
576599
&mut self,
577600
context: &RewriteContext<'_>,
578601
shape: Shape,
579602
child_shape: Shape,
580-
) -> Option<()>;
581-
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String>;
603+
) -> Result<(), RewriteError>;
604+
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult;
582605
// Returns `Some` if the chain is only a root, None otherwise.
583606
fn pure_root(&mut self) -> Option<String>;
584607
}
@@ -621,12 +644,16 @@ impl<'a> ChainFormatterShared<'a> {
621644
}
622645
}
623646

624-
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
647+
fn format_children(
648+
&mut self,
649+
context: &RewriteContext<'_>,
650+
child_shape: Shape,
651+
) -> Result<(), RewriteError> {
625652
for item in &self.children[..self.children.len() - 1] {
626653
let rewrite = format_chain_item(item, context, child_shape, self.allow_overflow)?;
627654
self.rewrites.push(rewrite);
628655
}
629-
Some(())
656+
Ok(())
630657
}
631658

632659
// Rewrite the last child. The last child of a chain requires special treatment. We need to
@@ -667,8 +694,8 @@ impl<'a> ChainFormatterShared<'a> {
667694
context: &RewriteContext<'_>,
668695
shape: Shape,
669696
child_shape: Shape,
670-
) -> Option<()> {
671-
let last = self.children.last()?;
697+
) -> Result<(), RewriteError> {
698+
let last = self.children.last().unknown_error()?;
672699
let extendable = may_extend && last_line_extendable(&self.rewrites[0]);
673700
let prev_last_line_width = last_line_width(&self.rewrites[0]);
674701

@@ -692,11 +719,17 @@ impl<'a> ChainFormatterShared<'a> {
692719
&& self.rewrites.iter().all(|s| !s.contains('\n'))
693720
&& one_line_budget > 0;
694721
let last_shape = if all_in_one_line {
695-
shape.sub_width(last.tries)?
722+
shape
723+
.sub_width(last.tries)
724+
.max_width_error(shape.width, last.span)?
696725
} else if extendable {
697-
child_shape.sub_width(last.tries)?
726+
child_shape
727+
.sub_width(last.tries)
728+
.max_width_error(child_shape.width, last.span)?
698729
} else {
699-
child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?
730+
child_shape
731+
.sub_width(shape.rhs_overhead(context.config) + last.tries)
732+
.max_width_error(child_shape.width, last.span)?
700733
};
701734

702735
let mut last_subexpr_str = None;
@@ -712,7 +745,7 @@ impl<'a> ChainFormatterShared<'a> {
712745
};
713746

714747
if let Some(one_line_shape) = one_line_shape {
715-
if let Some(rw) = last.rewrite(context, one_line_shape) {
748+
if let Ok(rw) = last.rewrite_result(context, one_line_shape) {
716749
// We allow overflowing here only if both of the following conditions match:
717750
// 1. The entire chain fits in a single line except the last child.
718751
// 2. `last_child_str.lines().count() >= 5`.
@@ -727,17 +760,18 @@ impl<'a> ChainFormatterShared<'a> {
727760
// last child on its own line, and compare two rewrites to choose which is
728761
// better.
729762
let last_shape = child_shape
730-
.sub_width(shape.rhs_overhead(context.config) + last.tries)?;
731-
match last.rewrite(context, last_shape) {
732-
Some(ref new_rw) if !could_fit_single_line => {
763+
.sub_width(shape.rhs_overhead(context.config) + last.tries)
764+
.max_width_error(child_shape.width, last.span)?;
765+
match last.rewrite_result(context, last_shape) {
766+
Ok(ref new_rw) if !could_fit_single_line => {
733767
last_subexpr_str = Some(new_rw.clone());
734768
}
735-
Some(ref new_rw) if new_rw.lines().count() >= line_count => {
769+
Ok(ref new_rw) if new_rw.lines().count() >= line_count => {
736770
last_subexpr_str = Some(rw);
737771
self.fits_single_line = could_fit_single_line && all_in_one_line;
738772
}
739-
new_rw @ Some(..) => {
740-
last_subexpr_str = new_rw;
773+
Ok(new_rw) => {
774+
last_subexpr_str = Some(new_rw);
741775
}
742776
_ => {
743777
last_subexpr_str = Some(rw);
@@ -752,22 +786,28 @@ impl<'a> ChainFormatterShared<'a> {
752786
let last_shape = if context.use_block_indent() {
753787
last_shape
754788
} else {
755-
child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?
789+
child_shape
790+
.sub_width(shape.rhs_overhead(context.config) + last.tries)
791+
.max_width_error(child_shape.width, last.span)?
756792
};
757793

758-
last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite(context, last_shape));
759-
self.rewrites.push(last_subexpr_str?);
760-
Some(())
794+
let last_subexpr_str =
795+
last_subexpr_str.unwrap_or(last.rewrite_result(context, last_shape)?);
796+
self.rewrites.push(last_subexpr_str);
797+
Ok(())
761798
}
762799

763-
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String> {
800+
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult {
764801
let connector = if self.fits_single_line {
765802
// Yay, we can put everything on one line.
766803
Cow::from("")
767804
} else {
768805
// Use new lines.
769806
if context.force_one_line_chain.get() {
770-
return None;
807+
return Err(RewriteError::ExceedsMaxWidth {
808+
configured_width: child_shape.width,
809+
span: self.children.last().unknown_error()?.span,
810+
});
771811
}
772812
child_shape.to_string_with_newline(context.config)
773813
};
@@ -786,7 +826,7 @@ impl<'a> ChainFormatterShared<'a> {
786826
result.push_str(rewrite);
787827
}
788828

789-
Some(result)
829+
Ok(result)
790830
}
791831
}
792832

@@ -811,8 +851,8 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
811851
parent: &ChainItem,
812852
context: &RewriteContext<'_>,
813853
shape: Shape,
814-
) -> Option<()> {
815-
let mut root_rewrite: String = parent.rewrite(context, shape)?;
854+
) -> Result<(), RewriteError> {
855+
let mut root_rewrite: String = parent.rewrite_result(context, shape)?;
816856

817857
let mut root_ends_with_block = parent.kind.is_block_like(context, &root_rewrite);
818858
let tab_width = context.config.tab_spaces().saturating_sub(shape.offset);
@@ -822,10 +862,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
822862
if let ChainItemKind::Comment(..) = item.kind {
823863
break;
824864
}
825-
let shape = shape.offset_left(root_rewrite.len())?;
826-
match &item.rewrite(context, shape) {
827-
Some(rewrite) => root_rewrite.push_str(rewrite),
828-
None => break,
865+
let shape = shape
866+
.offset_left(root_rewrite.len())
867+
.max_width_error(shape.width, item.span)?;
868+
match &item.rewrite_result(context, shape) {
869+
Ok(rewrite) => root_rewrite.push_str(rewrite),
870+
Err(_) => break,
829871
}
830872

831873
root_ends_with_block = last_line_extendable(&root_rewrite);
@@ -837,15 +879,19 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
837879
}
838880
self.shared.rewrites.push(root_rewrite);
839881
self.root_ends_with_block = root_ends_with_block;
840-
Some(())
882+
Ok(())
841883
}
842884

843885
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
844886
let block_end = self.root_ends_with_block;
845887
Some(get_block_child_shape(block_end, context, shape))
846888
}
847889

848-
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
890+
fn format_children(
891+
&mut self,
892+
context: &RewriteContext<'_>,
893+
child_shape: Shape,
894+
) -> Result<(), RewriteError> {
849895
self.shared.format_children(context, child_shape)
850896
}
851897

@@ -854,12 +900,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
854900
context: &RewriteContext<'_>,
855901
shape: Shape,
856902
child_shape: Shape,
857-
) -> Option<()> {
903+
) -> Result<(), RewriteError> {
858904
self.shared
859905
.format_last_child(true, context, shape, child_shape)
860906
}
861907

862-
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String> {
908+
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult {
863909
self.shared.join_rewrites(context, child_shape)
864910
}
865911

@@ -890,9 +936,9 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
890936
parent: &ChainItem,
891937
context: &RewriteContext<'_>,
892938
shape: Shape,
893-
) -> Option<()> {
939+
) -> Result<(), RewriteError> {
894940
let parent_shape = shape.visual_indent(0);
895-
let mut root_rewrite = parent.rewrite(context, parent_shape)?;
941+
let mut root_rewrite = parent.rewrite_result(context, parent_shape)?;
896942
let multiline = root_rewrite.contains('\n');
897943
self.offset = if multiline {
898944
last_line_width(&root_rewrite).saturating_sub(shape.used_width())
@@ -904,18 +950,19 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
904950
let item = &self.shared.children[0];
905951
if let ChainItemKind::Comment(..) = item.kind {
906952
self.shared.rewrites.push(root_rewrite);
907-
return Some(());
953+
return Ok(());
908954
}
909955
let child_shape = parent_shape
910956
.visual_indent(self.offset)
911-
.sub_width(self.offset)?;
912-
let rewrite = item.rewrite(context, child_shape)?;
957+
.sub_width(self.offset)
958+
.max_width_error(parent_shape.width, item.span)?;
959+
let rewrite = item.rewrite_result(context, child_shape)?;
913960
if filtered_str_fits(&rewrite, context.config.max_width(), shape) {
914961
root_rewrite.push_str(&rewrite);
915962
} else {
916963
// We couldn't fit in at the visual indent, try the last
917964
// indent.
918-
let rewrite = item.rewrite(context, parent_shape)?;
965+
let rewrite = item.rewrite_result(context, parent_shape)?;
919966
root_rewrite.push_str(&rewrite);
920967
self.offset = 0;
921968
}
@@ -924,7 +971,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
924971
}
925972

926973
self.shared.rewrites.push(root_rewrite);
927-
Some(())
974+
Ok(())
928975
}
929976

930977
fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
@@ -937,7 +984,11 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
937984
)
938985
}
939986

940-
fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
987+
fn format_children(
988+
&mut self,
989+
context: &RewriteContext<'_>,
990+
child_shape: Shape,
991+
) -> Result<(), RewriteError> {
941992
self.shared.format_children(context, child_shape)
942993
}
943994

@@ -946,12 +997,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
946997
context: &RewriteContext<'_>,
947998
shape: Shape,
948999
child_shape: Shape,
949-
) -> Option<()> {
1000+
) -> Result<(), RewriteError> {
9501001
self.shared
9511002
.format_last_child(false, context, shape, child_shape)
9521003
}
9531004

954-
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String> {
1005+
fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult {
9551006
self.shared.join_rewrites(context, child_shape)
9561007
}
9571008

src/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ pub(crate) fn format_expr(
241241
ast::ExprKind::Try(..)
242242
| ast::ExprKind::Field(..)
243243
| ast::ExprKind::MethodCall(..)
244-
| ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape),
244+
| ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape).ok(),
245245
ast::ExprKind::MacCall(ref mac) => {
246246
rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| {
247247
wrap_str(

0 commit comments

Comments
 (0)