diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index 1a6e2da5c7..439d15ec6a 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -11,11 +11,11 @@ use gpui::{ StyleRefinement, Styled, Task, TextStyleRefinement, View, ViewContext, }; use itertools::Itertools; -use language::{Diagnostic, DiagnosticEntry, Language, LanguageRegistry}; +use language::{DiagnosticEntry, Language, LanguageRegistry}; use lsp::DiagnosticSeverity; use markdown::{Markdown, MarkdownStyle}; use multi_buffer::ToOffset; -use project::{HoverBlock, InlayHintLabelPart}; +use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart}; use settings::Settings; use std::rc::Rc; use std::{borrow::Cow, cell::RefCell}; @@ -263,50 +263,14 @@ fn show_hover( delay.await; } - let local_diagnostic = if let Some(invisible) = snapshot + let local_diagnostic = snapshot .buffer_snapshot - .chars_at(anchor) - .next() - .filter(|&c| is_invisible(c)) - { - let after = snapshot.buffer_snapshot.anchor_after( - anchor.to_offset(&snapshot.buffer_snapshot) + invisible.len_utf8(), - ); - Some(DiagnosticEntry { - diagnostic: Diagnostic { - severity: DiagnosticSeverity::HINT, - message: format!("Unicode character U+{:02X}", invisible as u32), - ..Default::default() - }, - range: anchor..after, - }) - } else if let Some(invisible) = snapshot - .buffer_snapshot - .reversed_chars_at(anchor) - .next() - .filter(|&c| is_invisible(c)) - { - let before = snapshot.buffer_snapshot.anchor_before( - anchor.to_offset(&snapshot.buffer_snapshot) - invisible.len_utf8(), - ); - Some(DiagnosticEntry { - diagnostic: Diagnostic { - severity: DiagnosticSeverity::HINT, - message: format!("Unicode character U+{:02X}", invisible as u32), - ..Default::default() - }, - range: before..anchor, - }) - } else { - snapshot - .buffer_snapshot - .diagnostics_in_range(anchor..anchor, false) - // Find the entry with the most specific range - .min_by_key(|entry| { - let range = entry.range.to_offset(&snapshot.buffer_snapshot); - range.end - range.start - }) - }; + .diagnostics_in_range(anchor..anchor, false) + // Find the entry with the most specific range + .min_by_key(|entry| { + let range = entry.range.to_offset(&snapshot.buffer_snapshot); + range.end - range.start + }); let diagnostic_popover = if let Some(local_diagnostic) = local_diagnostic { let text = match local_diagnostic.diagnostic.source { @@ -389,6 +353,31 @@ fn show_hover( this.hover_state.diagnostic_popover = diagnostic_popover; })?; + let invisible_char = if let Some(invisible) = snapshot + .buffer_snapshot + .chars_at(anchor) + .next() + .filter(|&c| is_invisible(c)) + { + let after = snapshot.buffer_snapshot.anchor_after( + anchor.to_offset(&snapshot.buffer_snapshot) + invisible.len_utf8(), + ); + Some((invisible, anchor..after)) + } else if let Some(invisible) = snapshot + .buffer_snapshot + .reversed_chars_at(anchor) + .next() + .filter(|&c| is_invisible(c)) + { + let before = snapshot.buffer_snapshot.anchor_before( + anchor.to_offset(&snapshot.buffer_snapshot) - invisible.len_utf8(), + ); + + Some((invisible, before..anchor)) + } else { + None + }; + let hovers_response = if let Some(hover_request) = hover_request { hover_request.await } else { @@ -396,8 +385,26 @@ fn show_hover( }; let snapshot = this.update(&mut cx, |this, cx| this.snapshot(cx))?; let mut hover_highlights = Vec::with_capacity(hovers_response.len()); - let mut info_popovers = Vec::with_capacity(hovers_response.len()); - let mut info_popover_tasks = Vec::with_capacity(hovers_response.len()); + let mut info_popovers = Vec::with_capacity( + hovers_response.len() + if invisible_char.is_some() { 1 } else { 0 }, + ); + + if let Some((invisible, range)) = invisible_char { + let blocks = vec![HoverBlock { + text: format!("Unicode character U+{:02X}", invisible as u32), + kind: HoverBlockKind::PlainText, + }]; + let parsed_content = parse_blocks(&blocks, &language_registry, None, &mut cx).await; + let scroll_handle = ScrollHandle::new(); + info_popovers.push(InfoPopover { + symbol_range: RangeInEditor::Text(range), + parsed_content, + scrollbar_state: ScrollbarState::new(scroll_handle.clone()), + scroll_handle, + keyboard_grace: Rc::new(RefCell::new(ignore_timeout)), + anchor: Some(anchor), + }) + } for hover_result in hovers_response { // Create symbol range of anchors for highlighting and filtering of future requests. @@ -410,7 +417,6 @@ fn show_hover( let end = snapshot .buffer_snapshot .anchor_in_excerpt(excerpt_id, range.end)?; - Some(start..end) }) .or_else(|| { @@ -428,21 +434,15 @@ fn show_hover( let parsed_content = parse_blocks(&blocks, &language_registry, language, &mut cx).await; let scroll_handle = ScrollHandle::new(); - info_popover_tasks.push(( - range.clone(), - InfoPopover { - symbol_range: RangeInEditor::Text(range), - parsed_content, - scrollbar_state: ScrollbarState::new(scroll_handle.clone()), - scroll_handle, - keyboard_grace: Rc::new(RefCell::new(ignore_timeout)), - anchor: Some(anchor), - }, - )); - } - for (highlight_range, info_popover) in info_popover_tasks { - hover_highlights.push(highlight_range); - info_popovers.push(info_popover); + hover_highlights.push(range.clone()); + info_popovers.push(InfoPopover { + symbol_range: RangeInEditor::Text(range), + parsed_content, + scrollbar_state: ScrollbarState::new(scroll_handle.clone()), + scroll_handle, + keyboard_grace: Rc::new(RefCell::new(ignore_timeout)), + anchor: Some(anchor), + }); } this.update(&mut cx, |editor, cx| { @@ -732,6 +732,7 @@ impl InfoPopover { cx.notify(); self.scroll_handle.set_offset(current); } + fn render_vertical_scrollbar(&self, cx: &mut ViewContext) -> Stateful
{ div() .occlude()