Fix diagnostic popups flickering when moving cursor in the boundaries of the symbol (#14870)

This PR just uses ranges returned by an LSP to work, the subsequent PR
would focus on trying to fall back onto tree-sitter in case of info
hovers. I'm also unsure if I'm supposed to use `local_diagnostic` or
`primary_diagnostic` when both are available
Release Notes:

- Fix diagnostic popups flickering when moving cursor in the boundaries
of the symbol

Before:


https://github.com/user-attachments/assets/4905a7e5-c333-453b-b204-264b3ef79586

After:


https://github.com/user-attachments/assets/c742c424-fb20-450d-8848-baaf1937dd47
This commit is contained in:
Stanislav Alekseev 2024-07-23 23:10:19 +03:00 committed by GitHub
parent b2b9d4ccb6
commit 5021397c01
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -213,22 +213,8 @@ fn show_hover(
};
if !ignore_timeout {
if editor
.hover_state
.info_popovers
.iter()
.any(|InfoPopover { symbol_range, .. }| {
symbol_range
.as_text_range()
.map(|range| {
let hover_range = range.to_offset(&snapshot.buffer_snapshot);
let offset = anchor.to_offset(&snapshot.buffer_snapshot);
// LSP returns a hover result for the end index of ranges that should be hovered, so we need to
// use an inclusive range here to check if we should dismiss the popover
(hover_range.start..=hover_range.end).contains(&offset)
})
.unwrap_or(false)
})
if same_info_hover(editor, &snapshot, anchor)
|| same_diagnostic_hover(editor, &snapshot, anchor)
{
// Hover triggered from same location as last time. Don't show again.
return;
@ -375,6 +361,43 @@ fn show_hover(
editor.hover_state.info_task = Some(task);
}
fn same_info_hover(editor: &Editor, snapshot: &EditorSnapshot, anchor: Anchor) -> bool {
editor
.hover_state
.info_popovers
.iter()
.any(|InfoPopover { symbol_range, .. }| {
symbol_range
.as_text_range()
.map(|range| {
let hover_range = range.to_offset(&snapshot.buffer_snapshot);
let offset = anchor.to_offset(&snapshot.buffer_snapshot);
// LSP returns a hover result for the end index of ranges that should be hovered, so we need to
// use an inclusive range here to check if we should dismiss the popover
(hover_range.start..=hover_range.end).contains(&offset)
})
.unwrap_or(false)
})
}
fn same_diagnostic_hover(editor: &Editor, snapshot: &EditorSnapshot, anchor: Anchor) -> bool {
editor
.hover_state
.diagnostic_popover
.as_ref()
.map(|diagnostic| {
let hover_range = diagnostic
.local_diagnostic
.range
.to_offset(&snapshot.buffer_snapshot);
let offset = anchor.to_offset(&snapshot.buffer_snapshot);
// Here we do basically the same as in `same_info_hover`, see comment there for an explanation
(hover_range.start..=hover_range.end).contains(&offset)
})
.unwrap_or(false)
}
async fn parse_blocks(
blocks: &[HoverBlock],
language_registry: &Arc<LanguageRegistry>,