Skip to content

Commit 2595630

Browse files
Teach last_line_width about config.tab_spaces
So that the line width is calculated as the rendered width of any trailing space plus the unicode width of the rest of the string. That is, for example, so that the line: \s\s\s\ssome_func(); Would have the same length as \tsome_func(); Assuming `tab_spaces=4`. This fixes a issue where the formatting a collection of binary operations would depend on whether hard of soft tabs were used. Specifically in the change to the call of `last_line_width` at line 135 of `src/pairs.rs`: the inconsistency above meant under some conditions when using hard tabs we could satisfy the condition on that line and drop into the block to snuggle the lines together, where with soft tabs a different width would be computed and we'd avoid snuggling them. A test has been added covering this case.
1 parent 2b98d06 commit 2595630

15 files changed

Lines changed: 199 additions & 83 deletions

src/chains.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,13 @@ impl Rewrite for Chain {
566566

567567
formatter.format_root(&self.parent, context, shape)?;
568568
if let Some(result) = formatter.pure_root() {
569-
return wrap_str(result, context.config.max_width(), shape)
570-
.max_width_error(shape.width, self.parent.span);
569+
return wrap_str(
570+
result,
571+
context.config.max_width(),
572+
context.config.tab_spaces(),
573+
shape,
574+
)
575+
.max_width_error(shape.width, self.parent.span);
571576
}
572577

573578
let first = self.children.first().unwrap_or(&self.parent);
@@ -582,7 +587,13 @@ impl Rewrite for Chain {
582587
formatter.format_last_child(context, shape, child_shape)?;
583588

584589
let result = formatter.join_rewrites(context, child_shape)?;
585-
wrap_str(result, context.config.max_width(), shape).max_width_error(shape.width, full_span)
590+
wrap_str(
591+
result,
592+
context.config.max_width(),
593+
context.config.tab_spaces(),
594+
shape,
595+
)
596+
.max_width_error(shape.width, full_span)
586597
}
587598
}
588599

