diff --git a/crates/diagnostics2/src/diagnostics.rs b/crates/diagnostics2/src/diagnostics.rs index d9a417b60a..f684a279fe 100644 --- a/crates/diagnostics2/src/diagnostics.rs +++ b/crates/diagnostics2/src/diagnostics.rs @@ -14,8 +14,8 @@ use editor::{ use futures::future::try_join_all; use gpui::{ actions, div, AnyElement, AnyView, AppContext, Component, Context, Div, EventEmitter, - FocusHandle, Model, ParentComponent, Render, SharedString, Styled, Subscription, Task, View, - ViewContext, VisualContext, WeakView, + FocusHandle, InteractiveComponent, Model, ParentComponent, Render, SharedString, Styled, + Subscription, Task, View, ViewContext, VisualContext, WeakView, }; use language::{ Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, @@ -27,7 +27,6 @@ use project_diagnostics_settings::ProjectDiagnosticsSettings; use settings::Settings; use std::{ any::{Any, TypeId}, - borrow::Cow, cmp::Ordering, mem, ops::Range, @@ -52,7 +51,6 @@ pub fn init(cx: &mut AppContext) { // todo!() // cx.add_action(ProjectDiagnosticsEditor::deploy); // cx.add_action(ProjectDiagnosticsEditor::toggle_warnings); - // items::init(cx); } struct ProjectDiagnosticsEditor { @@ -101,10 +99,6 @@ impl Render for ProjectDiagnosticsEditor { } // impl View for ProjectDiagnosticsEditor { -// fn ui_name() -> &'static str { -// "ProjectDiagnosticsEditor" -// } - // fn render(&mut self, cx: &mut ViewContext) -> AnyElement { // if self.path_states.is_empty() { // let theme = &theme::current(cx).project_diagnostics; @@ -127,34 +121,6 @@ impl Render for ProjectDiagnosticsEditor { // cx.focus(&self.editor); // } // } - -// fn debug_json(&self, cx: &AppContext) -> serde_json::Value { -// let project = self.project.read(cx); -// json!({ -// "project": json!({ -// "language_servers": project.language_server_statuses().collect::>(), -// "summary": project.diagnostic_summary(cx), -// }), -// "summary": self.summary, -// "paths_to_update": self.paths_to_update.iter().map(|(server_id, paths)| -// (server_id.0, paths.into_iter().map(|path| path.path.to_string_lossy()).collect::>()) -// ).collect::>(), -// "current_diagnostics": self.current_diagnostics.iter().map(|(server_id, paths)| -// (server_id.0, paths.into_iter().map(|path| path.path.to_string_lossy()).collect::>()) -// ).collect::>(), -// "paths_states": self.path_states.iter().map(|state| -// json!({ -// "path": state.path.path.to_string_lossy(), -// "groups": state.diagnostic_groups.iter().map(|group| -// json!({ -// "block_count": group.blocks.len(), -// "excerpt_count": group.excerpts.len(), -// }) -// ).collect::>(), -// }) -// ).collect::>(), -// }) -// } // } impl ProjectDiagnosticsEditor { @@ -224,23 +190,33 @@ impl ProjectDiagnosticsEditor { fn emit_item_event_for_editor_event(event: &EditorEvent, cx: &mut ViewContext) { match event { EditorEvent::Closed => cx.emit(ItemEvent::CloseItem), + EditorEvent::Saved | EditorEvent::TitleChanged => { cx.emit(ItemEvent::UpdateTab); cx.emit(ItemEvent::UpdateBreadcrumbs); } + EditorEvent::Reparsed => { cx.emit(ItemEvent::UpdateBreadcrumbs); } + EditorEvent::SelectionsChanged { local } if *local => { cx.emit(ItemEvent::UpdateBreadcrumbs); } + EditorEvent::DirtyChanged => { cx.emit(ItemEvent::UpdateTab); } + EditorEvent::BufferEdited => { cx.emit(ItemEvent::Edit); cx.emit(ItemEvent::UpdateBreadcrumbs); } + + EditorEvent::ExcerptsAdded { .. } | EditorEvent::ExcerptsRemoved { .. } => { + cx.emit(ItemEvent::Edit); + } + _ => {} } } @@ -793,7 +769,7 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { let (message, highlights) = highlight_diagnostic_message(Vec::new(), &diagnostic.message); Arc::new(move |cx| { let settings = ThemeSettings::get_global(cx); - div().render() + div().id("diagnostic header").render() // let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round(); // let icon = if diagnostic.severity == DiagnosticSeverity::ERROR { // Svg::new("icons/error.svg").with_color(theme.error_diagnostic.message.text.color) @@ -920,7 +896,7 @@ mod tests { display_map::{BlockContext, TransformBlock}, DisplayPoint, }; - use gpui::{px, TestAppContext, WindowContext}; + use gpui::{px, TestAppContext, VisualTestContext, WindowContext}; use language::{Diagnostic, DiagnosticEntry, DiagnosticSeverity, PointUtf16, Unclipped}; use project::FakeFs; use serde_json::json; @@ -961,7 +937,8 @@ mod tests { let language_server_id = LanguageServerId(0); let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); - let workspace = window.root(cx); + let cx = &mut VisualTestContext::from_window(*window, cx); + let workspace = window.root(cx).unwrap(); // Create some diagnostics project.update(cx, |project, cx| { @@ -1355,7 +1332,8 @@ mod tests { let server_id_2 = LanguageServerId(101); let project = Project::test(fs.clone(), ["/test".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); - let workspace = window.root(cx); + let cx = &mut VisualTestContext::from_window(*window, cx); + let workspace = window.root(cx).unwrap(); let view = window.build_view(cx, |cx| { ProjectDiagnosticsEditor::new(project.clone(), workspace.downgrade(), cx) @@ -1602,7 +1580,8 @@ mod tests { fn init_test(cx: &mut TestAppContext) { cx.update(|cx| { - cx.set_global(SettingsStore::test(cx)); + let settings = SettingsStore::test(cx); + cx.set_global(settings); theme::init(cx); language::init(cx); client::init_settings(cx); @@ -1629,10 +1608,11 @@ mod tests { line_height: px(0.), em_width: px(0.), block_id: ix, + editor_style: &editor::EditorStyle::default(), }) .element_id()? .try_into() - .expect("All blocks must have string ID"), + .ok()?, TransformBlock::ExcerptHeader { starts_new_buffer, .. diff --git a/crates/diagnostics2/src/items.rs b/crates/diagnostics2/src/items.rs index 2353267303..33e3a52691 100644 --- a/crates/diagnostics2/src/items.rs +++ b/crates/diagnostics2/src/items.rs @@ -91,7 +91,6 @@ impl DiagnosticIndicator { } } -// todo: is this nessesary anymore? impl EventEmitter for DiagnosticIndicator {} // impl View for DiagnosticIndicator { diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 65adada01e..a35eda0725 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -585,7 +585,7 @@ pub enum SoftWrap { Column(u32), } -#[derive(Clone)] +#[derive(Clone, Default)] pub struct EditorStyle { pub background: Hsla, pub local_player: PlayerColor, diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 0e4fb35362..1b4507d336 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -20,10 +20,10 @@ use collections::{BTreeMap, HashMap}; use gpui::{ div, point, px, relative, size, transparent_black, Action, AnyElement, AvailableSpace, BorrowWindow, Bounds, Component, ContentMask, Corners, DispatchPhase, Edges, Element, - ElementId, ElementInputHandler, Entity, EntityId, Hsla, - InteractiveComponent, Line, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, - ParentComponent, Pixels, ScrollWheelEvent, Size, StatefulInteractiveComponent, Style, Styled, - TextRun, TextStyle, View, ViewContext, WindowContext, + ElementId, ElementInputHandler, Entity, EntityId, Hsla, InteractiveComponent, Line, + MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentComponent, Pixels, + ScrollWheelEvent, Size, StatefulInteractiveComponent, Style, Styled, TextRun, TextStyle, View, + ViewContext, WindowContext, }; use itertools::Itertools; use language::language_settings::ShowWhitespaceSetting; @@ -1977,6 +1977,7 @@ impl EditorElement { TransformBlock::ExcerptHeader { .. } => false, TransformBlock::Custom(block) => block.style() == BlockStyle::Fixed, }); + let mut render_block = |block: &TransformBlock, available_space: Size, block_id: usize, @@ -2010,6 +2011,7 @@ impl EditorElement { editor_style: &self.style, }) } + TransformBlock::ExcerptHeader { buffer, range, diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index 50c409c0f2..405a835663 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -377,6 +377,32 @@ impl Model { } } +impl View { + pub fn next_notification(&self, cx: &TestAppContext) -> impl Future { + use postage::prelude::{Sink as _, Stream as _}; + + let (mut tx, mut rx) = postage::mpsc::channel(1); + let mut cx = cx.app.app.borrow_mut(); + let subscription = cx.observe(self, move |_, _| { + tx.try_send(()).ok(); + }); + + let duration = if std::env::var("CI").is_ok() { + Duration::from_secs(5) + } else { + Duration::from_secs(1) + }; + + async move { + let notification = crate::util::timeout(duration, rx.recv()) + .await + .expect("next notification timed out"); + drop(subscription); + notification.expect("model dropped while test was waiting for its next notification") + } + } +} + impl View { pub fn condition( &self, diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 6d0d97029d..82713094a7 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -2,14 +2,14 @@ use crate::{ key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, - EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData, - InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model, ModelContext, - Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Path, - Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, - PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, - RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style, SubscriberSet, - Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, VisualContext, - WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, + EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, + ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, LayoutId, Model, + ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseDownEvent, MouseMoveEvent, + MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, + PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, + RenderImageParams, RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, + Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, + VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, }; use anyhow::{anyhow, Context as _, Result}; use collections::HashMap; @@ -2347,6 +2347,17 @@ impl WindowHandle { } } + pub fn root(&self, cx: &mut C) -> Result> + where + C: Context, + { + Flatten::flatten(cx.update_window(self.any_handle, |root_view, _| { + root_view + .downcast::() + .map_err(|_| anyhow!("the type of the window's root view has changed")) + })) + } + pub fn update( &self, cx: &mut C, diff --git a/crates/theme2/src/styles/players.rs b/crates/theme2/src/styles/players.rs index dfb0a6ff4e..b8a983ba51 100644 --- a/crates/theme2/src/styles/players.rs +++ b/crates/theme2/src/styles/players.rs @@ -1,6 +1,6 @@ use gpui::Hsla; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct PlayerColor { pub cursor: Hsla, pub background: Hsla, diff --git a/crates/theme2/src/theme2.rs b/crates/theme2/src/theme2.rs index b6790b5a6f..d6cc974e5e 100644 --- a/crates/theme2/src/theme2.rs +++ b/crates/theme2/src/theme2.rs @@ -113,7 +113,7 @@ impl Theme { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct DiagnosticStyle { pub error: Hsla, pub warning: Hsla,