Add an include/exclude warnings toggle in project diagnostics

This commit is contained in:
Antonio Scandurra 2023-09-27 17:47:19 -06:00
parent ece4875973
commit f603d682cd
3 changed files with 143 additions and 3 deletions

View file

@ -1,4 +1,5 @@
pub mod items;
mod toolbar_controls;
use anyhow::Result;
use collections::{BTreeSet, HashSet};
@ -30,18 +31,20 @@ use std::{
sync::Arc,
};
use theme::ThemeSettings;
pub use toolbar_controls::ToolbarControls;
use util::TryFutureExt;
use workspace::{
item::{BreadcrumbText, Item, ItemEvent, ItemHandle},
ItemNavHistory, Pane, PaneBackdrop, ToolbarItemLocation, Workspace,
};
actions!(diagnostics, [Deploy]);
actions!(diagnostics, [Deploy, ToggleWarnings]);
const CONTEXT_LINE_COUNT: u32 = 1;
pub fn init(cx: &mut AppContext) {
cx.add_action(ProjectDiagnosticsEditor::deploy);
cx.add_action(ProjectDiagnosticsEditor::toggle_warnings);
items::init(cx);
}
@ -55,6 +58,7 @@ struct ProjectDiagnosticsEditor {
excerpts: ModelHandle<MultiBuffer>,
path_states: Vec<PathState>,
paths_to_update: BTreeSet<(ProjectPath, LanguageServerId)>,
include_warnings: bool,
}
struct PathState {
@ -187,6 +191,7 @@ impl ProjectDiagnosticsEditor {
editor,
path_states: Default::default(),
paths_to_update,
include_warnings: true,
};
this.update_excerpts(None, cx);
this
@ -204,6 +209,18 @@ impl ProjectDiagnosticsEditor {
}
}
fn toggle_warnings(&mut self, _: &ToggleWarnings, cx: &mut ViewContext<Self>) {
self.include_warnings = !self.include_warnings;
self.paths_to_update = self
.project
.read(cx)
.diagnostic_summaries(cx)
.map(|(path, server_id, _)| (path, server_id))
.collect();
self.update_excerpts(None, cx);
cx.notify();
}
fn update_excerpts(
&mut self,
language_server_id: Option<LanguageServerId>,
@ -277,14 +294,18 @@ impl ProjectDiagnosticsEditor {
let mut blocks_to_add = Vec::new();
let mut blocks_to_remove = HashSet::default();
let mut first_excerpt_id = None;
let max_severity = if self.include_warnings {
DiagnosticSeverity::WARNING
} else {
DiagnosticSeverity::ERROR
};
let excerpts_snapshot = self.excerpts.update(cx, |excerpts, excerpts_cx| {
let mut old_groups = path_state.diagnostic_groups.iter().enumerate().peekable();
let mut new_groups = snapshot
.diagnostic_groups(language_server_id)
.into_iter()
.filter(|(_, group)| {
group.entries[group.primary_ix].diagnostic.severity
<= DiagnosticSeverity::WARNING
group.entries[group.primary_ix].diagnostic.severity <= max_severity
})
.peekable();
loop {

View file

@ -0,0 +1,115 @@
use crate::{ProjectDiagnosticsEditor, ToggleWarnings};
use gpui::{
elements::*,
platform::{CursorStyle, MouseButton},
Action, Entity, EventContext, View, ViewContext, WeakViewHandle,
};
use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView};
pub struct ToolbarControls {
editor: Option<WeakViewHandle<ProjectDiagnosticsEditor>>,
}
impl Entity for ToolbarControls {
type Event = ();
}
impl View for ToolbarControls {
fn ui_name() -> &'static str {
"ToolbarControls"
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
let include_warnings = self
.editor
.as_ref()
.and_then(|editor| editor.upgrade(cx))
.map(|editor| editor.read(cx).include_warnings)
.unwrap_or(false);
let tooltip = if include_warnings {
"Exclude Warnings".into()
} else {
"Include Warnings".into()
};
Flex::row()
.with_child(render_toggle_button(
0,
"icons/warning.svg",
include_warnings,
(tooltip, Some(Box::new(ToggleWarnings))),
cx,
move |this, cx| {
if let Some(editor) = this.editor.and_then(|editor| editor.upgrade(cx)) {
editor.update(cx, |editor, cx| {
editor.toggle_warnings(&Default::default(), cx)
});
}
},
))
.into_any()
}
}
impl ToolbarItemView for ToolbarControls {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
_: &mut ViewContext<Self>,
) -> ToolbarItemLocation {
if let Some(pane_item) = active_pane_item.as_ref() {
if let Some(editor) = pane_item.downcast::<ProjectDiagnosticsEditor>() {
self.editor = Some(editor.downgrade());
ToolbarItemLocation::PrimaryRight { flex: None }
} else {
ToolbarItemLocation::Hidden
}
} else {
ToolbarItemLocation::Hidden
}
}
}
impl ToolbarControls {
pub fn new() -> Self {
ToolbarControls { editor: None }
}
}
fn render_toggle_button<
F: 'static + Fn(&mut ToolbarControls, &mut EventContext<ToolbarControls>),
>(
index: usize,
icon: &'static str,
toggled: bool,
tooltip: (String, Option<Box<dyn Action>>),
cx: &mut ViewContext<ToolbarControls>,
on_click: F,
) -> AnyElement<ToolbarControls> {
enum Button {}
let theme = theme::current(cx);
let (tooltip_text, action) = tooltip;
MouseEventHandler::new::<Button, _>(index, cx, |mouse_state, _| {
let style = theme
.workspace
.toolbar
.toggleable_tool
.in_state(toggled)
.style_for(mouse_state);
Svg::new(icon)
.with_color(style.color)
.constrained()
.with_width(style.icon_width)
.aligned()
.constrained()
.with_width(style.button_width)
.with_height(style.button_width)
.contained()
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, view, cx| on_click(view, cx))
.with_tooltip::<Button>(index, tooltip_text, action, theme.tooltip.clone(), cx)
.into_any_named("quick action bar button")
}

View file

@ -275,6 +275,10 @@ pub fn initialize_workspace(
QuickActionBar::new(buffer_search_bar, workspace)
});
toolbar.add_item(quick_action_bar, cx);
let diagnostic_editor_controls = cx.add_view(|_| {
diagnostics::ToolbarControls::new()
});
toolbar.add_item(diagnostic_editor_controls, cx);
let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
toolbar.add_item(project_search_bar, cx);
let submit_feedback_button =