Show diagnostics in scrollbar (#7175)
This PR implements support for displaying diagnostics in the scrollbar, similar to what is already done for search results, symbols, git diff, ... For example, changing a field name (`text`) without changing the references looks like this in `buffer.rs` (note the red lines in the scrollbar):  As you can see, the errors, warnings, ... are displayed in the scroll bar, which helps to identify possible problems with the current file. Relevant issues: #4866, #6819 Release Notes: - Added diagnostic indicators to the scrollbar
This commit is contained in:
parent
2940a0ebd8
commit
ce4c15dca6
5 changed files with 81 additions and 1 deletions
|
@ -127,7 +127,9 @@
|
||||||
// Whether to show selections in the scrollbar.
|
// Whether to show selections in the scrollbar.
|
||||||
"selections": true,
|
"selections": true,
|
||||||
// Whether to show symbols selections in the scrollbar.
|
// Whether to show symbols selections in the scrollbar.
|
||||||
"symbols_selections": true
|
"symbols_selections": true,
|
||||||
|
// Whether to show diagnostic indicators in the scrollbar.
|
||||||
|
"diagnostics": true
|
||||||
},
|
},
|
||||||
"relative_line_numbers": false,
|
"relative_line_numbers": false,
|
||||||
// When to populate a new search's query based on the text under the cursor.
|
// When to populate a new search's query based on the text under the cursor.
|
||||||
|
|
|
@ -34,6 +34,7 @@ pub struct Scrollbar {
|
||||||
pub git_diff: bool,
|
pub git_diff: bool,
|
||||||
pub selections: bool,
|
pub selections: bool,
|
||||||
pub symbols_selections: bool,
|
pub symbols_selections: bool,
|
||||||
|
pub diagnostics: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// When to show the scrollbar in the editor.
|
/// When to show the scrollbar in the editor.
|
||||||
|
@ -122,6 +123,10 @@ pub struct ScrollbarContent {
|
||||||
///
|
///
|
||||||
/// Default: true
|
/// Default: true
|
||||||
pub symbols_selections: Option<bool>,
|
pub symbols_selections: Option<bool>,
|
||||||
|
/// Whether to show diagnostic indicators in the scrollbar.
|
||||||
|
///
|
||||||
|
/// Default: true
|
||||||
|
pub diagnostics: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings for EditorSettings {
|
impl Settings for EditorSettings {
|
||||||
|
|
|
@ -35,6 +35,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use language::language_settings::ShowWhitespaceSetting;
|
use language::language_settings::ShowWhitespaceSetting;
|
||||||
|
use lsp::DiagnosticSeverity;
|
||||||
use multi_buffer::Anchor;
|
use multi_buffer::Anchor;
|
||||||
use project::{
|
use project::{
|
||||||
project_settings::{GitGutterSetting, ProjectSettings},
|
project_settings::{GitGutterSetting, ProjectSettings},
|
||||||
|
@ -1477,6 +1478,64 @@ impl EditorElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if layout.is_singleton && scrollbar_settings.diagnostics {
|
||||||
|
let max_point = layout
|
||||||
|
.position_map
|
||||||
|
.snapshot
|
||||||
|
.display_snapshot
|
||||||
|
.buffer_snapshot
|
||||||
|
.max_point();
|
||||||
|
|
||||||
|
let diagnostics = layout
|
||||||
|
.position_map
|
||||||
|
.snapshot
|
||||||
|
.buffer_snapshot
|
||||||
|
.diagnostics_in_range::<_, Point>(Point::zero()..max_point, false)
|
||||||
|
// We want to sort by severity, in order to paint the most severe diagnostics last.
|
||||||
|
.sorted_by_key(|diagnostic| std::cmp::Reverse(diagnostic.diagnostic.severity));
|
||||||
|
|
||||||
|
for diagnostic in diagnostics {
|
||||||
|
let start_display = diagnostic
|
||||||
|
.range
|
||||||
|
.start
|
||||||
|
.to_display_point(&layout.position_map.snapshot.display_snapshot);
|
||||||
|
let end_display = diagnostic
|
||||||
|
.range
|
||||||
|
.end
|
||||||
|
.to_display_point(&layout.position_map.snapshot.display_snapshot);
|
||||||
|
let start_y = y_for_row(start_display.row() as f32);
|
||||||
|
let mut end_y = if diagnostic.range.start == diagnostic.range.end {
|
||||||
|
y_for_row((end_display.row() + 1) as f32)
|
||||||
|
} else {
|
||||||
|
y_for_row((end_display.row()) as f32)
|
||||||
|
};
|
||||||
|
|
||||||
|
if end_y - start_y < px(1.) {
|
||||||
|
end_y = start_y + px(1.);
|
||||||
|
}
|
||||||
|
let bounds = Bounds::from_corners(point(left, start_y), point(right, end_y));
|
||||||
|
|
||||||
|
let color = match diagnostic.diagnostic.severity {
|
||||||
|
DiagnosticSeverity::ERROR => cx.theme().status().error,
|
||||||
|
DiagnosticSeverity::WARNING => cx.theme().status().warning,
|
||||||
|
DiagnosticSeverity::INFORMATION => cx.theme().status().info,
|
||||||
|
_ => cx.theme().status().hint,
|
||||||
|
};
|
||||||
|
cx.paint_quad(quad(
|
||||||
|
bounds,
|
||||||
|
Corners::default(),
|
||||||
|
color,
|
||||||
|
Edges {
|
||||||
|
top: Pixels::ZERO,
|
||||||
|
right: px(1.),
|
||||||
|
bottom: Pixels::ZERO,
|
||||||
|
left: px(1.),
|
||||||
|
},
|
||||||
|
cx.theme().colors().scrollbar_thumb_border,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cx.paint_quad(quad(
|
cx.paint_quad(quad(
|
||||||
thumb_bounds,
|
thumb_bounds,
|
||||||
Corners::default(),
|
Corners::default(),
|
||||||
|
@ -2106,6 +2165,9 @@ impl EditorElement {
|
||||||
// Symbols Selections
|
// Symbols Selections
|
||||||
(is_singleton && scrollbar_settings.symbols_selections && (editor.has_background_highlights::<DocumentHighlightRead>() || editor.has_background_highlights::<DocumentHighlightWrite>()))
|
(is_singleton && scrollbar_settings.symbols_selections && (editor.has_background_highlights::<DocumentHighlightRead>() || editor.has_background_highlights::<DocumentHighlightWrite>()))
|
||||||
||
|
||
|
||||||
|
// Diagnostics
|
||||||
|
(is_singleton && scrollbar_settings.diagnostics && snapshot.buffer_snapshot.has_diagnostics())
|
||||||
|
||
|
||||||
// Scrollmanager
|
// Scrollmanager
|
||||||
editor.scroll_manager.scrollbars_visible()
|
editor.scroll_manager.scrollbars_visible()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2993,6 +2993,11 @@ impl BufferSnapshot {
|
||||||
self.git_diff.hunks_intersecting_range_rev(range, self)
|
self.git_diff.hunks_intersecting_range_rev(range, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns if the buffer contains any diagnostics.
|
||||||
|
pub fn has_diagnostics(&self) -> bool {
|
||||||
|
!self.diagnostics.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns all the diagnostics intersecting the given range.
|
/// Returns all the diagnostics intersecting the given range.
|
||||||
pub fn diagnostics_in_range<'a, T, O>(
|
pub fn diagnostics_in_range<'a, T, O>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
|
|
@ -3052,6 +3052,12 @@ impl MultiBufferSnapshot {
|
||||||
self.has_conflict
|
self.has_conflict
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_diagnostics(&self) -> bool {
|
||||||
|
self.excerpts
|
||||||
|
.iter()
|
||||||
|
.any(|excerpt| excerpt.buffer.has_diagnostics())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn diagnostic_group<'a, O>(
|
pub fn diagnostic_group<'a, O>(
|
||||||
&'a self,
|
&'a self,
|
||||||
group_id: usize,
|
group_id: usize,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue