diff --git a/Cargo.lock b/Cargo.lock index 93631697c1e93de55d1c32ce89360dadd0926f34..24cd7a7748622e2c7a12f49f125ffa0c123a7dfd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6785,6 +6785,7 @@ name = "util" version = "0.1.0" dependencies = [ "anyhow", + "backtrace", "futures 0.3.24", "git2", "lazy_static", diff --git a/crates/rope/Cargo.toml b/crates/rope/Cargo.toml index 0f754c1fb3f30e820ceb76d816c2cf09abb2d2a5..bd1dc690db8b34b78846f96cbb06d36ec70cc65b 100644 --- a/crates/rope/Cargo.toml +++ b/crates/rope/Cargo.toml @@ -12,7 +12,7 @@ smallvec = { version = "1.6", features = ["union"] } sum_tree = { path = "../sum_tree" } arrayvec = "0.7.1" log = { version = "0.4.16", features = ["kv_unstable_serde"] } - +util = { path = "../util" } [dev-dependencies] rand = "0.8.3" diff --git a/crates/rope/src/rope.rs b/crates/rope/src/rope.rs index d4ee894310a103cd8fd183da3202c756f5b85605..53713e3f7a35f7e0d1f3c463575f60f0c5af0efe 100644 --- a/crates/rope/src/rope.rs +++ b/crates/rope/src/rope.rs @@ -12,6 +12,7 @@ use std::{ str, }; use sum_tree::{Bias, Dimension, SumTree}; +use util::debug_panic; pub use offset_utf16::OffsetUtf16; pub use point::Point; @@ -679,28 +680,33 @@ impl Chunk { fn point_to_offset(&self, target: Point) -> usize { let mut offset = 0; let mut point = Point::new(0, 0); + for ch in self.0.chars() { if point >= target { if point > target { - panic!("point {:?} is inside of character {:?}", target, ch); + debug_panic!("point {target:?} is inside of character {ch:?}"); } break; } if ch == '\n' { point.row += 1; + point.column = 0; + if point.row > target.row { - panic!( - "point {:?} is beyond the end of a line with length {}", - target, point.column + debug_panic!( + "point {target:?} is beyond the end of a line with length {}", + point.column ); + break; } - point.column = 0; } else { point.column += ch.len_utf8() as u32; } + offset += ch.len_utf8(); } + offset } @@ -737,26 +743,27 @@ impl Chunk { if ch == '\n' { point.row += 1; point.column = 0; + if point.row > target.row { - if clip { - // Return the offset of the newline - return offset; + if !clip { + debug_panic!( + "point {target:?} is beyond the end of a line with length {}", + point.column + ); } - panic!( - "point {:?} is beyond the end of a line with length {}", - target, point.column - ); + // Return the offset of the newline + return offset; } } else { point.column += ch.len_utf16() as u32; } if point > target { - if clip { - // Return the offset of the codepoint which we have landed within, bias left - return offset; + if !clip { + debug_panic!("point {target:?} is inside of codepoint {ch:?}"); } - panic!("point {:?} is inside of codepoint {:?}", target, ch); + // Return the offset of the codepoint which we have landed within, bias left + return offset; } offset += ch.len_utf8(); diff --git a/crates/util/Cargo.toml b/crates/util/Cargo.toml index c083137156fa5c39f3b9d53568f7c319d05c6a3f..fc16eeb53c3751006917e181b2f4ae184d9d2940 100644 --- a/crates/util/Cargo.toml +++ b/crates/util/Cargo.toml @@ -11,6 +11,7 @@ test-support = ["serde_json", "tempdir", "git2"] [dependencies] anyhow = "1.0.38" +backtrace = "0.3" futures = "0.3" log = { version = "0.4.16", features = ["kv_unstable_serde"] } lazy_static = "1.4.0" diff --git a/crates/util/src/lib.rs b/crates/util/src/lib.rs index e35f2df7d42f6f87f30f9f99f49a20b2c95b62af..22d63a0996f10d72294974036b85498632d0d680 100644 --- a/crates/util/src/lib.rs +++ b/crates/util/src/lib.rs @@ -1,6 +1,7 @@ #[cfg(any(test, feature = "test-support"))] pub mod test; +pub use backtrace::Backtrace; use futures::Future; use rand::{seq::SliceRandom, Rng}; use std::{ @@ -10,6 +11,18 @@ use std::{ task::{Context, Poll}, }; +#[macro_export] +macro_rules! debug_panic { + ( $($fmt_arg:tt)* ) => { + if cfg!(debug_assertions) { + panic!( $($fmt_arg)* ); + } else { + let backtrace = $crate::Backtrace::new(); + log::error!("{}\n{:?}", format_args!($($fmt_arg)*), backtrace); + } + }; +} + pub fn truncate(s: &str, max_chars: usize) -> &str { match s.char_indices().nth(max_chars) { None => s,