Fix editor::GoToDiagnostics cycle (#24697)

Re-lands https://github.com/zed-industries/zed/pull/24446 with a more
appropriate fix


https://github.com/user-attachments/assets/45f665f0-473a-49bd-b013-b9d1bdb902bd

After activating 2nd diagnostics group, `find_map` code for next
diagnostics did not skip the previous group for the same place.

This time, instead of fiddling with the diagnostics group comparison,
the code splits the diagnostics by search place, looks up the active
group (if any) in both split parts, and selects the entries after the
group elements.

Release Notes:

- Fixed `editor::GoToDiagnostics` action stuck when multiple diagnostics
groups belong to the same place
This commit is contained in:
Kirill Bulatov
2025-02-11 22:41:23 +00:00
committed by GitHub
parent 7da913c801
commit 73b32a20e2
2 changed files with 256 additions and 74 deletions
+170
View File
@@ -10668,6 +10668,176 @@ async fn go_to_prev_overlapping_diagnostic(
"});
}
#[gpui::test]
async fn cycle_through_same_place_diagnostics(
executor: BackgroundExecutor,
cx: &mut gpui::TestAppContext,
) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
let lsp_store =
cx.update_editor(|editor, _, cx| editor.project.as_ref().unwrap().read(cx).lsp_store());
cx.set_state(indoc! {"
ˇfn func(abc def: i32) -> u32 {
}
"});
cx.update(|_, cx| {
lsp_store.update(cx, |lsp_store, cx| {
lsp_store
.update_diagnostics(
LanguageServerId(0),
lsp::PublishDiagnosticsParams {
uri: lsp::Url::from_file_path(path!("/root/file")).unwrap(),
version: None,
diagnostics: vec![
lsp::Diagnostic {
range: lsp::Range::new(
lsp::Position::new(0, 11),
lsp::Position::new(0, 12),
),
severity: Some(lsp::DiagnosticSeverity::ERROR),
..Default::default()
},
lsp::Diagnostic {
range: lsp::Range::new(
lsp::Position::new(0, 12),
lsp::Position::new(0, 15),
),
severity: Some(lsp::DiagnosticSeverity::ERROR),
..Default::default()
},
lsp::Diagnostic {
range: lsp::Range::new(
lsp::Position::new(0, 12),
lsp::Position::new(0, 15),
),
severity: Some(lsp::DiagnosticSeverity::ERROR),
..Default::default()
},
lsp::Diagnostic {
range: lsp::Range::new(
lsp::Position::new(0, 25),
lsp::Position::new(0, 28),
),
severity: Some(lsp::DiagnosticSeverity::ERROR),
..Default::default()
},
],
},
&[],
cx,
)
.unwrap()
});
});
executor.run_until_parked();
//// Backward
// Fourth diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abc def: i32) -> ˇu32 {
}
"});
// Third diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abc ˇdef: i32) -> u32 {
}
"});
// Second diagnostic, same place
cx.update_editor(|editor, window, cx| {
editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abc ˇdef: i32) -> u32 {
}
"});
// First diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abcˇ def: i32) -> u32 {
}
"});
// Wrapped over, fourth diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_prev_diagnostic(&GoToPrevDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abc def: i32) -> ˇu32 {
}
"});
cx.update_editor(|editor, window, cx| {
editor.move_to_beginning(&MoveToBeginning, window, cx);
});
cx.assert_editor_state(indoc! {"
ˇfn func(abc def: i32) -> u32 {
}
"});
//// Forward
// First diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_diagnostic(&GoToDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abcˇ def: i32) -> u32 {
}
"});
// Second diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_diagnostic(&GoToDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abc ˇdef: i32) -> u32 {
}
"});
// Third diagnostic, same place
cx.update_editor(|editor, window, cx| {
editor.go_to_diagnostic(&GoToDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abc ˇdef: i32) -> u32 {
}
"});
// Fourth diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_diagnostic(&GoToDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abc def: i32) -> ˇu32 {
}
"});
// Wrapped around, first diagnostic
cx.update_editor(|editor, window, cx| {
editor.go_to_diagnostic(&GoToDiagnostic, window, cx);
});
cx.assert_editor_state(indoc! {"
fn func(abcˇ def: i32) -> u32 {
}
"});
}
#[gpui::test]
async fn test_diagnostics_with_links(cx: &mut TestAppContext) {
init_test(cx, |_| {});