Render diagnostics view and such a bit more
This commit is contained in:
parent
c6d22af416
commit
967ef9d414
9 changed files with 100 additions and 127 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -11474,6 +11474,7 @@ dependencies = [
|
||||||
"copilot2",
|
"copilot2",
|
||||||
"ctor",
|
"ctor",
|
||||||
"db2",
|
"db2",
|
||||||
|
"diagnostics2",
|
||||||
"editor2",
|
"editor2",
|
||||||
"env_logger 0.9.3",
|
"env_logger 0.9.3",
|
||||||
"feature_flags2",
|
"feature_flags2",
|
||||||
|
|
|
@ -116,6 +116,7 @@ impl Clone for Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hit count for each command in the palette.
|
/// Hit count for each command in the palette.
|
||||||
/// We only account for commands triggered directly via command palette and not by e.g. keystrokes because
|
/// We only account for commands triggered directly via command palette and not by e.g. keystrokes because
|
||||||
/// if an user already knows a keystroke for a command, they are unlikely to use a command palette to look for it.
|
/// if an user already knows a keystroke for a command, they are unlikely to use a command palette to look for it.
|
||||||
|
|
|
@ -14,8 +14,9 @@ use editor::{
|
||||||
use futures::future::try_join_all;
|
use futures::future::try_join_all;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, AnyElement, AnyView, AppContext, Component, Context, Div, EventEmitter,
|
actions, div, AnyElement, AnyView, AppContext, Component, Context, Div, EventEmitter,
|
||||||
FocusHandle, InteractiveComponent, Model, ParentComponent, Render, SharedString, Styled,
|
FocusEvent, FocusHandle, Focusable, FocusableComponent, InteractiveComponent, Model,
|
||||||
Subscription, Task, View, ViewContext, VisualContext, WeakView,
|
ParentComponent, Render, SharedString, Styled, Subscription, Task, View, ViewContext,
|
||||||
|
VisualContext, WeakView,
|
||||||
};
|
};
|
||||||
use language::{
|
use language::{
|
||||||
Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection,
|
Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection,
|
||||||
|
@ -48,9 +49,8 @@ const CONTEXT_LINE_COUNT: u32 = 1;
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
ProjectDiagnosticsSettings::register(cx);
|
ProjectDiagnosticsSettings::register(cx);
|
||||||
// todo!()
|
cx.observe_new_views(ProjectDiagnosticsEditor::register)
|
||||||
// cx.add_action(ProjectDiagnosticsEditor::deploy);
|
.detach();
|
||||||
// cx.add_action(ProjectDiagnosticsEditor::toggle_warnings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProjectDiagnosticsEditor {
|
struct ProjectDiagnosticsEditor {
|
||||||
|
@ -91,39 +91,34 @@ struct DiagnosticGroupState {
|
||||||
impl EventEmitter<ItemEvent> for ProjectDiagnosticsEditor {}
|
impl EventEmitter<ItemEvent> for ProjectDiagnosticsEditor {}
|
||||||
|
|
||||||
impl Render for ProjectDiagnosticsEditor {
|
impl Render for ProjectDiagnosticsEditor {
|
||||||
type Element = Div<Self>;
|
type Element = Focusable<Self, Div<Self>>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div().size_full().bg(gpui::red())
|
let child = if self.path_states.is_empty() {
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_center()
|
||||||
|
.size_full()
|
||||||
|
.child(Label::new("No problems in workspace"))
|
||||||
|
} else {
|
||||||
|
div().size_full().child(self.editor.clone())
|
||||||
|
};
|
||||||
|
|
||||||
|
div()
|
||||||
|
.track_focus(&self.focus_handle)
|
||||||
|
.size_full()
|
||||||
|
.on_focus_in(Self::focus_in)
|
||||||
|
.on_action(Self::toggle_warnings)
|
||||||
|
.child(child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl View for ProjectDiagnosticsEditor {
|
|
||||||
// fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
|
||||||
// if self.path_states.is_empty() {
|
|
||||||
// let theme = &theme::current(cx).project_diagnostics;
|
|
||||||
// PaneBackdrop::new(
|
|
||||||
// cx.view_id(),
|
|
||||||
// Label::new("No problems in workspace", theme.empty_message.clone())
|
|
||||||
// .aligned()
|
|
||||||
// .contained()
|
|
||||||
// .with_style(theme.container)
|
|
||||||
// .into_any(),
|
|
||||||
// )
|
|
||||||
// .into_any()
|
|
||||||
// } else {
|
|
||||||
// ChildView::new(&self.editor, cx).into_any()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn focus_in(&mut self, _: AnyView, cx: &mut ViewContext<Self>) {
|
|
||||||
// if cx.is_self_focused() && !self.path_states.is_empty() {
|
|
||||||
// cx.focus(&self.editor);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
impl ProjectDiagnosticsEditor {
|
impl ProjectDiagnosticsEditor {
|
||||||
|
fn register(workspace: &mut Workspace, _: &mut ViewContext<Workspace>) {
|
||||||
|
workspace.register_action(Self::deploy);
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
project_handle: Model<Project>,
|
project_handle: Model<Project>,
|
||||||
workspace: WeakView<Workspace>,
|
workspace: WeakView<Workspace>,
|
||||||
|
@ -240,6 +235,12 @@ impl ProjectDiagnosticsEditor {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_in(&mut self, _: &FocusEvent, cx: &mut ViewContext<Self>) {
|
||||||
|
if self.focus_handle.is_focused(cx) && !self.path_states.is_empty() {
|
||||||
|
self.editor.focus_handle(cx).focus(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn update_excerpts(
|
fn update_excerpts(
|
||||||
&mut self,
|
&mut self,
|
||||||
language_server_id: Option<LanguageServerId>,
|
language_server_id: Option<LanguageServerId>,
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
use collections::HashSet;
|
use collections::HashSet;
|
||||||
use editor::{Editor, GoToDiagnostic};
|
use editor::{Editor, GoToDiagnostic};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, serde_json, AppContext, CursorStyle, Div, Entity, EventEmitter, MouseButton, Render,
|
div, serde_json, svg, AppContext, CursorStyle, Div, Entity, EventEmitter, InteractiveComponent,
|
||||||
Styled, Subscription, View, ViewContext, WeakView,
|
MouseButton, ParentComponent, Render, Stateful, Styled, Subscription, Svg, View, ViewContext,
|
||||||
|
WeakView,
|
||||||
};
|
};
|
||||||
use language::Diagnostic;
|
use language::Diagnostic;
|
||||||
use lsp::LanguageServerId;
|
use lsp::LanguageServerId;
|
||||||
|
use theme::ActiveTheme;
|
||||||
|
use ui::{Icon, IconElement, Label, TextColor};
|
||||||
use workspace::{item::ItemHandle, StatusItemView, ToolbarItemEvent, Workspace};
|
use workspace::{item::ItemHandle, StatusItemView, ToolbarItemEvent, Workspace};
|
||||||
|
|
||||||
use crate::ProjectDiagnosticsEditor;
|
use crate::ProjectDiagnosticsEditor;
|
||||||
|
|
||||||
// todo!()
|
|
||||||
// pub fn init(cx: &mut AppContext) {
|
|
||||||
// cx.add_action(DiagnosticIndicator::go_to_next_diagnostic);
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub struct DiagnosticIndicator {
|
pub struct DiagnosticIndicator {
|
||||||
summary: project::DiagnosticSummary,
|
summary: project::DiagnosticSummary,
|
||||||
active_editor: Option<WeakView<Editor>>,
|
active_editor: Option<WeakView<Editor>>,
|
||||||
|
@ -25,10 +23,33 @@ pub struct DiagnosticIndicator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for DiagnosticIndicator {
|
impl Render for DiagnosticIndicator {
|
||||||
type Element = Div<Self>;
|
type Element = Stateful<Self, Div<Self>>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div().size_full().bg(gpui::red())
|
let mut summary_row = div().flex().flex_row().size_full();
|
||||||
|
|
||||||
|
if self.summary.error_count > 0 {
|
||||||
|
summary_row =
|
||||||
|
summary_row.child(IconElement::new(Icon::XCircle).color(TextColor::Error));
|
||||||
|
summary_row = summary_row.child(Label::new(self.summary.error_count.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.summary.warning_count > 0 {
|
||||||
|
summary_row = summary_row
|
||||||
|
.child(IconElement::new(Icon::ExclamationTriangle).color(TextColor::Warning));
|
||||||
|
summary_row = summary_row.child(Label::new(self.summary.warning_count.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.summary.error_count == 0 && self.summary.warning_count == 0 {
|
||||||
|
summary_row =
|
||||||
|
summary_row.child(IconElement::new(Icon::Check).color(TextColor::Success));
|
||||||
|
}
|
||||||
|
|
||||||
|
div()
|
||||||
|
.id(cx.entity_id())
|
||||||
|
.on_action(Self::go_to_next_diagnostic)
|
||||||
|
.size_full()
|
||||||
|
.child(summary_row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,19 +61,23 @@ impl DiagnosticIndicator {
|
||||||
this.in_progress_checks.insert(*language_server_id);
|
this.in_progress_checks.insert(*language_server_id);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
project::Event::DiskBasedDiagnosticsFinished { language_server_id }
|
project::Event::DiskBasedDiagnosticsFinished { language_server_id }
|
||||||
| project::Event::LanguageServerRemoved(language_server_id) => {
|
| project::Event::LanguageServerRemoved(language_server_id) => {
|
||||||
this.summary = project.read(cx).diagnostic_summary(cx);
|
this.summary = project.read(cx).diagnostic_summary(cx);
|
||||||
this.in_progress_checks.remove(language_server_id);
|
this.in_progress_checks.remove(language_server_id);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
project::Event::DiagnosticsUpdated { .. } => {
|
project::Event::DiagnosticsUpdated { .. } => {
|
||||||
this.summary = project.read(cx).diagnostic_summary(cx);
|
this.summary = project.read(cx).diagnostic_summary(cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
summary: project.read(cx).diagnostic_summary(cx),
|
summary: project.read(cx).diagnostic_summary(cx),
|
||||||
in_progress_checks: project
|
in_progress_checks: project
|
||||||
|
|
|
@ -14,50 +14,35 @@ impl Render for ToolbarControls {
|
||||||
type Element = Div<Self>;
|
type Element = Div<Self>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
div()
|
let include_warnings = self
|
||||||
.h_flex()
|
.editor
|
||||||
.child(IconButton::new("toggle-warnings", Icon::Warning).on_click(|view, cx| todo!()))
|
.as_ref()
|
||||||
|
.and_then(|editor| editor.upgrade())
|
||||||
|
.map(|editor| editor.read(cx).include_warnings)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let tooltip = if include_warnings {
|
||||||
|
"Exclude Warnings"
|
||||||
|
} else {
|
||||||
|
"Include Warnings"
|
||||||
|
};
|
||||||
|
|
||||||
|
div().child(
|
||||||
|
IconButton::new("toggle-warnings", Icon::ExclamationTriangle)
|
||||||
|
.tooltip(tooltip)
|
||||||
|
.on_click(|this: &mut Self, cx| {
|
||||||
|
if let Some(editor) = this.editor.as_ref().and_then(|editor| editor.upgrade()) {
|
||||||
|
editor.update(cx, |editor, cx| {
|
||||||
|
editor.toggle_warnings(&Default::default(), cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventEmitter<ToolbarItemEvent> for ToolbarControls {}
|
impl EventEmitter<ToolbarItemEvent> for ToolbarControls {}
|
||||||
|
|
||||||
// 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 {
|
impl ToolbarItemView for ToolbarControls {
|
||||||
fn set_active_pane_item(
|
fn set_active_pane_item(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -82,42 +67,3 @@ impl ToolbarControls {
|
||||||
ToolbarControls { editor: None }
|
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")
|
|
||||||
// }
|
|
||||||
|
|
|
@ -64,7 +64,6 @@ pub enum Icon {
|
||||||
Split,
|
Split,
|
||||||
SplitMessage,
|
SplitMessage,
|
||||||
Terminal,
|
Terminal,
|
||||||
Warning,
|
|
||||||
XCircle,
|
XCircle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +122,6 @@ impl Icon {
|
||||||
Icon::Split => "icons/split.svg",
|
Icon::Split => "icons/split.svg",
|
||||||
Icon::SplitMessage => "icons/split_message.svg",
|
Icon::SplitMessage => "icons/split_message.svg",
|
||||||
Icon::Terminal => "icons/terminal.svg",
|
Icon::Terminal => "icons/terminal.svg",
|
||||||
Icon::Warning => "icons/warning.svg",
|
|
||||||
Icon::XCircle => "icons/error.svg",
|
Icon::XCircle => "icons/error.svg",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ client = { package = "client2", path = "../client2" }
|
||||||
# clock = { path = "../clock" }
|
# clock = { path = "../clock" }
|
||||||
copilot = { package = "copilot2", path = "../copilot2" }
|
copilot = { package = "copilot2", path = "../copilot2" }
|
||||||
# copilot_button = { path = "../copilot_button" }
|
# copilot_button = { path = "../copilot_button" }
|
||||||
# diagnostics = { path = "../diagnostics" }
|
diagnostics = { package = "diagnostics2", path = "../diagnostics2" }
|
||||||
db = { package = "db2", path = "../db2" }
|
db = { package = "db2", path = "../db2" }
|
||||||
editor = { package="editor2", path = "../editor2" }
|
editor = { package="editor2", path = "../editor2" }
|
||||||
# feedback = { path = "../feedback" }
|
# feedback = { path = "../feedback" }
|
||||||
|
|
|
@ -147,6 +147,7 @@ fn main() {
|
||||||
command_palette::init(cx);
|
command_palette::init(cx);
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
editor::init(cx);
|
editor::init(cx);
|
||||||
|
diagnostics::init(cx);
|
||||||
copilot::init(
|
copilot::init(
|
||||||
copilot_language_server_id,
|
copilot_language_server_id,
|
||||||
http.clone(),
|
http.clone(),
|
||||||
|
|
|
@ -314,8 +314,8 @@ pub fn initialize_workspace(
|
||||||
// QuickActionBar::new(buffer_search_bar, workspace)
|
// QuickActionBar::new(buffer_search_bar, workspace)
|
||||||
// });
|
// });
|
||||||
// toolbar.add_item(quick_action_bar, cx);
|
// toolbar.add_item(quick_action_bar, cx);
|
||||||
// let diagnostic_editor_controls =
|
let diagnostic_editor_controls =
|
||||||
// cx.add_view(|_| diagnostics2::ToolbarControls::new());
|
cx.build_view(|_| diagnostics::ToolbarControls::new());
|
||||||
// toolbar.add_item(diagnostic_editor_controls, cx);
|
// toolbar.add_item(diagnostic_editor_controls, cx);
|
||||||
// let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
|
// let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
|
||||||
// toolbar.add_item(project_search_bar, cx);
|
// toolbar.add_item(project_search_bar, cx);
|
||||||
|
@ -347,8 +347,8 @@ pub fn initialize_workspace(
|
||||||
|
|
||||||
// let copilot =
|
// let copilot =
|
||||||
// cx.add_view(|cx| copilot_button::CopilotButton::new(app_state.fs.clone(), cx));
|
// cx.add_view(|cx| copilot_button::CopilotButton::new(app_state.fs.clone(), cx));
|
||||||
// let diagnostic_summary =
|
let diagnostic_summary =
|
||||||
// cx.add_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx));
|
cx.build_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx));
|
||||||
// let activity_indicator = activity_indicator::ActivityIndicator::new(
|
// let activity_indicator = activity_indicator::ActivityIndicator::new(
|
||||||
// workspace,
|
// workspace,
|
||||||
// app_state.languages.clone(),
|
// app_state.languages.clone(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue