Fix a panic when diagnostics contain multiple links (cherry-pick #16601) (#16603)

gcp-cherry-pick-bot[bot] and Conrad Irwin created

Cherry-picked Fix a panic when diagnostics contain multiple links
(#16601)

Follow up from #14518

Release Notes:

- Fixed a panic when diagnostics contain multiple links

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>

Change summary

crates/editor/src/editor_tests.rs | 37 +++++++++++++++++++++++++++++++++
crates/markdown/src/parser.rs     |  8 ++++--
2 files changed, 42 insertions(+), 3 deletions(-)

Detailed changes

crates/editor/src/editor_tests.rs 🔗

@@ -9090,6 +9090,43 @@ async fn go_to_prev_overlapping_diagnostic(
     "});
 }
 
+#[gpui::test]
+async fn test_diagnostics_with_links(cx: &mut TestAppContext) {
+    init_test(cx, |_| {});
+
+    let mut cx = EditorTestContext::new(cx).await;
+
+    cx.set_state(indoc! {"
+        fn func(abˇc def: i32) -> u32 {
+        }
+    "});
+    let project = cx.update_editor(|editor, _| editor.project.clone().unwrap());
+
+    cx.update(|cx| {
+        project.update(cx, |project, cx| {
+            project.update_diagnostics(
+                LanguageServerId(0),
+                lsp::PublishDiagnosticsParams {
+                    uri: lsp::Url::from_file_path("/root/file").unwrap(),
+                    version: None,
+                    diagnostics: vec![lsp::Diagnostic {
+                        range: lsp::Range::new(lsp::Position::new(0, 8), lsp::Position::new(0, 12)),
+                        severity: Some(lsp::DiagnosticSeverity::ERROR),
+                        message: "we've had problems with <https://link.one>, and <https://link.two> is broken".to_string(),
+                        ..Default::default()
+                    }],
+                },
+                &[],
+                cx,
+            )
+        })
+    }).unwrap();
+    cx.run_until_parked();
+    cx.update_editor(|editor, cx| hover_popover::hover(editor, &Default::default(), cx));
+    cx.run_until_parked();
+    cx.update_editor(|editor, _| assert!(editor.hover_state.diagnostic_popover.is_some()))
+}
+
 #[gpui::test]
 async fn go_to_hunk(executor: BackgroundExecutor, cx: &mut gpui::TestAppContext) {
     init_test(cx, |_| {});

crates/markdown/src/parser.rs 🔗

@@ -96,8 +96,8 @@ pub fn parse_links_only(text: &str) -> Vec<(Range<usize>, MarkdownEvent)> {
         start: 0,
         end: text.len(),
     };
-    for link in finder.links(&text[text_range.clone()]) {
-        let link_range = text_range.start + link.start()..text_range.start + link.end();
+    for link in finder.links(&text) {
+        let link_range = link.start()..link.end();
 
         if link_range.start > text_range.start {
             events.push((text_range.start..link_range.start, MarkdownEvent::Text));
@@ -118,7 +118,9 @@ pub fn parse_links_only(text: &str) -> Vec<(Range<usize>, MarkdownEvent)> {
         text_range.start = link_range.end;
     }
 
-    events.push((text_range, MarkdownEvent::Text));
+    if text_range.end > text_range.start {
+        events.push((text_range, MarkdownEvent::Text));
+    }
 
     events
 }