Prevent a panic when uncommenting a line with only a comment token (#5933)

Open a new document `test.rs` and type the following:
`di//<esc><C-c>`

The margin calculation pushes the range out of bounds for the comment
marker when there are no characters (newline) after it.

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value:
Char range out of bounds: char range 0..3,
Rope/RopeSlice char length 2', ropey-1.6.0/src/rope.rs:546:37

The debug build catches the error in the transaction: thread 'main'
panicked at 'attempt to subtract with overflow',
helix-core/src/transaction.rs:503:26
pull/5959/head
Mike Trinkala 2 years ago committed by GitHub
parent a4751db8c7
commit ef221abe83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -45,7 +45,7 @@ fn find_line_comment(
// determine margin of 0 or 1 for uncommenting; if any comment token is not followed by a space, // determine margin of 0 or 1 for uncommenting; if any comment token is not followed by a space,
// a margin of 0 is used for all lines. // a margin of 0 is used for all lines.
if matches!(line_slice.get_char(pos + token_len), Some(c) if c != ' ') { if !matches!(line_slice.get_char(pos + token_len), Some(c) if c == ' ') {
margin = 0; margin = 0;
} }
@ -108,8 +108,8 @@ mod test {
let text = doc.slice(..); let text = doc.slice(..);
let res = find_line_comment("//", text, 0..3); let res = find_line_comment("//", text, 0..3);
// (commented = true, to_change = [line 0, line 2], min = col 2, margin = 1) // (commented = true, to_change = [line 0, line 2], min = col 2, margin = 0)
assert_eq!(res, (false, vec![0, 2], 2, 1)); assert_eq!(res, (false, vec![0, 2], 2, 0));
// comment // comment
let transaction = toggle_line_comments(&doc, &selection, None); let transaction = toggle_line_comments(&doc, &selection, None);
@ -136,6 +136,17 @@ mod test {
assert_eq!(doc, " 1\n\n 2\n 3"); assert_eq!(doc, " 1\n\n 2\n 3");
assert!(selection.len() == 1); // to ignore the selection unused warning assert!(selection.len() == 1); // to ignore the selection unused warning
// 0 margin comments, with no space
doc = Rope::from("//");
// reset the selection.
selection = Selection::single(0, doc.len_chars() - 1);
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, "");
assert!(selection.len() == 1); // to ignore the selection unused warning
// TODO: account for uncommenting with uneven comment indentation // TODO: account for uncommenting with uneven comment indentation
} }
} }

Loading…
Cancel
Save