Fix some panics (#43233)

Lukas Wirth created

Fixes ZED-2NP
Fixes ZED-3DP
Fixes ZED-3EV

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/editor/src/editor.rs               |  4 +---
crates/language_tools/src/lsp_log_view.rs | 15 ++++++++-------
crates/util/src/paths.rs                  | 15 +++++++++++----
3 files changed, 20 insertions(+), 14 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -17112,9 +17112,6 @@ impl Editor {
 
             let multi_buffer = editor.read_with(cx, |editor, _| editor.buffer().clone())?;
 
-            let multi_buffer_snapshot =
-                multi_buffer.read_with(cx, |multi_buffer, cx| multi_buffer.snapshot(cx))?;
-
             let (locations, current_location_index) =
                 multi_buffer.update(cx, |multi_buffer, cx| {
                     let mut locations = locations
@@ -17134,6 +17131,7 @@ impl Editor {
                         })
                         .collect::<Vec<_>>();
 
+                    let multi_buffer_snapshot = multi_buffer.snapshot(cx);
                     // There is an O(n) implementation, but given this list will be
                     // small (usually <100 items), the extra O(log(n)) factor isn't
                     // worth the (surprisingly large amount of) extra complexity.

crates/language_tools/src/lsp_log_view.rs 🔗

@@ -5,7 +5,6 @@ use gpui::{
     App, Context, Corner, Entity, EventEmitter, FocusHandle, Focusable, IntoElement, ParentElement,
     Render, Styled, Subscription, Task, WeakEntity, Window, actions, div,
 };
-use itertools::Itertools;
 use language::{LanguageServerId, language_settings::SoftWrap};
 use lsp::{
     LanguageServer, LanguageServerBinary, LanguageServerName, LanguageServerSelector, MessageType,
@@ -241,13 +240,15 @@ impl LspLogView {
                                 ],
                                 cx,
                             );
-                            if text.len() > 1024
-                                && let Some((fold_offset, _)) =
-                                    text.char_indices().dropping(1024).next()
-                                && fold_offset < text.len()
-                            {
+                            if text.len() > 1024 {
+                                let b = editor.buffer().read(cx).as_singleton().unwrap().read(cx);
+                                let fold_offset =
+                                    b.as_rope().ceil_char_boundary(last_offset.0 + 1024);
                                 editor.fold_ranges(
-                                    vec![last_offset + fold_offset..last_offset + text.len()],
+                                    vec![
+                                        MultiBufferOffset(fold_offset)
+                                            ..MultiBufferOffset(b.as_rope().len()),
+                                    ],
                                     false,
                                     window,
                                     cx,

crates/util/src/paths.rs 🔗

@@ -625,7 +625,14 @@ impl PathWithPosition {
     pub fn parse_str(s: &str) -> Self {
         let trimmed = s.trim();
         let path = Path::new(trimmed);
-        let maybe_file_name_with_row_col = path.file_name().unwrap_or_default().to_string_lossy();
+        let Some(maybe_file_name_with_row_col) = path.file_name().unwrap_or_default().to_str()
+        else {
+            return Self {
+                path: Path::new(s).to_path_buf(),
+                row: None,
+                column: None,
+            };
+        };
         if maybe_file_name_with_row_col.is_empty() {
             return Self {
                 path: Path::new(s).to_path_buf(),
@@ -640,15 +647,15 @@ impl PathWithPosition {
         static SUFFIX_RE: LazyLock<Regex> =
             LazyLock::new(|| Regex::new(ROW_COL_CAPTURE_REGEX).unwrap());
         match SUFFIX_RE
-            .captures(&maybe_file_name_with_row_col)
+            .captures(maybe_file_name_with_row_col)
             .map(|caps| caps.extract())
         {
             Some((_, [file_name, maybe_row, maybe_column])) => {
                 let row = maybe_row.parse::<u32>().ok();
                 let column = maybe_column.parse::<u32>().ok();
 
-                let suffix_length = maybe_file_name_with_row_col.len() - file_name.len();
-                let path_without_suffix = &trimmed[..trimmed.len() - suffix_length];
+                let (_, suffix) = trimmed.split_once(file_name).unwrap();
+                let path_without_suffix = &trimmed[..trimmed.len() - suffix.len()];
 
                 Self {
                     path: Path::new(path_without_suffix).to_path_buf(),