Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 40778f5

Browse files
authored
Merge pull request #1422 from Xanewok/reformat-range-fix
Always send correct end column when formatting
2 parents 7efdf31 + fac0118 commit 40778f5

File tree

2 files changed

+39
-30
lines changed

2 files changed

+39
-30
lines changed

rls/src/actions/format.rs

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ impl Rustfmt {
7878
NewlineStyle::Native => native,
7979
};
8080

81+
let lsp_line_length = |line: &str| line.chars().map(char::len_utf16).sum();
82+
let line_cols: Vec<usize> = input.lines().map(lsp_line_length).collect();
83+
8184
let output = self.format(input, cfg)?;
8285
let ModifiedLines { chunks } = output.parse().map_err(|_| Error::Failed)?;
8386

@@ -86,15 +89,21 @@ impl Rustfmt {
8689
.map(|item| {
8790
// Rustfmt's line indices are 1-based
8891
let start_line = u64::from(item.line_number_orig) - 1;
89-
// Could underflow if we don't remove lines and there's only one
90-
let removed = u64::from(item.lines_removed).saturating_sub(1);
92+
let end_line = {
93+
// Could underflow if we don't remove lines and there's only one
94+
let removed = u64::from(item.lines_removed).saturating_sub(1);
95+
start_line + removed
96+
};
97+
let end_col: Option<usize> = line_cols.get(end_line as usize).copied();
98+
let end_col: u64 = end_col.map(|col| col as u64).unwrap_or_else(u64::max_value);
99+
91100
TextEdit {
92101
range: Range {
93102
start: Position::new(start_line, 0),
94103
// We don't extend the range past the last line because
95104
// sometimes it may not exist, skewing the diff and
96105
// making us add an invalid additional trailing newline.
97-
end: Position::new(start_line + removed, u64::max_value()),
106+
end: Position::new(end_line, end_col),
98107
},
99108
new_text: item.lines.join(newline),
100109
}
@@ -202,34 +211,34 @@ mod tests {
202211

203212
#[test]
204213
fn calc_text_edits() {
205-
let config = || FmtConfig::default().get_rustfmt_config().clone();
206-
let format = |x: &str| Rustfmt::Internal.calc_text_edits(x.to_string(), config()).unwrap();
207-
let line_range = |start, end| Range {
208-
start: Position { line: start, character: 0 },
209-
end: Position { line: end, character: u64::max_value() },
210-
};
211-
// Handle single-line text wrt. added/removed trailing newline
212-
assert_eq!(
213-
format("fn main() {} "),
214-
vec![TextEdit { range: line_range(0, 0), new_text: "fn main() {}\n".to_owned() }]
215-
);
216-
217-
assert_eq!(
218-
format("fn main() {} \n"),
219-
vec![TextEdit { range: line_range(0, 0), new_text: "fn main() {}".to_owned() }]
220-
);
214+
fn format(input: &str) -> Vec<TextEdit> {
215+
let config = || FmtConfig::default().get_rustfmt_config().clone();
216+
Rustfmt::Internal.calc_text_edits(input.to_string(), config()).unwrap()
217+
}
221218

222-
assert_eq!(
223-
format("\nfn main() {} \n"),
224-
vec![TextEdit { range: line_range(0, 1), new_text: "fn main() {}".to_owned() }]
225-
);
219+
fn test_case(input: &str, output: Vec<(u64, u64, u64, u64, &str)>) {
220+
assert_eq!(
221+
format(input),
222+
output
223+
.into_iter()
224+
.map(|(start_l, start_c, end_l, end_c, out)| TextEdit {
225+
range: Range {
226+
start: Position { line: start_l, character: start_c },
227+
end: Position { line: end_l, character: end_c },
228+
},
229+
new_text: out.to_owned(),
230+
})
231+
.collect::<Vec<_>>()
232+
)
233+
}
234+
// Handle single-line text wrt. added/removed trailing newline
235+
test_case("fn main() {} ", vec![(0, 0, 0, 13, "fn main() {}\n")]);
236+
test_case("fn main() {} \n", vec![(0, 0, 0, 13, "fn main() {}")]);
237+
test_case("\nfn main() {} \n", vec![(0, 0, 1, 13, "fn main() {}")]);
226238
// Check that we send two separate edits
227-
assert_eq!(
228-
format(" struct Upper ;\n\nstruct Lower ;"),
229-
vec![
230-
TextEdit { range: line_range(0, 0), new_text: "struct Upper;".to_owned() },
231-
TextEdit { range: line_range(2, 2), new_text: "struct Lower;\n".to_owned() }
232-
]
239+
test_case(
240+
" struct Upper ;\n\nstruct Lower ;",
241+
vec![(0, 0, 0, 16, "struct Upper;"), (2, 0, 2, 14, "struct Lower;\n")],
233242
);
234243
}
235244
}

tests/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1763,7 +1763,7 @@ fn client_reformat() {
17631763
assert_eq!(result.unwrap()[0], TextEdit {
17641764
range: Range {
17651765
start: Position { line: 0, character: 0 },
1766-
end: Position { line: 1, character: u64::max_value() },
1766+
end: Position { line: 1, character: 69 },
17671767
},
17681768
new_text: "pub mod foo;\npub fn main() {\n let world = \"world\";\n println!(\"Hello, {}!\", world);\n}".to_string(),
17691769
});

0 commit comments

Comments
 (0)