@@ -718,7 +729,7 @@ impl<'a> ChainFormatterShared<'a> {
718729
) -> Result<(), RewriteError> {
719730
let last = self.children.last().unknown_error()?;
720731
let extendable = may_extend && last_line_extendable(&self.rewrites[0]);
721-
let prev_last_line_width = last_line_width(&self.rewrites[0]);
732+
let prev_last_line_width = last_line_width(&self.rewrites[0], context.config.tab_spaces());
722733

723734
// Total of all items excluding the last.
724735
let almost_total = if extendable {
@@ -958,7 +969,8 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
958969
let mut root_rewrite = parent.rewrite_result(context, parent_shape)?;
959970
let multiline = root_rewrite.contains('\n');
960971
self.offset = if multiline {
961-
last_line_width(&root_rewrite).saturating_sub(shape.used_width())
972+
last_line_width(&root_rewrite, context.config.tab_spaces())
973+
.saturating_sub(shape.used_width())
962974
} else {
963975
trimmed_last_line_width(&root_rewrite)
964976
};
@@ -973,7 +985,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
973985
.visual_indent(self.offset)
974986
.sub_width(self.offset, item.span)?;
975987
let rewrite = item.rewrite_result(context, child_shape)?;
976-
if filtered_str_fits(&rewrite, context.config.max_width(), shape) {
988+
if filtered_str_fits(
989+
&rewrite,
990+
context.config.max_width(),
991+
context.config.tab_spaces(),
992+
shape,
993+
) {
977994
root_rewrite.push_str(&rewrite);
978995
} else {
979996
// We couldn't fit in at the visual indent, try the last

src/closures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ fn rewrite_closure_fn_decl(
351351
prefix.push_str(&ret_str);
352352
}
353353
// 1 = space between `|...|` and body.
354-
let extra_offset = last_line_width(&prefix) + 1;
354+
let extra_offset = last_line_width(&prefix, context.config.tab_spaces()) + 1;
355355

356356
Ok((prefix, extra_offset))
357357
}

src/comment.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,9 @@ pub(crate) fn combine_strs_with_missing_comments(
174174
} else {
175175
" "
176176
};
177-
let mut one_line_width =
178-
last_line_width(prev_str) + first_line_width(next_str) + first_sep.len();
177+
let mut one_line_width = last_line_width(prev_str, context.config.tab_spaces())
178+
+ first_line_width(next_str)
179+
+ first_sep.len();
179180

180181
let config = context.config;
181182
let indent = shape.indent;
@@ -207,7 +208,9 @@ pub(crate) fn combine_strs_with_missing_comments(
207208
let first_sep = if prev_str.is_empty() || missing_comment.is_empty() {
208209
Cow::from("")
209210
} else {
210-
let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1;
211+
let one_line_width = last_line_width(prev_str, context.config.tab_spaces())
212+
+ first_line_width(&missing_comment)
213+
+ 1;
211214
if prefer_same_line && one_line_width <= shape.width {
212215
Cow::from(" ")
213216
} else {
@@ -871,7 +874,8 @@ impl<'a> CommentRewrite<'a> {
871874

872875
self.fmt.shape = if self.is_prev_line_multi_line {
873876
// 1 = " "
874-
let offset = 1 + last_line_width(&self.result) - self.line_start.len();
877+
let offset = 1 + last_line_width(&self.result, self.fmt.config.tab_spaces())
878+
- self.line_start.len();
875879
Shape {
876880
width: self.max_width.saturating_sub(offset),
877881
indent: self.fmt_indent,

src/expr.rs

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ pub(crate) fn format_expr(
279279
wrap_str(
280280
context.snippet(expr.span).to_owned(),
281281
context.config.max_width(),
282+
context.config.tab_spaces(),
282283
shape,
283284
)
284285
.max_width_error(shape.width, expr.span)
@@ -597,7 +598,10 @@ fn rewrite_single_line_block(
597598
shape: Shape,
598599
) -> RewriteResult {
599600
if let Some(block_expr) = stmt::Stmt::from_simple_block(context, block, attrs) {
600-
let expr_shape = shape.offset_left(last_line_width(prefix), block_expr.span())?;
601+
let expr_shape = shape.offset_left(
602+
last_line_width(prefix, context.config.tab_spaces()),
603+
block_expr.span(),
604+
)?;
601605
let expr_str = block_expr.rewrite_result(context, expr_shape)?;
602606
let label_str = rewrite_label(context, label);
603607
let result = format!("{prefix}{label_str}{{ {expr_str} }}");
@@ -1097,7 +1101,7 @@ impl<'a> ControlFlow<'a> {
10971101
};
10981102

10991103
let used_width = if pat_expr_string.contains('\n') {
1100-
last_line_width(&pat_expr_string)
1104+
last_line_width(&pat_expr_string, context.config.tab_spaces())
11011105
} else {
11021106
// 2 = spaces after keyword and condition.
11031107
label_string.len() + self.keyword.len() + pat_expr_string.len() + 2
@@ -1342,6 +1346,7 @@ pub(crate) fn rewrite_literal(
13421346
_ => wrap_str(
13431347
context.snippet(span).to_owned(),
13441348
context.config.max_width(),
1349+
context.config.tab_spaces(),
13451350
shape,
13461351
)
13471352
.max_width_error(shape.width, span),
@@ -1360,8 +1365,13 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) ->
13601365
{
13611366
return Ok(string_lit.to_owned());
13621367
} else {
1363-
return wrap_str(string_lit.to_owned(), context.config.max_width(), shape)
1364-
.max_width_error(shape.width, span);
1368+
return wrap_str(
1369+
string_lit.to_owned(),
1370+
context.config.max_width(),
1371+
context.config.tab_spaces(),
1372+
shape,
1373+
)
1374+
.max_width_error(shape.width, span);
13651375
}
13661376
}
13671377

@@ -1402,6 +1412,7 @@ fn rewrite_int_lit(
14021412
token_lit.suffix.as_ref().map_or("", |s| s.as_str())
14031413
),
14041414
context.config.max_width(),
1415+
context.config.tab_spaces(),
14051416
shape,
14061417
)
14071418
.max_width_error(shape.width, span);
@@ -1411,6 +1422,7 @@ fn rewrite_int_lit(
14111422
wrap_str(
14121423
context.snippet(span).to_owned(),
14131424
context.config.max_width(),
1425+
context.config.tab_spaces(),
14141426
shape,
14151427
)
14161428
.max_width_error(shape.width, span)
@@ -1429,6 +1441,7 @@ fn rewrite_float_lit(
14291441
return wrap_str(
14301442
context.snippet(span).to_owned(),
14311443
context.config.max_width(),
1444+
context.config.tab_spaces(),
14321445
shape,
14331446
)
14341447
.max_width_error(shape.width, span);
@@ -1477,6 +1490,7 @@ fn rewrite_float_lit(
14771490
suffix.unwrap_or(""),
14781491
),
14791492
context.config.max_width(),
1493+
context.config.tab_spaces(),
14801494
shape,
14811495
)
14821496
.max_width_error(shape.width, span)
@@ -1698,7 +1712,7 @@ fn rewrite_index(
16981712
) -> RewriteResult {
16991713
let expr_str = expr.rewrite_result(context, shape)?;
17001714

1701-
let offset = last_line_width(&expr_str) + 1;
1715+
let offset = last_line_width(&expr_str, context.config.tab_spaces()) + 1;
17021716
let rhs_overhead = shape.rhs_overhead(context.config);
17031717
let index_shape = if expr_str.contains('\n') {
17041718
Shape::legacy(context.config.max_width(), shape.indent)
@@ -2220,11 +2234,12 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
22202234
rhs_kind: &RhsAssignKind<'_>,
22212235
rhs_tactics: RhsTactics,
22222236
) -> RewriteResult {
2223-
let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
2224-
shape.indent.width()
2225-
} else {
2226-
0
2227-
});
2237+
let last_line_width =
2238+
last_line_width(lhs, context.config.tab_spaces()).saturating_sub(if lhs.contains('\n') {
2239+
shape.indent.width()
2240+
} else {
2241+
0
2242+
});
22282243
// 1 = space between operator and rhs.
22292244
let orig_shape = shape.offset_left_opt(last_line_width + 1).unwrap_or(Shape {
22302245
width: 0,
@@ -2321,7 +2336,12 @@ fn choose_rhs<R: Rewrite>(
23212336

23222337
match (orig_rhs, new_rhs) {
23232338
(Ok(ref orig_rhs), Ok(ref new_rhs))
2324-
if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) =>
2339+
if !filtered_str_fits(
2340+
&new_rhs,
2341+
context.config.max_width(),
2342+
context.config.tab_spaces(),
2343+
new_shape,
2344+
) =>
23252345
{
23262346
Ok(format!("{before_space_str}{orig_rhs}"))
23272347
}

0 commit comments

Comments
 (0)