Skip to content

Commit c8fd0cf

Browse files
Fix wrong indenting with hard tabs in binop pairs
When rewriting pairs of multi-line binary operations, we would check the length of a line to see if we can snuggle the current line into the previous one. We compute the length of the previous line using `last_line_width` which is not aware of indentation widths (i.e. `config.tab_spaces`), so if we were formatting something like: if some_long_name { foo } | if some_other_name { bar } Then when we get to the line for `| if some_other_name {` we check the previous line, which is: * `\s\s\s\s\s\s\s\s}' if we are not using hard tabs (and 1 tab = 4 spaces), and * `\t\t}` if we are using hard-tabs `last_line_width` would return 9 for the first one, and 3 for the second. Meaning if we're using hard tabs we could conclude that it should fit on the previous line, leading to inconsistent behaviour between the two. To fix this, create a version of `last_line_width` that is aware of `config.tab_spaces`.
1 parent 1faf402 commit c8fd0cf

3 files changed

Lines changed: 36 additions & 2 deletions

File tree

src/pairs.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult};
77
use crate::shape::Shape;
88
use crate::spanned::Spanned;
99
use crate::utils::{
10-
first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str,
10+
first_line_width, is_single_line, last_line_width, last_line_width_cfg,
11+
trimmed_last_line_width, wrap_str,
1112
};
1213

1314
/// Sigils that decorate a binop pair.
@@ -132,7 +133,7 @@ fn rewrite_pairs_multiline<T: Rewrite>(
132133
} else {
133134
shape.used_width()
134135
};
135-
if last_line_width(&result) + offset <= nested_shape.used_width() {
136+
if last_line_width_cfg(context.config, &result) + offset <= nested_shape.used_width() {
136137
// We must snuggle the next line onto the previous line to avoid an orphan.
137138
if let Some(line_shape) =
138139
shape.offset_left_opt(s.len() + 2 + trimmed_last_line_width(&result))

src/utils.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ pub(crate) fn last_line_width(s: &str) -> usize {
222222
unicode_str_width(s.rsplitn(2, '\n').next().unwrap_or(""))
223223
}
224224

225+
/// The width of the last line in s.
226+
#[inline]
227+
pub(crate) fn last_line_width_cfg(config: &Config, s: &str) -> usize {
228+
let last_line = s.rsplitn(2, '\n').next().unwrap_or("");
229+
let (prefix_width, prefix_end) = get_prefix_space_width2(&config, last_line);
230+
prefix_width + unicode_str_width(&last_line[prefix_end..])
231+
}
232+
225233
/// The total used width of the last line.
226234
#[inline]
227235
pub(crate) fn last_line_used_width(s: &str, offset: usize) -> usize {
@@ -697,6 +705,20 @@ fn get_prefix_space_width(config: &Config, s: &str) -> usize {
697705
width
698706
}
699707

708+
fn get_prefix_space_width2(config: &Config, s: &str) -> (usize, usize) {
709+
let mut width = 0;
710+
let mut prefix_end = 0;
711+
for c in s.chars() {
712+
match c {
713+
' ' => width += 1,
714+
'\t' => width += config.tab_spaces(),
715+
_ => return (width, prefix_end),
716+
}
717+
prefix_end += 1;
718+
}
719+
(width, prefix_end)
720+
}
721+
700722
pub(crate) trait NodeIdExt {
701723
fn root() -> Self;
702724
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// rustfmt-hard_tabs: true
2+
3+
fn testing() {
4+
let _ = some_long_name
5+
| if some_other_long_name {
6+
foo
7+
}
8+
| if some_other_name {
9+
bar
10+
};
11+
}

0 commit comments

Comments
 (0)