From e6604d1641cf8a12846be02e9be2251aed976714 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 21 Apr 2023 15:57:16 -0600 Subject: [PATCH 01/23] Fix missing actions in the command palette Previously, the workspace view was on the stack when we were computing the available actions, which excluded it. This is a stopgap. We should find a better solution ASAP. --- crates/command_palette/src/command_palette.rs | 16 ++++++++++------ crates/gpui/src/app/window.rs | 5 +++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 07c6de8663..1d9ac62c2c 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -2,7 +2,7 @@ use collections::CommandPaletteFilter; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ actions, elements::*, keymap_matcher::Keystroke, Action, AppContext, Element, MouseState, - ViewContext, + ViewContext, WindowContext, }; use picker::{Picker, PickerDelegate, PickerEvent}; use settings::Settings; @@ -45,15 +45,19 @@ fn toggle_command_palette(_: &mut Workspace, _: &Toggle, cx: &mut ViewContext>) -> Self { + pub fn new(focused_view_id: usize, cx: &mut WindowContext) -> Self { let actions = cx .available_actions(focused_view_id) .filter_map(|(name, action, bindings)| { diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 12dc9a60c5..4a08d07aaa 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -444,6 +444,11 @@ impl<'a> WindowContext<'a> { .map(|action_type| (action_type, depth)), ); } + } else { + log::error!( + "view {} not found when computing available actions", + view_id + ); } } From 23932b7e6c5e8f0dc27e8fd90395194eb1446d7d Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 21 Apr 2023 16:06:07 -0700 Subject: [PATCH 02/23] Fixed non-deterministic test failure and made mouse to cell conversion work correctly --- crates/terminal/src/terminal.rs | 117 +++++++++++++++++--------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index d951633bb3..1498e63aeb 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -31,6 +31,7 @@ use mappings::mouse::{ }; use procinfo::LocalProcessInfo; +use serde::{Deserialize, Serialize}; use settings::{AlternateScroll, Settings, Shell, TerminalBlink}; use util::truncate_and_trailoff; @@ -113,7 +114,7 @@ impl EventListener for ZedListener { } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct TerminalSize { pub cell_width: f32, pub line_height: f32, @@ -441,7 +442,7 @@ impl TerminalBuilder { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Deserialize, Serialize)] pub struct IndexedCell { pub point: Point, pub cell: Cell, @@ -1074,7 +1075,7 @@ impl Terminal { //Hyperlinks if self.selection_phase == SelectionPhase::Ended { - let mouse_cell_index = content_index_for_mouse(position, &self.last_content); + let mouse_cell_index = content_index_for_mouse(position, &self.last_content.size); if let Some(link) = self.last_content.cells[mouse_cell_index].hyperlink() { cx.platform().open_url(link.uri()); } else { @@ -1254,17 +1255,16 @@ fn all_search_matches<'a, T>( RegexIter::new(start, end, AlacDirection::Right, term, regex) } -fn content_index_for_mouse<'a>(pos: Vector2F, content: &'a TerminalContent) -> usize { - let col = min( - (pos.x() / content.size.cell_width()) as usize, - content.size.columns() - 1, - ) as usize; - let line = min( - (pos.y() / content.size.line_height()) as usize, - content.size.screen_lines() - 1, - ) as usize; +fn content_index_for_mouse(pos: Vector2F, size: &TerminalSize) -> usize { + let col = (pos.x() / size.cell_width()).round() as usize; - line * content.size.columns() + col + let clamped_col = min(col, size.columns() - 1); + + let row = (pos.y() / size.line_height()).round() as usize; + + let clamped_row = min(row, size.screen_lines() - 1); + + clamped_row * size.columns() + clamped_col } #[cfg(test)] @@ -1274,17 +1274,19 @@ mod tests { term::cell::Cell, }; use gpui::geometry::vector::vec2f; - use rand::{rngs::ThreadRng, thread_rng, Rng}; + use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng}; use crate::{content_index_for_mouse, IndexedCell, TerminalContent, TerminalSize}; #[test] - fn test_mouse_to_cell() { + fn test_mouse_to_cell_test() { let mut rng = thread_rng(); + const ITERATIONS: usize = 10; + const PRECISION: usize = 1000; - for _ in 0..10 { - let viewport_cells = rng.gen_range(5..50); - let cell_size = rng.gen_range(5.0..20.0); + for _ in 0..ITERATIONS { + let viewport_cells = rng.gen_range(15..20); + let cell_size = rng.gen_range(5 * PRECISION..20 * PRECISION) as f32 / PRECISION as f32; let size = crate::TerminalSize { cell_width: cell_size, @@ -1293,26 +1295,27 @@ mod tests { width: cell_size * (viewport_cells as f32), }; - let (content, cells) = create_terminal_content(size, &mut rng); + let cells = get_cells(size, &mut rng); + let content = convert_cells_to_content(size, &cells); - for i in 0..(viewport_cells - 1) { - let i = i as usize; - for j in 0..(viewport_cells - 1) { - let j = j as usize; - let min_row = i as f32 * cell_size; - let max_row = (i + 1) as f32 * cell_size; - let min_col = j as f32 * cell_size; - let max_col = (j + 1) as f32 * cell_size; + for row in 0..(viewport_cells - 1) { + let row = row as usize; + for col in 0..(viewport_cells - 1) { + let col = col as usize; + + let row_offset = rng.gen_range(0..PRECISION) as f32 / PRECISION as f32; + let col_offset = rng.gen_range(0..PRECISION) as f32 / PRECISION as f32; let mouse_pos = vec2f( - rng.gen_range(min_row..max_row), - rng.gen_range(min_col..max_col), + col as f32 * cell_size + col_offset, + row as f32 * cell_size + row_offset, ); - assert_eq!( - content.cells[content_index_for_mouse(mouse_pos, &content)].c, - cells[j][i] - ); + let content_index = content_index_for_mouse(mouse_pos, &content.size); + let mouse_cell = content.cells[content_index].c; + let real_cell = cells[row][col]; + + assert_eq!(mouse_cell, real_cell); } } } @@ -1329,29 +1332,40 @@ mod tests { width: 100., }; - let (content, cells) = create_terminal_content(size, &mut rng); + let cells = get_cells(size, &mut rng); + let content = convert_cells_to_content(size, &cells); assert_eq!( - content.cells[content_index_for_mouse(vec2f(-10., -10.), &content)].c, + content.cells[content_index_for_mouse(vec2f(-10., -10.), &content.size)].c, cells[0][0] ); assert_eq!( - content.cells[content_index_for_mouse(vec2f(1000., 1000.), &content)].c, + content.cells[content_index_for_mouse(vec2f(1000., 1000.), &content.size)].c, cells[9][9] ); } - fn create_terminal_content( - size: TerminalSize, - rng: &mut ThreadRng, - ) -> (TerminalContent, Vec>) { - let mut ic = Vec::new(); + fn get_cells(size: TerminalSize, rng: &mut ThreadRng) -> Vec> { let mut cells = Vec::new(); - for row in 0..((size.height() / size.line_height()) as usize) { + for _ in 0..((size.height() / size.line_height()) as usize) { let mut row_vec = Vec::new(); - for col in 0..((size.width() / size.cell_width()) as usize) { - let cell_char = rng.gen(); + for _ in 0..((size.width() / size.cell_width()) as usize) { + let cell_char = rng.sample(Alphanumeric) as char; + row_vec.push(cell_char) + } + cells.push(row_vec) + } + + cells + } + + fn convert_cells_to_content(size: TerminalSize, cells: &Vec>) -> TerminalContent { + let mut ic = Vec::new(); + + for row in 0..cells.len() { + for col in 0..cells[row].len() { + let cell_char = cells[row][col]; ic.push(IndexedCell { point: Point::new(Line(row as i32), Column(col)), cell: Cell { @@ -1359,18 +1373,13 @@ mod tests { ..Default::default() }, }); - row_vec.push(cell_char) } - cells.push(row_vec) } - ( - TerminalContent { - cells: ic, - size, - ..Default::default() - }, - cells, - ) + TerminalContent { + cells: ic, + size, + ..Default::default() + } } } From d841c3729b48306af37153065d4afcf887cb6b29 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 21 Apr 2023 16:12:33 -0700 Subject: [PATCH 03/23] Wire through the gutter, rather than implicitly adding it --- crates/terminal_view/src/terminal_element.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index 496dca0e79..93d9aef5c5 100644 --- a/crates/terminal_view/src/terminal_element.rs +++ b/crates/terminal_view/src/terminal_element.rs @@ -46,6 +46,7 @@ pub struct LayoutState { mode: TermMode, display_offset: usize, hyperlink_tooltip: Option>, + gutter: f32, } ///Helper struct for converting data between alacritty's cursor points, and displayed cursor points @@ -572,10 +573,14 @@ impl Drawable for TerminalElement { let text_style = TerminalElement::make_text_style(font_cache, settings); let selection_color = settings.theme.editor.selection.selection; let match_color = settings.theme.search.match_background; + let gutter; let dimensions = { let line_height = text_style.font_size * settings.terminal_line_height(); let cell_width = font_cache.em_advance(text_style.font_id, text_style.font_size); - TerminalSize::new(line_height, cell_width, constraint.max) + gutter = cell_width; + + let size = constraint.max - vec2f(gutter, 0.); + TerminalSize::new(line_height, cell_width, size) }; let search_matches = if let Some(terminal_model) = self.terminal.upgrade(cx) { @@ -714,6 +719,7 @@ impl Drawable for TerminalElement { mode: *mode, display_offset: *display_offset, hyperlink_tooltip, + gutter, }, ) } @@ -733,7 +739,7 @@ impl Drawable for TerminalElement { let clip_bounds = Some(visible_bounds); scene.paint_layer(clip_bounds, |scene| { - let origin = bounds.origin() + vec2f(layout.size.cell_width, 0.); + let origin = bounds.origin() + vec2f(layout.gutter, 0.); // Elements are ephemeral, only at paint time do we know what could be clicked by a mouse self.attach_mouse_handlers(scene, origin, visible_bounds, layout.mode, cx); From 616188c541926080911e04684e159f25c63f2f68 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 21 Apr 2023 17:15:15 -0700 Subject: [PATCH 04/23] Fix a bug where the character under a cursor could not reliably be selected --- crates/terminal/src/terminal.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 1498e63aeb..071aa55cd9 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -665,6 +665,7 @@ impl Terminal { self.last_content.size, term.grid().display_offset(), ); + let side = mouse_side(*position, self.last_content.size); selection.update(point, side); @@ -1025,7 +1026,9 @@ impl Terminal { self.last_content.size, self.last_content.display_offset, ); - let side = mouse_side(position, self.last_content.size); + + // Use .opposite so that selection is inclusive of the cell clicked. + let side = mouse_side(position, self.last_content.size).opposite(); let selection_type = match e.click_count { 0 => return, //This is a release From 733abc9ed2fd685d722fa94635412e4dfd115356 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 21 Apr 2023 17:24:20 -0700 Subject: [PATCH 05/23] Revert previous change --- crates/terminal/src/terminal.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 071aa55cd9..9338253ff5 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -7,7 +7,7 @@ use alacritty_terminal::{ event::{Event as AlacTermEvent, EventListener, Notify, WindowSize}, event_loop::{EventLoop, Msg, Notifier}, grid::{Dimensions, Scroll as AlacScroll}, - index::{Column, Direction as AlacDirection, Line, Point}, + index::{Column, Direction as AlacDirection, Line, Point, Side}, selection::{Selection, SelectionRange, SelectionType}, sync::FairMutex, term::{ @@ -1028,7 +1028,7 @@ impl Terminal { ); // Use .opposite so that selection is inclusive of the cell clicked. - let side = mouse_side(position, self.last_content.size).opposite(); + let side = mouse_side(position, self.last_content.size); let selection_type = match e.click_count { 0 => return, //This is a release From fa7f4974a07176d6b4758831293a3cc5e0e14de0 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 21 Apr 2023 17:26:45 -0700 Subject: [PATCH 06/23] Remove unused import --- crates/terminal/src/terminal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 9338253ff5..25852875c3 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -7,7 +7,7 @@ use alacritty_terminal::{ event::{Event as AlacTermEvent, EventListener, Notify, WindowSize}, event_loop::{EventLoop, Msg, Notifier}, grid::{Dimensions, Scroll as AlacScroll}, - index::{Column, Direction as AlacDirection, Line, Point, Side}, + index::{Column, Direction as AlacDirection, Line, Point}, selection::{Selection, SelectionRange, SelectionType}, sync::FairMutex, term::{ From 455d383d08e0df93f418b49f5823888ff6b70120 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 21 Apr 2023 21:42:23 -0700 Subject: [PATCH 07/23] Change copilot wording to be more explicit --- crates/copilot_button/src/copilot_button.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index da13ce4413..ed1536a098 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -272,7 +272,10 @@ impl CopilotButton { let mut menu_options = Vec::with_capacity(2); menu_options.push(ContextMenuItem::item("Sign In", InitiateSignIn)); - menu_options.push(ContextMenuItem::item("Hide Copilot", HideCopilot)); + menu_options.push(ContextMenuItem::item( + "Disable Copilot Integration", + HideCopilot, + )); self.popup_menu.update(cx, |menu, cx| { menu.show( From c7874cf169826e1af6c825376070c2741f9eb21e Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 24 Apr 2023 09:03:54 -0700 Subject: [PATCH 08/23] Update copilot_button.rs --- crates/copilot_button/src/copilot_button.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index ed1536a098..1d2fc9117d 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -273,7 +273,7 @@ impl CopilotButton { menu_options.push(ContextMenuItem::item("Sign In", InitiateSignIn)); menu_options.push(ContextMenuItem::item( - "Disable Copilot Integration", + "Disable Copilot", HideCopilot, )); From c12e2ac3fb6e103ebbc32a6f72756a6ce091803e Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 24 Apr 2023 09:25:04 -0700 Subject: [PATCH 09/23] fix formatting --- crates/copilot_button/src/copilot_button.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index 1d2fc9117d..c8bfcc7550 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -272,10 +272,7 @@ impl CopilotButton { let mut menu_options = Vec::with_capacity(2); menu_options.push(ContextMenuItem::item("Sign In", InitiateSignIn)); - menu_options.push(ContextMenuItem::item( - "Disable Copilot", - HideCopilot, - )); + menu_options.push(ContextMenuItem::item("Disable Copilot", HideCopilot)); self.popup_menu.update(cx, |menu, cx| { menu.show( From abdccf73939e46dca6d73801bb6437317f519123 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 20 Apr 2023 17:47:18 -0700 Subject: [PATCH 10/23] Use a workspace dependency for the futures crate --- Cargo.toml | 1 + crates/activity_indicator/Cargo.toml | 2 +- crates/call/Cargo.toml | 2 +- crates/client/Cargo.toml | 2 +- crates/collab/Cargo.toml | 2 +- crates/collab_ui/Cargo.toml | 2 +- crates/copilot/Cargo.toml | 2 +- crates/copilot_button/Cargo.toml | 2 +- crates/editor/Cargo.toml | 2 +- crates/feedback/Cargo.toml | 2 +- crates/fs/Cargo.toml | 2 +- crates/git/Cargo.toml | 2 +- crates/gpui/Cargo.toml | 2 +- crates/language/Cargo.toml | 2 +- crates/live_kit_client/Cargo.toml | 4 ++-- crates/live_kit_server/Cargo.toml | 2 +- crates/lsp/Cargo.toml | 2 +- crates/node_runtime/Cargo.toml | 2 +- crates/project/Cargo.toml | 2 +- crates/project_panel/Cargo.toml | 2 +- crates/project_symbols/Cargo.toml | 2 +- crates/rpc/Cargo.toml | 2 +- crates/search/Cargo.toml | 2 +- crates/settings/Cargo.toml | 2 +- crates/sqlez/Cargo.toml | 4 ++-- crates/terminal/Cargo.toml | 2 +- crates/terminal_view/Cargo.toml | 2 +- crates/util/Cargo.toml | 2 +- crates/workspace/Cargo.toml | 2 +- crates/zed/Cargo.toml | 2 +- 30 files changed, 32 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1275571668..1c325fbb8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,7 @@ serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] } rand = { version = "0.8" } postage = { version = "0.5", features = ["futures-traits"] } smallvec = { version = "1.6", features = ["union"] } +futures = { version = "0.3" } [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "c51896d32dcc11a38e41f36e3deb1a6a9c4f4b14" } diff --git a/crates/activity_indicator/Cargo.toml b/crates/activity_indicator/Cargo.toml index b54271ee2d..a11174357b 100644 --- a/crates/activity_indicator/Cargo.toml +++ b/crates/activity_indicator/Cargo.toml @@ -17,5 +17,5 @@ project = { path = "../project" } settings = { path = "../settings" } util = { path = "../util" } workspace = { path = "../workspace" } -futures = "0.3" +futures = { workspace = true } smallvec = { workspace = true } diff --git a/crates/call/Cargo.toml b/crates/call/Cargo.toml index 4e738c0651..c1d8baa118 100644 --- a/crates/call/Cargo.toml +++ b/crates/call/Cargo.toml @@ -33,7 +33,7 @@ util = { path = "../util" } anyhow = "1.0.38" async-broadcast = "0.4" -futures = "0.3" +futures = { workspace = true } postage = { workspace = true } [dev-dependencies] diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 560a754bf7..a3b75e3aba 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -22,7 +22,7 @@ sum_tree = { path = "../sum_tree" } anyhow = "1.0.38" async-recursion = "0.3" async-tungstenite = { version = "0.16", features = ["async-tls"] } -futures = "0.3" +futures = { workspace = true } image = "0.23" lazy_static = "1.4.0" log = { version = "0.4.16", features = ["kv_unstable_serde"] } diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 778ae42ec4..4a86a33d71 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -27,7 +27,7 @@ base64 = "0.13" clap = { version = "3.1", features = ["derive"], optional = true } dashmap = "5.4" envy = "0.4.2" -futures = "0.3" +futures = { workspace = true } hyper = "0.14" lazy_static = "1.4" lipsum = { version = "0.8", optional = true } diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index 50f81c335c..994e61a386 100644 --- a/crates/collab_ui/Cargo.toml +++ b/crates/collab_ui/Cargo.toml @@ -40,7 +40,7 @@ theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } anyhow = "1.0" -futures = "0.3" +futures = { workspace = true } log = "0.4" postage = { workspace = true } serde = { workspace = true } diff --git a/crates/copilot/Cargo.toml b/crates/copilot/Cargo.toml index f4d75cc582..a837df97dd 100644 --- a/crates/copilot/Cargo.toml +++ b/crates/copilot/Cargo.toml @@ -35,7 +35,7 @@ log = "0.4" serde = { workspace = true } serde_derive = { workspace = true } smol = "1.2.5" -futures = "0.3" +futures = { workspace = true } [dev-dependencies] clock = { path = "../clock" } diff --git a/crates/copilot_button/Cargo.toml b/crates/copilot_button/Cargo.toml index f44493b323..67d44f8bd4 100644 --- a/crates/copilot_button/Cargo.toml +++ b/crates/copilot_button/Cargo.toml @@ -19,4 +19,4 @@ util = { path = "../util" } workspace = { path = "../workspace" } anyhow = "1.0" smol = "1.2.5" -futures = "0.3" +futures = { workspace = true } diff --git a/crates/editor/Cargo.toml b/crates/editor/Cargo.toml index 4cd81df1dc..47c5aaa715 100644 --- a/crates/editor/Cargo.toml +++ b/crates/editor/Cargo.toml @@ -47,7 +47,7 @@ workspace = { path = "../workspace" } aho-corasick = "0.7" anyhow = "1.0" -futures = "0.3" +futures = { workspace = true } indoc = "1.0.4" itertools = "0.10" lazy_static = "1.4" diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index 57b91876e3..1acc14892c 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -16,7 +16,7 @@ client = { path = "../client" } editor = { path = "../editor" } language = { path = "../language" } log = "0.4" -futures = "0.3" +futures = { workspace = true } gpui = { path = "../gpui" } human_bytes = "0.4.1" isahc = "1.7" diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index f4981ac13a..5eab919b7c 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -15,7 +15,7 @@ rope = { path = "../rope" } util = { path = "../util" } anyhow = "1.0.57" async-trait = "0.1" -futures = "0.3" +futures = { workspace = true } tempfile = "3" fsevent = { path = "../fsevent" } lazy_static = "1.4.0" diff --git a/crates/git/Cargo.toml b/crates/git/Cargo.toml index 3e88d72313..b1fa0eda78 100644 --- a/crates/git/Cargo.toml +++ b/crates/git/Cargo.toml @@ -19,7 +19,7 @@ log = { version = "0.4.16", features = ["kv_unstable_serde"] } smol = "1.2" parking_lot = "0.11.1" async-trait = "0.1" -futures = "0.3" +futures = { workspace = true } git2 = { version = "0.15", default-features = false } [dev-dependencies] diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 88c40665c2..858f67cf5f 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -25,7 +25,7 @@ ctor = "0.1" dhat = { version = "0.3", optional = true } env_logger = { version = "0.9", optional = true } etagere = "0.2" -futures = "0.3" +futures = { workspace = true } image = "0.23" itertools = "0.10" lazy_static = "1.4.0" diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index 4e15ccf679..d09b346348 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -39,7 +39,7 @@ util = { path = "../util" } anyhow = "1.0.38" async-broadcast = "0.4" async-trait = "0.1" -futures = "0.3" +futures = { workspace = true } lazy_static = "1.4" log = { version = "0.4.16", features = ["kv_unstable_serde"] } parking_lot = "0.11.1" diff --git a/crates/live_kit_client/Cargo.toml b/crates/live_kit_client/Cargo.toml index 70032d83aa..95057b3d0e 100644 --- a/crates/live_kit_client/Cargo.toml +++ b/crates/live_kit_client/Cargo.toml @@ -32,7 +32,7 @@ anyhow = "1.0.38" async-broadcast = "0.4" core-foundation = "0.9.3" core-graphics = "0.22.3" -futures = "0.3" +futures = { workspace = true } log = { version = "0.4.16", features = ["kv_unstable_serde"] } parking_lot = "0.11.1" postage = { workspace = true } @@ -56,7 +56,7 @@ cocoa = "0.24" core-foundation = "0.9.3" core-graphics = "0.22.3" foreign-types = "0.3" -futures = "0.3" +futures = { workspace = true } hmac = "0.12" jwt = "0.16" lazy_static = "1.4" diff --git a/crates/live_kit_server/Cargo.toml b/crates/live_kit_server/Cargo.toml index 8cced6d089..cfb3a9c885 100644 --- a/crates/live_kit_server/Cargo.toml +++ b/crates/live_kit_server/Cargo.toml @@ -12,7 +12,7 @@ doctest = false [dependencies] anyhow = "1.0.38" async-trait = "0.1" -futures = "0.3" +futures = { workspace = true } hmac = "0.12" log = "0.4" jwt = "0.16" diff --git a/crates/lsp/Cargo.toml b/crates/lsp/Cargo.toml index 4370aaab06..86b4ed9e40 100644 --- a/crates/lsp/Cargo.toml +++ b/crates/lsp/Cargo.toml @@ -17,7 +17,7 @@ gpui = { path = "../gpui" } util = { path = "../util" } anyhow = "1.0" async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "82d00a04211cf4e1236029aa03e6b6ce2a74c553", optional = true } -futures = "0.3" +futures = { workspace = true } log = { version = "0.4.16", features = ["kv_unstable_serde"] } lsp-types = "0.91" parking_lot = "0.11" diff --git a/crates/node_runtime/Cargo.toml b/crates/node_runtime/Cargo.toml index 32ab6abbb3..eb43be61ce 100644 --- a/crates/node_runtime/Cargo.toml +++ b/crates/node_runtime/Cargo.toml @@ -13,7 +13,7 @@ gpui = { path = "../gpui" } util = { path = "../util" } async-compression = { version = "0.3", features = ["gzip", "futures-bufread"] } async-tar = "0.4.2" -futures = "0.3" +futures = { workspace = true } anyhow = "1.0.38" parking_lot = "0.11.1" serde = { workspace = true } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index e30ab56e45..4ce5f24e9d 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -41,7 +41,7 @@ aho-corasick = "0.7" anyhow = "1.0.57" async-trait = "0.1" backtrace = "0.3" -futures = "0.3" +futures = { workspace = true } ignore = "0.4" lazy_static = "1.4.0" log = { version = "0.4.16", features = ["kv_unstable_serde"] } diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 2b72959e25..195bcee10a 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -20,7 +20,7 @@ theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } postage = { workspace = true } -futures = "0.3" +futures = { workspace = true } unicase = "2.6" [dev-dependencies] diff --git a/crates/project_symbols/Cargo.toml b/crates/project_symbols/Cargo.toml index 9e79b09d72..b03e62cc55 100644 --- a/crates/project_symbols/Cargo.toml +++ b/crates/project_symbols/Cargo.toml @@ -24,7 +24,7 @@ postage = { workspace = true } smol = "1.2" [dev-dependencies] -futures = "0.3" +futures = { workspace = true } settings = { path = "../settings", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } language = { path = "../language", features = ["test-support"] } diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 2773dd2f3b..78f37fd5ae 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -21,7 +21,7 @@ anyhow = "1.0" async-lock = "2.4" async-tungstenite = "0.16" base64 = "0.13" -futures = "0.3" +futures = { workspace = true } parking_lot = "0.11.1" prost = "0.8" rand = "0.8" diff --git a/crates/search/Cargo.toml b/crates/search/Cargo.toml index fb4e79a703..fc8737e73f 100644 --- a/crates/search/Cargo.toml +++ b/crates/search/Cargo.toml @@ -20,7 +20,7 @@ theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } anyhow = "1.0" -futures = "0.3" +futures = { workspace = true } log = { version = "0.4.16", features = ["kv_unstable_serde"] } postage = { workspace = true } serde = { workspace = true } diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index fbb3ad63f3..ab5e428b7b 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -18,7 +18,7 @@ gpui = { path = "../gpui" } sqlez = { path = "../sqlez" } fs = { path = "../fs" } anyhow = "1.0.38" -futures = "0.3" +futures = { workspace = true } theme = { path = "../theme" } staff_mode = { path = "../staff_mode" } util = { path = "../util" } diff --git a/crates/sqlez/Cargo.toml b/crates/sqlez/Cargo.toml index 716ec76644..7e82a50247 100644 --- a/crates/sqlez/Cargo.toml +++ b/crates/sqlez/Cargo.toml @@ -14,5 +14,5 @@ smol = "1.2" thread_local = "1.1.4" lazy_static = "1.4" parking_lot = "0.11.1" -futures = "0.3" -uuid = { version = "1.1.2", features = ["v4"] } \ No newline at end of file +futures = { workspace = true } +uuid = { version = "1.1.2", features = ["v4"] } diff --git a/crates/terminal/Cargo.toml b/crates/terminal/Cargo.toml index 107d325677..f46bdad5d5 100644 --- a/crates/terminal/Cargo.toml +++ b/crates/terminal/Cargo.toml @@ -20,7 +20,7 @@ procinfo = { git = "https://github.com/zed-industries/wezterm", rev = "5cd757e5f smallvec = { workspace = true } smol = "1.2.5" mio-extras = "2.0.6" -futures = "0.3" +futures = { workspace = true } ordered-float = "2.1.1" itertools = "0.10" dirs = "4.0.0" diff --git a/crates/terminal_view/Cargo.toml b/crates/terminal_view/Cargo.toml index f271cd118d..fe7dd833e9 100644 --- a/crates/terminal_view/Cargo.toml +++ b/crates/terminal_view/Cargo.toml @@ -24,7 +24,7 @@ terminal = { path = "../terminal" } smallvec = { workspace = true } smol = "1.2.5" mio-extras = "2.0.6" -futures = "0.3" +futures = { workspace = true } ordered-float = "2.1.1" itertools = "0.10" dirs = "4.0.0" diff --git a/crates/util/Cargo.toml b/crates/util/Cargo.toml index 38124dcc11..faf88c5c9d 100644 --- a/crates/util/Cargo.toml +++ b/crates/util/Cargo.toml @@ -16,7 +16,7 @@ anyhow = "1.0.38" backtrace = "0.3" log = { version = "0.4.16", features = ["kv_unstable_serde"] } lazy_static = "1.4.0" -futures = "0.3" +futures = { workspace = true } isahc = "1.7" smol = "1.2.5" url = "2.2" diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 84db04e9a6..69ee515a91 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -38,7 +38,7 @@ util = { path = "../util" } async-recursion = "1.0.0" bincode = "1.2.1" anyhow = "1.0.38" -futures = "0.3" +futures = { workspace = true } lazy_static = "1.4" env_logger = "0.9.1" log = { version = "0.4.16", features = ["kv_unstable_serde"] } diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 7eb35f3b3e..abd9dd10d9 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -76,7 +76,7 @@ chrono = "0.4" ctor = "0.1.20" easy-parallel = "3.1.0" env_logger = "0.9" -futures = "0.3" +futures = { workspace = true } ignore = "0.4" image = "0.23" indexmap = "1.6.2" From 2dd492062548f272acab6d787bf0ad82cb099ed6 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 20 Apr 2023 17:47:51 -0700 Subject: [PATCH 11/23] Add LanguageServer::on_io method, for observing JSON sent back and forth --- crates/lsp/src/lsp.rs | 110 +++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index b6a4d8513e..86352d225d 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -20,10 +20,10 @@ use std::{ future::Future, io::Write, path::PathBuf, - str::FromStr, + str::{self, FromStr as _}, sync::{ atomic::{AtomicUsize, Ordering::SeqCst}, - Arc, + Arc, Weak, }, }; use std::{path::Path, process::Stdio}; @@ -34,16 +34,18 @@ const CONTENT_LEN_HEADER: &str = "Content-Length: "; type NotificationHandler = Box, &str, AsyncAppContext)>; type ResponseHandler = Box)>; +type IoHandler = Box; pub struct LanguageServer { server_id: LanguageServerId, next_id: AtomicUsize, - outbound_tx: channel::Sender>, + outbound_tx: channel::Sender, name: String, capabilities: ServerCapabilities, code_action_kinds: Option>, notification_handlers: Arc>>, response_handlers: Arc>>>, + io_handlers: Arc>>, executor: Arc, #[allow(clippy::type_complexity)] io_tasks: Mutex>, Task>)>>, @@ -56,9 +58,16 @@ pub struct LanguageServer { #[repr(transparent)] pub struct LanguageServerId(pub usize); -pub struct Subscription { - method: &'static str, - notification_handlers: Arc>>, +pub enum Subscription { + Detached, + Notification { + method: &'static str, + notification_handlers: Arc>>, + }, + Io { + id: usize, + io_handlers: Weak>>, + }, } #[derive(Serialize, Deserialize)] @@ -177,33 +186,40 @@ impl LanguageServer { Stdout: AsyncRead + Unpin + Send + 'static, F: FnMut(AnyNotification) + 'static + Send, { - let (outbound_tx, outbound_rx) = channel::unbounded::>(); + let (outbound_tx, outbound_rx) = channel::unbounded::(); + let (output_done_tx, output_done_rx) = barrier::channel(); let notification_handlers = Arc::new(Mutex::new(HashMap::<_, NotificationHandler>::default())); let response_handlers = Arc::new(Mutex::new(Some(HashMap::<_, ResponseHandler>::default()))); + let io_handlers = Arc::new(Mutex::new(HashMap::default())); let input_task = cx.spawn(|cx| { - let notification_handlers = notification_handlers.clone(); - let response_handlers = response_handlers.clone(); Self::handle_input( stdout, on_unhandled_notification, - notification_handlers, - response_handlers, + notification_handlers.clone(), + response_handlers.clone(), + io_handlers.clone(), cx, ) .log_err() }); - let (output_done_tx, output_done_rx) = barrier::channel(); let output_task = cx.background().spawn({ - let response_handlers = response_handlers.clone(); - Self::handle_output(stdin, outbound_rx, output_done_tx, response_handlers).log_err() + Self::handle_output( + stdin, + outbound_rx, + output_done_tx, + response_handlers.clone(), + io_handlers.clone(), + ) + .log_err() }); Self { server_id, notification_handlers, response_handlers, + io_handlers, name: Default::default(), capabilities: Default::default(), code_action_kinds, @@ -226,6 +242,7 @@ impl LanguageServer { mut on_unhandled_notification: F, notification_handlers: Arc>>, response_handlers: Arc>>>, + io_handlers: Arc>>, cx: AsyncAppContext, ) -> anyhow::Result<()> where @@ -252,7 +269,13 @@ impl LanguageServer { buffer.resize(message_len, 0); stdout.read_exact(&mut buffer).await?; - log::trace!("incoming message:{}", String::from_utf8_lossy(&buffer)); + + if let Ok(message) = str::from_utf8(&buffer) { + log::trace!("incoming message:{}", message); + for handler in io_handlers.lock().values_mut() { + handler(true, message); + } + } if let Ok(msg) = serde_json::from_slice::(&buffer) { if let Some(handler) = notification_handlers.lock().get_mut(msg.method) { @@ -291,9 +314,10 @@ impl LanguageServer { async fn handle_output( stdin: Stdin, - outbound_rx: channel::Receiver>, + outbound_rx: channel::Receiver, output_done_tx: barrier::Sender, response_handlers: Arc>>>, + io_handlers: Arc>>, ) -> anyhow::Result<()> where Stdin: AsyncWrite + Unpin + Send + 'static, @@ -307,13 +331,17 @@ impl LanguageServer { }); let mut content_len_buffer = Vec::new(); while let Ok(message) = outbound_rx.recv().await { - log::trace!("outgoing message:{}", String::from_utf8_lossy(&message)); + log::trace!("outgoing message:{}", message); + for handler in io_handlers.lock().values_mut() { + handler(false, &message); + } + content_len_buffer.clear(); write!(content_len_buffer, "{}", message.len()).unwrap(); stdin.write_all(CONTENT_LEN_HEADER.as_bytes()).await?; stdin.write_all(&content_len_buffer).await?; stdin.write_all("\r\n\r\n".as_bytes()).await?; - stdin.write_all(&message).await?; + stdin.write_all(message.as_bytes()).await?; stdin.flush().await?; } drop(output_done_tx); @@ -464,6 +492,19 @@ impl LanguageServer { self.on_custom_request(T::METHOD, f) } + #[must_use] + pub fn on_io(&self, f: F) -> Subscription + where + F: 'static + Send + FnMut(bool, &str), + { + let id = self.next_id.fetch_add(1, SeqCst); + self.io_handlers.lock().insert(id, Box::new(f)); + Subscription::Io { + id, + io_handlers: Arc::downgrade(&self.io_handlers), + } + } + pub fn remove_request_handler(&self) { self.notification_handlers.lock().remove(T::METHOD); } @@ -490,7 +531,7 @@ impl LanguageServer { prev_handler.is_none(), "registered multiple handlers for the same LSP method" ); - Subscription { + Subscription::Notification { method, notification_handlers: self.notification_handlers.clone(), } @@ -537,7 +578,7 @@ impl LanguageServer { }, }; if let Some(response) = - serde_json::to_vec(&response).log_err() + serde_json::to_string(&response).log_err() { outbound_tx.try_send(response).ok(); } @@ -560,7 +601,7 @@ impl LanguageServer { message: error.to_string(), }), }; - if let Some(response) = serde_json::to_vec(&response).log_err() { + if let Some(response) = serde_json::to_string(&response).log_err() { outbound_tx.try_send(response).ok(); } } @@ -572,7 +613,7 @@ impl LanguageServer { prev_handler.is_none(), "registered multiple handlers for the same LSP method" ); - Subscription { + Subscription::Notification { method, notification_handlers: self.notification_handlers.clone(), } @@ -612,14 +653,14 @@ impl LanguageServer { fn request_internal( next_id: &AtomicUsize, response_handlers: &Mutex>>, - outbound_tx: &channel::Sender>, + outbound_tx: &channel::Sender, params: T::Params, ) -> impl 'static + Future> where T::Result: 'static + Send, { let id = next_id.fetch_add(1, SeqCst); - let message = serde_json::to_vec(&Request { + let message = serde_json::to_string(&Request { jsonrpc: JSON_RPC_VERSION, id, method: T::METHOD, @@ -662,10 +703,10 @@ impl LanguageServer { } fn notify_internal( - outbound_tx: &channel::Sender>, + outbound_tx: &channel::Sender, params: T::Params, ) -> Result<()> { - let message = serde_json::to_vec(&Notification { + let message = serde_json::to_string(&Notification { jsonrpc: JSON_RPC_VERSION, method: T::METHOD, params, @@ -686,7 +727,7 @@ impl Drop for LanguageServer { impl Subscription { pub fn detach(mut self) { - self.method = ""; + *(&mut self) = Self::Detached; } } @@ -698,7 +739,20 @@ impl fmt::Display for LanguageServerId { impl Drop for Subscription { fn drop(&mut self) { - self.notification_handlers.lock().remove(self.method); + match self { + Subscription::Detached => {} + Subscription::Notification { + method, + notification_handlers, + } => { + notification_handlers.lock().remove(method); + } + Subscription::Io { id, io_handlers } => { + if let Some(io_handlers) = io_handlers.upgrade() { + io_handlers.lock().remove(id); + } + } + } } } From a280a93cd8a80da187622c7b763aaf4d27fef519 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 20 Apr 2023 17:56:22 -0700 Subject: [PATCH 12/23] Start work on a language server log view --- Cargo.lock | 21 ++ Cargo.toml | 1 + crates/editor/src/editor.rs | 21 ++ crates/lsp_log/Cargo.toml | 29 +++ crates/lsp_log/src/lsp_log.rs | 374 ++++++++++++++++++++++++++++++++++ crates/project/src/project.rs | 36 ++-- crates/zed/Cargo.toml | 1 + crates/zed/src/zed.rs | 7 +- 8 files changed, 477 insertions(+), 13 deletions(-) create mode 100644 crates/lsp_log/Cargo.toml create mode 100644 crates/lsp_log/src/lsp_log.rs diff --git a/Cargo.lock b/Cargo.lock index 7c2f043193..5713bddd0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3612,6 +3612,26 @@ dependencies = [ "url", ] +[[package]] +name = "lsp_log" +version = "0.1.0" +dependencies = [ + "anyhow", + "collections", + "editor", + "futures 0.3.25", + "gpui", + "language", + "lsp", + "project", + "serde", + "settings", + "theme", + "unindent", + "util", + "workspace", +] + [[package]] name = "mach" version = "0.3.2" @@ -8571,6 +8591,7 @@ dependencies = [ "libc", "log", "lsp", + "lsp_log", "node_runtime", "num_cpus", "outline", diff --git a/Cargo.toml b/Cargo.toml index 1c325fbb8e..94a0b0d402 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ members = [ "crates/live_kit_client", "crates/live_kit_server", "crates/lsp", + "crates/lsp_log", "crates/media", "crates/menu", "crates/node_runtime", diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 54ba2c1a9c..563c0aa132 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -511,6 +511,7 @@ pub struct Editor { workspace_id: Option, keymap_context_layers: BTreeMap, input_enabled: bool, + read_only: bool, leader_replica_id: Option, remote_id: Option, hover_state: HoverState, @@ -1283,6 +1284,7 @@ impl Editor { workspace_id: None, keymap_context_layers: Default::default(), input_enabled: true, + read_only: false, leader_replica_id: None, remote_id: None, hover_state: Default::default(), @@ -1425,6 +1427,10 @@ impl Editor { self.input_enabled = input_enabled; } + pub fn set_read_only(&mut self, read_only: bool) { + self.read_only = read_only; + } + fn selections_did_change( &mut self, local: bool, @@ -1533,6 +1539,10 @@ impl Editor { S: ToOffset, T: Into>, { + if self.read_only { + return; + } + self.buffer .update(cx, |buffer, cx| buffer.edit(edits, None, cx)); } @@ -1543,6 +1553,10 @@ impl Editor { S: ToOffset, T: Into>, { + if self.read_only { + return; + } + self.buffer.update(cx, |buffer, cx| { buffer.edit(edits, Some(AutoindentMode::EachLine), cx) }); @@ -1897,6 +1911,9 @@ impl Editor { pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext) { let text: Arc = text.into(); + if self.read_only { + return; + } if !self.input_enabled { cx.emit(Event::InputIgnored { text }); return; @@ -2282,6 +2299,10 @@ impl Editor { autoindent_mode: Option, cx: &mut ViewContext, ) { + if self.read_only { + return; + } + let text: Arc = text.into(); self.transact(cx, |this, cx| { let old_selections = this.selections.all_adjusted(cx); diff --git a/crates/lsp_log/Cargo.toml b/crates/lsp_log/Cargo.toml new file mode 100644 index 0000000000..4eeebef9a4 --- /dev/null +++ b/crates/lsp_log/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "lsp_log" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/lsp_log.rs" +doctest = false + +[dependencies] +collections = { path = "../collections" } +editor = { path = "../editor" } +settings = { path = "../settings" } +theme = { path = "../theme" } +language = { path = "../language" } +project = { path = "../project" } +workspace = { path = "../workspace" } +gpui = { path = "../gpui" } +util = { path = "../util" } +lsp = { path = "../lsp" } +futures = { workspace = true } +serde = { workspace = true } +anyhow = "1.0" + +[dev-dependencies] +gpui = { path = "../gpui", features = ["test-support"] } +util = { path = "../util", features = ["test-support"] } +unindent = "0.1.7" diff --git a/crates/lsp_log/src/lsp_log.rs b/crates/lsp_log/src/lsp_log.rs new file mode 100644 index 0000000000..a50e9ad9a9 --- /dev/null +++ b/crates/lsp_log/src/lsp_log.rs @@ -0,0 +1,374 @@ +use collections::HashMap; +use editor::Editor; +use futures::{channel::mpsc, StreamExt}; +use gpui::{ + actions, + elements::{ + AnchorCorner, ChildView, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, + ParentElement, Stack, + }, + impl_internal_actions, + platform::MouseButton, + AppContext, Element, ElementBox, Entity, ModelHandle, RenderContext, View, ViewContext, + ViewHandle, +}; +use language::{Buffer, LanguageServerId, LanguageServerName}; +use project::{Project, WorktreeId}; +use settings::Settings; +use std::{borrow::Cow, sync::Arc}; +use theme::Theme; +use workspace::{ + item::{Item, ItemHandle}, + ToolbarItemLocation, ToolbarItemView, Workspace, +}; + +const SEND_LINE: &str = "// Send:\n"; +const RECEIVE_LINE: &str = "// Receive:\n"; + +pub struct LspLogView { + enabled_logs: HashMap, + current_server_id: Option, + project: ModelHandle, + io_tx: mpsc::UnboundedSender<(LanguageServerId, bool, String)>, +} + +pub struct LspLogToolbarItemView { + log_view: Option>, + menu_open: bool, + project: ModelHandle, +} + +struct LogState { + buffer: ModelHandle, + editor: ViewHandle, + last_message_kind: Option, + _subscription: lsp::Subscription, +} + +#[derive(Copy, Clone, PartialEq, Eq)] +enum MessageKind { + Send, + Receive, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +struct ActivateLog { + server_id: LanguageServerId, +} + +#[derive(Clone, Copy, PartialEq, Eq)] +struct ToggleMenu; + +impl_internal_actions!(log, [ActivateLog, ToggleMenu]); +actions!(log, [OpenLanguageServerLogs]); + +pub fn init(cx: &mut AppContext) { + cx.add_action(LspLogView::deploy); + cx.add_action(LspLogToolbarItemView::toggle_menu); + cx.add_action(LspLogToolbarItemView::activate_log_for_server); +} + +impl LspLogView { + pub fn new(project: ModelHandle, cx: &mut ViewContext) -> Self { + let (io_tx, mut io_rx) = mpsc::unbounded(); + let this = Self { + enabled_logs: HashMap::default(), + current_server_id: None, + io_tx, + project, + }; + cx.spawn_weak(|this, mut cx| async move { + while let Some((language_server_id, is_output, mut message)) = io_rx.next().await { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |this, cx| { + message.push('\n'); + this.on_io(language_server_id, is_output, &message, cx); + }) + } + } + }) + .detach(); + this + } + + fn deploy( + workspace: &mut Workspace, + _: &OpenLanguageServerLogs, + cx: &mut ViewContext, + ) { + let project = workspace.project().read(cx); + if project.is_remote() { + return; + } + + let log_view = cx.add_view(|cx| Self::new(workspace.project().clone(), cx)); + workspace.add_item(Box::new(log_view), cx); + } + + fn activate_log(&mut self, action: &ActivateLog, cx: &mut ViewContext) { + self.enable_logs_for_language_server(action.server_id, cx); + self.current_server_id = Some(action.server_id); + cx.notify(); + } + + fn on_io( + &mut self, + language_server_id: LanguageServerId, + is_received: bool, + message: &str, + cx: &mut ViewContext, + ) { + if let Some(state) = self.enabled_logs.get_mut(&language_server_id) { + state.buffer.update(cx, |buffer, cx| { + let kind = if is_received { + MessageKind::Receive + } else { + MessageKind::Send + }; + if state.last_message_kind != Some(kind) { + let len = buffer.len(); + let line = match kind { + MessageKind::Send => SEND_LINE, + MessageKind::Receive => RECEIVE_LINE, + }; + buffer.edit([(len..len, line)], None, cx); + state.last_message_kind = Some(kind); + } + let len = buffer.len(); + buffer.edit([(len..len, message)], None, cx); + }); + } + } + + pub fn enable_logs_for_language_server( + &mut self, + server_id: LanguageServerId, + cx: &mut ViewContext, + ) { + if let Some(server) = self.project.read(cx).language_server_for_id(server_id) { + self.enabled_logs.entry(server_id).or_insert_with(|| { + let project = self.project.read(cx); + let io_tx = self.io_tx.clone(); + let language = project.languages().language_for_name("JSON"); + let buffer = cx.add_model(|cx| Buffer::new(0, "", cx)); + cx.spawn({ + let buffer = buffer.clone(); + |_, mut cx| async move { + let language = language.await.ok(); + buffer.update(&mut cx, |buffer, cx| { + buffer.set_language(language, cx); + }); + } + }) + .detach(); + let editor = cx.add_view(|cx| { + let mut editor = + Editor::for_buffer(buffer.clone(), Some(self.project.clone()), cx); + editor.set_read_only(true); + editor + }); + + LogState { + buffer, + editor, + last_message_kind: None, + _subscription: server.on_io(move |is_received, json| { + io_tx + .unbounded_send((server_id, is_received, json.to_string())) + .ok(); + }), + } + }); + } + } +} + +impl View for LspLogView { + fn ui_name() -> &'static str { + "LspLogView" + } + + fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { + if let Some(id) = self.current_server_id { + if let Some(log) = self.enabled_logs.get_mut(&id) { + return ChildView::new(&log.editor, cx).boxed(); + } + } + Empty::new().boxed() + } +} + +impl Item for LspLogView { + fn tab_content(&self, _: Option, style: &theme::Tab, _: &AppContext) -> ElementBox { + Label::new("Logs", style.label.clone()).boxed() + } +} + +impl ToolbarItemView for LspLogToolbarItemView { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + cx: &mut ViewContext, + ) -> workspace::ToolbarItemLocation { + self.menu_open = false; + if let Some(item) = active_pane_item { + if let Some(log_view) = item.downcast::() { + self.log_view = Some(log_view.clone()); + return ToolbarItemLocation::PrimaryLeft { + flex: Some((1., false)), + }; + } + } + self.log_view = None; + ToolbarItemLocation::Hidden + } +} + +impl View for LspLogToolbarItemView { + fn ui_name() -> &'static str { + "LspLogView" + } + + fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox { + let theme = cx.global::().theme.clone(); + let Some(log_view) = self.log_view.as_ref() else { return Empty::new().boxed() }; + let project = self.project.read(cx); + let mut language_servers = project.language_servers().collect::>(); + language_servers.sort_by_key(|a| a.0); + + let current_server_id = log_view.read(cx).current_server_id; + let current_server = current_server_id.and_then(|current_server_id| { + if let Ok(ix) = language_servers.binary_search_by_key(¤t_server_id, |e| e.0) { + Some(language_servers[ix].clone()) + } else { + None + } + }); + + Stack::new() + .with_child(Self::render_language_server_menu_header( + current_server, + &self.project, + &theme, + cx, + )) + .with_children(if self.menu_open { + Some( + Overlay::new( + Flex::column() + .with_children(language_servers.into_iter().filter_map( + |(id, name, worktree_id)| { + Self::render_language_server_menu_item( + id, + name, + worktree_id, + &self.project, + &theme, + cx, + ) + }, + )) + .contained() + .with_style(theme.contacts_popover.container) + .constrained() + .with_width(200.) + .with_height(400.) + .boxed(), + ) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopRight) + .with_z_index(999) + .aligned() + .bottom() + .right() + .boxed(), + ) + } else { + None + }) + .boxed() + } +} + +impl LspLogToolbarItemView { + pub fn new(project: ModelHandle) -> Self { + Self { + menu_open: false, + log_view: None, + project, + } + } + + fn toggle_menu(&mut self, _: &ToggleMenu, cx: &mut ViewContext) { + self.menu_open = !self.menu_open; + cx.notify(); + } + + fn activate_log_for_server(&mut self, action: &ActivateLog, cx: &mut ViewContext) { + if let Some(log_view) = &self.log_view { + log_view.update(cx, |log_view, cx| { + log_view.activate_log(action, cx); + }); + self.menu_open = false; + } + cx.notify(); + } + + fn render_language_server_menu_header( + current_server: Option<(LanguageServerId, LanguageServerName, WorktreeId)>, + project: &ModelHandle, + theme: &Arc, + cx: &mut RenderContext, + ) -> ElementBox { + MouseEventHandler::::new(0, cx, move |state, cx| { + let project = project.read(cx); + let label: Cow = current_server + .and_then(|(_, server_name, worktree_id)| { + let worktree = project.worktree_for_id(worktree_id, cx)?; + let worktree = &worktree.read(cx); + Some(format!("{} - ({})", server_name.0, worktree.root_name()).into()) + }) + .unwrap_or_else(|| "No server selected".into()); + Label::new(label, theme.context_menu.item.default.label.clone()).boxed() + }) + .on_click(MouseButton::Left, move |_, cx| { + cx.dispatch_action(ToggleMenu); + }) + .boxed() + } + + fn render_language_server_menu_item( + id: LanguageServerId, + name: LanguageServerName, + worktree_id: WorktreeId, + project: &ModelHandle, + theme: &Arc, + cx: &mut RenderContext, + ) -> Option { + let project = project.read(cx); + let worktree = project.worktree_for_id(worktree_id, cx)?; + let worktree = &worktree.read(cx); + if !worktree.is_visible() { + return None; + } + let label = format!("{} - ({})", name.0, worktree.root_name()); + + Some( + MouseEventHandler::::new(id.0, cx, move |state, cx| { + Label::new(label, theme.context_menu.item.default.label.clone()).boxed() + }) + .on_click(MouseButton::Left, move |_, cx| { + cx.dispatch_action(ActivateLog { server_id: id }) + }) + .boxed(), + ) + } +} + +impl Entity for LspLogView { + type Event = (); +} + +impl Entity for LspLogToolbarItemView { + type Event = (); +} diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index afd0b3bbae..aad9a50856 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -185,6 +185,8 @@ pub struct Collaborator { #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { + LanguageServerAdded(LanguageServerId), + LanguageServerRemoved(LanguageServerId), ActiveEntryChanged(Option), WorktreeAdded, WorktreeRemoved(WorktreeId), @@ -1869,7 +1871,7 @@ impl Project { let next_snapshot = buffer.text_snapshot(); let language_servers: Vec<_> = self - .language_servers_iter_for_buffer(buffer, cx) + .language_servers_for_buffer(buffer, cx) .map(|i| i.1.clone()) .collect(); @@ -6279,7 +6281,25 @@ impl Project { } } - pub fn language_servers_iter_for_buffer( + pub fn language_servers( + &self, + ) -> impl '_ + Iterator { + self.language_server_ids + .iter() + .map(|((worktree_id, server_name), server_id)| { + (*server_id, server_name.clone(), *worktree_id) + }) + } + + pub fn language_server_for_id(&self, id: LanguageServerId) -> Option> { + if let LanguageServerState::Running { server, .. } = self.language_servers.get(&id)? { + Some(server.clone()) + } else { + None + } + } + + pub fn language_servers_for_buffer( &self, buffer: &Buffer, cx: &AppContext, @@ -6299,20 +6319,12 @@ impl Project { }) } - fn language_servers_for_buffer( - &self, - buffer: &Buffer, - cx: &AppContext, - ) -> Vec<(&Arc, &Arc)> { - self.language_servers_iter_for_buffer(buffer, cx).collect() - } - fn primary_language_servers_for_buffer( &self, buffer: &Buffer, cx: &AppContext, ) -> Option<(&Arc, &Arc)> { - self.language_servers_iter_for_buffer(buffer, cx).next() + self.language_servers_for_buffer(buffer, cx).next() } fn language_server_for_buffer( @@ -6321,7 +6333,7 @@ impl Project { server_id: LanguageServerId, cx: &AppContext, ) -> Option<(&Arc, &Arc)> { - self.language_servers_iter_for_buffer(buffer, cx) + self.language_servers_for_buffer(buffer, cx) .find(|(_, s)| s.server_id() == server_id) } diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index abd9dd10d9..fe6f7a8758 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -46,6 +46,7 @@ journal = { path = "../journal" } language = { path = "../language" } language_selector = { path = "../language_selector" } lsp = { path = "../lsp" } +lsp_log = { path = "../lsp_log" } node_runtime = { path = "../node_runtime" } outline = { path = "../outline" } plugin_runtime = { path = "../plugin_runtime" } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index c6cfd8c109..c035ac07dd 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -262,6 +262,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::AppContext) { ); activity_indicator::init(cx); copilot_button::init(cx); + lsp_log::init(cx); call::init(app_state.client.clone(), app_state.user_store.clone(), cx); settings::KeymapFileContent::load_defaults(cx); } @@ -273,7 +274,7 @@ pub fn initialize_workspace( ) { let workspace_handle = cx.handle(); cx.subscribe(&workspace_handle, { - move |_, _, event, cx| { + move |workspace, _, event, cx| { if let workspace::Event::PaneAdded(pane) = event { pane.update(cx, |pane, cx| { pane.toolbar().update(cx, |toolbar, cx| { @@ -287,6 +288,10 @@ pub fn initialize_workspace( toolbar.add_item(submit_feedback_button, cx); let feedback_info_text = cx.add_view(|_| FeedbackInfoText::new()); toolbar.add_item(feedback_info_text, cx); + let lsp_log_item = cx.add_view(|_| { + lsp_log::LspLogToolbarItemView::new(workspace.project().clone()) + }); + toolbar.add_item(lsp_log_item, cx); }) }); } From 6ef6f03322af0df5131fdbd31b9d41fba36888fe Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 21 Apr 2023 14:45:16 -0700 Subject: [PATCH 13/23] Update LspLog view to use new gpui APIs --- crates/lsp_log/src/lsp_log.rs | 93 ++++++++++++++++------------------- 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/crates/lsp_log/src/lsp_log.rs b/crates/lsp_log/src/lsp_log.rs index a50e9ad9a9..14329dbbd3 100644 --- a/crates/lsp_log/src/lsp_log.rs +++ b/crates/lsp_log/src/lsp_log.rs @@ -7,16 +7,15 @@ use gpui::{ AnchorCorner, ChildView, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, ParentElement, Stack, }, - impl_internal_actions, platform::MouseButton, - AppContext, Element, ElementBox, Entity, ModelHandle, RenderContext, View, ViewContext, - ViewHandle, + AnyElement, AppContext, Element, Entity, ModelHandle, View, ViewContext, ViewHandle, }; use language::{Buffer, LanguageServerId, LanguageServerName}; use project::{Project, WorktreeId}; use settings::Settings; use std::{borrow::Cow, sync::Arc}; use theme::Theme; +use util::ResultExt; use workspace::{ item::{Item, ItemHandle}, ToolbarItemLocation, ToolbarItemView, Workspace, @@ -51,21 +50,10 @@ enum MessageKind { Receive, } -#[derive(Clone, Copy, PartialEq, Eq)] -struct ActivateLog { - server_id: LanguageServerId, -} - -#[derive(Clone, Copy, PartialEq, Eq)] -struct ToggleMenu; - -impl_internal_actions!(log, [ActivateLog, ToggleMenu]); actions!(log, [OpenLanguageServerLogs]); pub fn init(cx: &mut AppContext) { - cx.add_action(LspLogView::deploy); - cx.add_action(LspLogToolbarItemView::toggle_menu); - cx.add_action(LspLogToolbarItemView::activate_log_for_server); + cx.add_action(LspLogView::open); } impl LspLogView { @@ -84,14 +72,16 @@ impl LspLogView { message.push('\n'); this.on_io(language_server_id, is_output, &message, cx); }) + .log_err(); } } + anyhow::Ok(()) }) .detach(); this } - fn deploy( + fn open( workspace: &mut Workspace, _: &OpenLanguageServerLogs, cx: &mut ViewContext, @@ -105,9 +95,9 @@ impl LspLogView { workspace.add_item(Box::new(log_view), cx); } - fn activate_log(&mut self, action: &ActivateLog, cx: &mut ViewContext) { - self.enable_logs_for_language_server(action.server_id, cx); - self.current_server_id = Some(action.server_id); + fn activate_log(&mut self, server_id: LanguageServerId, cx: &mut ViewContext) { + self.enable_logs_for_language_server(server_id, cx); + self.current_server_id = Some(server_id); cx.notify(); } @@ -188,19 +178,24 @@ impl View for LspLogView { "LspLogView" } - fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> gpui::ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if let Some(id) = self.current_server_id { if let Some(log) = self.enabled_logs.get_mut(&id) { - return ChildView::new(&log.editor, cx).boxed(); + return ChildView::new(&log.editor, cx).into_any(); } } - Empty::new().boxed() + Empty::new().into_any() } } impl Item for LspLogView { - fn tab_content(&self, _: Option, style: &theme::Tab, _: &AppContext) -> ElementBox { - Label::new("Logs", style.label.clone()).boxed() + fn tab_content( + &self, + _: Option, + style: &theme::Tab, + _: &AppContext, + ) -> AnyElement { + Label::new("Logs", style.label.clone()).into_any() } } @@ -208,7 +203,7 @@ impl ToolbarItemView for LspLogToolbarItemView { fn set_active_pane_item( &mut self, active_pane_item: Option<&dyn ItemHandle>, - cx: &mut ViewContext, + _: &mut ViewContext, ) -> workspace::ToolbarItemLocation { self.menu_open = false; if let Some(item) = active_pane_item { @@ -229,9 +224,9 @@ impl View for LspLogToolbarItemView { "LspLogView" } - fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox { + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { let theme = cx.global::().theme.clone(); - let Some(log_view) = self.log_view.as_ref() else { return Empty::new().boxed() }; + let Some(log_view) = self.log_view.as_ref() else { return Empty::new().into_any() }; let project = self.project.read(cx); let mut language_servers = project.language_servers().collect::>(); language_servers.sort_by_key(|a| a.0); @@ -272,21 +267,19 @@ impl View for LspLogToolbarItemView { .with_style(theme.contacts_popover.container) .constrained() .with_width(200.) - .with_height(400.) - .boxed(), + .with_height(400.), ) .with_fit_mode(OverlayFitMode::SwitchAnchor) .with_anchor_corner(AnchorCorner::TopRight) .with_z_index(999) .aligned() .bottom() - .right() - .boxed(), + .right(), ) } else { None }) - .boxed() + .into_any() } } @@ -299,15 +292,15 @@ impl LspLogToolbarItemView { } } - fn toggle_menu(&mut self, _: &ToggleMenu, cx: &mut ViewContext) { + fn toggle_menu(&mut self, cx: &mut ViewContext) { self.menu_open = !self.menu_open; cx.notify(); } - fn activate_log_for_server(&mut self, action: &ActivateLog, cx: &mut ViewContext) { + fn activate_log_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { if let Some(log_view) = &self.log_view { log_view.update(cx, |log_view, cx| { - log_view.activate_log(action, cx); + log_view.activate_log(id, cx); }); self.menu_open = false; } @@ -318,9 +311,10 @@ impl LspLogToolbarItemView { current_server: Option<(LanguageServerId, LanguageServerName, WorktreeId)>, project: &ModelHandle, theme: &Arc, - cx: &mut RenderContext, - ) -> ElementBox { - MouseEventHandler::::new(0, cx, move |state, cx| { + cx: &mut ViewContext, + ) -> impl Element { + enum ToggleMenu {} + MouseEventHandler::::new(0, cx, move |state, cx| { let project = project.read(cx); let label: Cow = current_server .and_then(|(_, server_name, worktree_id)| { @@ -329,12 +323,11 @@ impl LspLogToolbarItemView { Some(format!("{} - ({})", server_name.0, worktree.root_name()).into()) }) .unwrap_or_else(|| "No server selected".into()); - Label::new(label, theme.context_menu.item.default.label.clone()).boxed() + Label::new(label, theme.context_menu.item.default.label.clone()) }) - .on_click(MouseButton::Left, move |_, cx| { - cx.dispatch_action(ToggleMenu); + .on_click(MouseButton::Left, move |_, view, cx| { + view.toggle_menu(cx); }) - .boxed() } fn render_language_server_menu_item( @@ -343,8 +336,9 @@ impl LspLogToolbarItemView { worktree_id: WorktreeId, project: &ModelHandle, theme: &Arc, - cx: &mut RenderContext, - ) -> Option { + cx: &mut ViewContext, + ) -> Option> { + enum ActivateLog {} let project = project.read(cx); let worktree = project.worktree_for_id(worktree_id, cx)?; let worktree = &worktree.read(cx); @@ -354,13 +348,12 @@ impl LspLogToolbarItemView { let label = format!("{} - ({})", name.0, worktree.root_name()); Some( - MouseEventHandler::::new(id.0, cx, move |state, cx| { - Label::new(label, theme.context_menu.item.default.label.clone()).boxed() + MouseEventHandler::::new(id.0, cx, move |state, cx| { + Label::new(label, theme.context_menu.item.default.label.clone()) }) - .on_click(MouseButton::Left, move |_, cx| { - cx.dispatch_action(ActivateLog { server_id: id }) - }) - .boxed(), + .on_click(MouseButton::Left, move |_, view, cx| { + view.activate_log_for_server(id, cx); + }), ) } } From 6ed7f1281f68d96f80e31af62dc2502cd7c335cd Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 21 Apr 2023 16:46:58 -0700 Subject: [PATCH 14/23] Persist LSP logs after log view is closed --- crates/lsp_log/src/lsp_log.rs | 389 +++++++++++++++++++++++----------- crates/theme/src/ui.rs | 34 ++- crates/welcome/src/welcome.rs | 10 +- 3 files changed, 293 insertions(+), 140 deletions(-) diff --git a/crates/lsp_log/src/lsp_log.rs b/crates/lsp_log/src/lsp_log.rs index 14329dbbd3..6030070006 100644 --- a/crates/lsp_log/src/lsp_log.rs +++ b/crates/lsp_log/src/lsp_log.rs @@ -1,4 +1,4 @@ -use collections::HashMap; +use collections::{hash_map, HashMap}; use editor::Editor; use futures::{channel::mpsc, StreamExt}; use gpui::{ @@ -7,15 +7,15 @@ use gpui::{ AnchorCorner, ChildView, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, ParentElement, Stack, }, - platform::MouseButton, - AnyElement, AppContext, Element, Entity, ModelHandle, View, ViewContext, ViewHandle, + platform::{CursorStyle, MouseButton}, + AnyElement, AppContext, Element, Entity, ModelContext, ModelHandle, View, ViewContext, + ViewHandle, WeakModelHandle, }; use language::{Buffer, LanguageServerId, LanguageServerName}; use project::{Project, WorktreeId}; use settings::Settings; use std::{borrow::Cow, sync::Arc}; -use theme::Theme; -use util::ResultExt; +use theme::{ui, Theme}; use workspace::{ item::{Item, ItemHandle}, ToolbarItemLocation, ToolbarItemView, Workspace, @@ -24,11 +24,27 @@ use workspace::{ const SEND_LINE: &str = "// Send:\n"; const RECEIVE_LINE: &str = "// Receive:\n"; +struct LogStore { + projects: HashMap, LogStoreProject>, + io_tx: mpsc::UnboundedSender<(WeakModelHandle, LanguageServerId, bool, String)>, +} + +struct LogStoreProject { + servers: HashMap, + _subscription: gpui::Subscription, +} + +struct LogStoreLanguageServer { + buffer: ModelHandle, + last_message_kind: Option, + _subscription: lsp::Subscription, +} + pub struct LspLogView { - enabled_logs: HashMap, + log_store: ModelHandle, current_server_id: Option, + editor: Option>, project: ModelHandle, - io_tx: mpsc::UnboundedSender<(LanguageServerId, bool, String)>, } pub struct LspLogToolbarItemView { @@ -37,13 +53,6 @@ pub struct LspLogToolbarItemView { project: ModelHandle, } -struct LogState { - buffer: ModelHandle, - editor: ViewHandle, - last_message_kind: Option, - _subscription: lsp::Subscription, -} - #[derive(Copy, Clone, PartialEq, Eq)] enum MessageKind { Send, @@ -53,26 +62,37 @@ enum MessageKind { actions!(log, [OpenLanguageServerLogs]); pub fn init(cx: &mut AppContext) { - cx.add_action(LspLogView::open); + let log_set = cx.add_model(|cx| LogStore::new(cx)); + + cx.add_action( + move |workspace: &mut Workspace, _: &OpenLanguageServerLogs, cx: _| { + let project = workspace.project().read(cx); + if project.is_local() { + workspace.add_item( + Box::new(cx.add_view(|cx| { + LspLogView::new(workspace.project().clone(), log_set.clone(), cx) + })), + cx, + ); + } + }, + ); } -impl LspLogView { - pub fn new(project: ModelHandle, cx: &mut ViewContext) -> Self { +impl LogStore { + fn new(cx: &mut ModelContext) -> Self { let (io_tx, mut io_rx) = mpsc::unbounded(); let this = Self { - enabled_logs: HashMap::default(), - current_server_id: None, + projects: HashMap::default(), io_tx, - project, }; cx.spawn_weak(|this, mut cx| async move { - while let Some((language_server_id, is_output, mut message)) = io_rx.next().await { + while let Some((project, server_id, is_output, mut message)) = io_rx.next().await { if let Some(this) = this.upgrade(&cx) { this.update(&mut cx, |this, cx| { message.push('\n'); - this.on_io(language_server_id, is_output, &message, cx); - }) - .log_err(); + this.on_io(project, server_id, is_output, &message, cx); + }); } } anyhow::Ok(()) @@ -81,95 +101,155 @@ impl LspLogView { this } - fn open( - workspace: &mut Workspace, - _: &OpenLanguageServerLogs, - cx: &mut ViewContext, - ) { - let project = workspace.project().read(cx); - if project.is_remote() { - return; - } - - let log_view = cx.add_view(|cx| Self::new(workspace.project().clone(), cx)); - workspace.add_item(Box::new(log_view), cx); - } - - fn activate_log(&mut self, server_id: LanguageServerId, cx: &mut ViewContext) { - self.enable_logs_for_language_server(server_id, cx); - self.current_server_id = Some(server_id); - cx.notify(); - } - - fn on_io( - &mut self, - language_server_id: LanguageServerId, - is_received: bool, - message: &str, - cx: &mut ViewContext, - ) { - if let Some(state) = self.enabled_logs.get_mut(&language_server_id) { - state.buffer.update(cx, |buffer, cx| { - let kind = if is_received { - MessageKind::Receive - } else { - MessageKind::Send - }; - if state.last_message_kind != Some(kind) { - let len = buffer.len(); - let line = match kind { - MessageKind::Send => SEND_LINE, - MessageKind::Receive => RECEIVE_LINE, - }; - buffer.edit([(len..len, line)], None, cx); - state.last_message_kind = Some(kind); - } - let len = buffer.len(); - buffer.edit([(len..len, message)], None, cx); - }); - } + pub fn has_enabled_logs_for_language_server( + &self, + project: &ModelHandle, + server_id: LanguageServerId, + ) -> bool { + self.projects + .get(&project.downgrade()) + .map_or(false, |store| store.servers.contains_key(&server_id)) } pub fn enable_logs_for_language_server( &mut self, + project: &ModelHandle, server_id: LanguageServerId, + cx: &mut ModelContext, + ) -> Option> { + let server = project.read(cx).language_server_for_id(server_id)?; + let weak_project = project.downgrade(); + let project_logs = match self.projects.entry(weak_project) { + hash_map::Entry::Occupied(entry) => entry.into_mut(), + hash_map::Entry::Vacant(entry) => entry.insert(LogStoreProject { + servers: HashMap::default(), + _subscription: cx.observe_release(&project, move |this, _, cx| { + this.projects.remove(&weak_project); + }), + }), + }; + let server_log_state = project_logs.servers.entry(server_id).or_insert_with(|| { + let io_tx = self.io_tx.clone(); + let language = project.read(cx).languages().language_for_name("JSON"); + let buffer = cx.add_model(|cx| Buffer::new(0, "", cx)); + cx.spawn_weak({ + let buffer = buffer.clone(); + |_, mut cx| async move { + let language = language.await.ok(); + buffer.update(&mut cx, |buffer, cx| { + buffer.set_language(language, cx); + }); + } + }) + .detach(); + + let project = project.downgrade(); + LogStoreLanguageServer { + buffer, + last_message_kind: None, + _subscription: server.on_io(move |is_received, json| { + io_tx + .unbounded_send((project, server_id, is_received, json.to_string())) + .ok(); + }), + } + }); + Some(server_log_state.buffer.clone()) + } + + pub fn disable_logs_for_language_server( + &mut self, + project: &ModelHandle, + server_id: LanguageServerId, + cx: &mut ModelContext, + ) { + let project = project.downgrade(); + if let Some(store) = self.projects.get_mut(&project) { + store.servers.remove(&server_id); + if store.servers.is_empty() { + self.projects.remove(&project); + } + } + } + + fn on_io( + &mut self, + project: WeakModelHandle, + language_server_id: LanguageServerId, + is_received: bool, + message: &str, + cx: &mut AppContext, + ) -> Option<()> { + let state = self + .projects + .get_mut(&project)? + .servers + .get_mut(&language_server_id)?; + state.buffer.update(cx, |buffer, cx| { + let kind = if is_received { + MessageKind::Receive + } else { + MessageKind::Send + }; + if state.last_message_kind != Some(kind) { + let len = buffer.len(); + let line = match kind { + MessageKind::Send => SEND_LINE, + MessageKind::Receive => RECEIVE_LINE, + }; + buffer.edit([(len..len, line)], None, cx); + state.last_message_kind = Some(kind); + } + let len = buffer.len(); + buffer.edit([(len..len, message)], None, cx); + }); + Some(()) + } +} + +impl LspLogView { + fn new( + project: ModelHandle, + log_set: ModelHandle, + _: &mut ViewContext, + ) -> Self { + Self { + project, + log_store: log_set, + editor: None, + current_server_id: None, + } + } + + fn show_logs_for_server(&mut self, server_id: LanguageServerId, cx: &mut ViewContext) { + let buffer = self.log_store.update(cx, |log_set, cx| { + log_set.enable_logs_for_language_server(&self.project, server_id, cx) + }); + if let Some(buffer) = buffer { + self.current_server_id = Some(server_id); + self.editor = Some(cx.add_view(|cx| { + let mut editor = Editor::for_buffer(buffer, Some(self.project.clone()), cx); + editor.set_read_only(true); + editor.move_to_end(&Default::default(), cx); + editor + })); + cx.notify(); + } + } + + fn toggle_logging_for_server( + &mut self, + server_id: LanguageServerId, + enabled: bool, cx: &mut ViewContext, ) { - if let Some(server) = self.project.read(cx).language_server_for_id(server_id) { - self.enabled_logs.entry(server_id).or_insert_with(|| { - let project = self.project.read(cx); - let io_tx = self.io_tx.clone(); - let language = project.languages().language_for_name("JSON"); - let buffer = cx.add_model(|cx| Buffer::new(0, "", cx)); - cx.spawn({ - let buffer = buffer.clone(); - |_, mut cx| async move { - let language = language.await.ok(); - buffer.update(&mut cx, |buffer, cx| { - buffer.set_language(language, cx); - }); - } - }) - .detach(); - let editor = cx.add_view(|cx| { - let mut editor = - Editor::for_buffer(buffer.clone(), Some(self.project.clone()), cx); - editor.set_read_only(true); - editor - }); - - LogState { - buffer, - editor, - last_message_kind: None, - _subscription: server.on_io(move |is_received, json| { - io_tx - .unbounded_send((server_id, is_received, json.to_string())) - .ok(); - }), - } - }); - } + self.log_store.update(cx, |log_store, cx| { + if enabled { + log_store.enable_logs_for_language_server(&self.project, server_id, cx); + } else { + log_store.disable_logs_for_language_server(&self.project, server_id, cx); + } + }); } } @@ -179,12 +259,11 @@ impl View for LspLogView { } fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - if let Some(id) = self.current_server_id { - if let Some(log) = self.enabled_logs.get_mut(&id) { - return ChildView::new(&log.editor, cx).into_any(); - } + if let Some(editor) = &self.editor { + ChildView::new(&editor, cx).into_any() + } else { + Empty::new().into_any() } - Empty::new().into_any() } } @@ -195,7 +274,7 @@ impl Item for LspLogView { style: &theme::Tab, _: &AppContext, ) -> AnyElement { - Label::new("Logs", style.label.clone()).into_any() + Label::new("LSP Logs", style.label.clone()).into_any() } } @@ -228,10 +307,24 @@ impl View for LspLogToolbarItemView { let theme = cx.global::().theme.clone(); let Some(log_view) = self.log_view.as_ref() else { return Empty::new().into_any() }; let project = self.project.read(cx); - let mut language_servers = project.language_servers().collect::>(); - language_servers.sort_by_key(|a| a.0); + let log_view = log_view.read(cx); + let log_store = log_view.log_store.read(cx); - let current_server_id = log_view.read(cx).current_server_id; + let mut language_servers = project + .language_servers() + .map(|(id, name, worktree)| { + ( + id, + name, + worktree, + log_store.has_enabled_logs_for_language_server(&self.project, id), + ) + }) + .collect::>(); + language_servers.sort_by_key(|a| (a.0, a.2)); + language_servers.dedup_by_key(|a| a.0); + + let current_server_id = log_view.current_server_id; let current_server = current_server_id.and_then(|current_server_id| { if let Ok(ix) = language_servers.binary_search_by_key(¤t_server_id, |e| e.0) { Some(language_servers[ix].clone()) @@ -252,11 +345,13 @@ impl View for LspLogToolbarItemView { Overlay::new( Flex::column() .with_children(language_servers.into_iter().filter_map( - |(id, name, worktree_id)| { + |(id, name, worktree_id, logging_enabled)| { Self::render_language_server_menu_item( id, name, worktree_id, + logging_enabled, + Some(id) == current_server_id, &self.project, &theme, cx, @@ -266,19 +361,22 @@ impl View for LspLogToolbarItemView { .contained() .with_style(theme.contacts_popover.container) .constrained() - .with_width(200.) + .with_width(400.) .with_height(400.), ) .with_fit_mode(OverlayFitMode::SwitchAnchor) - .with_anchor_corner(AnchorCorner::TopRight) + .with_anchor_corner(AnchorCorner::TopLeft) .with_z_index(999) .aligned() .bottom() - .right(), + .left(), ) } else { None }) + .aligned() + .left() + .clipped() .into_any() } } @@ -297,10 +395,29 @@ impl LspLogToolbarItemView { cx.notify(); } - fn activate_log_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { + fn toggle_logging_for_server( + &mut self, + id: LanguageServerId, + enabled: bool, + cx: &mut ViewContext, + ) { if let Some(log_view) = &self.log_view { log_view.update(cx, |log_view, cx| { - log_view.activate_log(id, cx); + log_view.toggle_logging_for_server(id, enabled, cx); + if !enabled && Some(id) == log_view.current_server_id { + log_view.current_server_id = None; + cx.notify(); + } + }); + self.menu_open = false; + } + cx.notify(); + } + + fn show_logs_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { + if let Some(log_view) = &self.log_view { + log_view.update(cx, |log_view, cx| { + log_view.show_logs_for_server(id, cx); }); self.menu_open = false; } @@ -308,7 +425,7 @@ impl LspLogToolbarItemView { } fn render_language_server_menu_header( - current_server: Option<(LanguageServerId, LanguageServerName, WorktreeId)>, + current_server: Option<(LanguageServerId, LanguageServerName, WorktreeId, bool)>, project: &ModelHandle, theme: &Arc, cx: &mut ViewContext, @@ -317,7 +434,7 @@ impl LspLogToolbarItemView { MouseEventHandler::::new(0, cx, move |state, cx| { let project = project.read(cx); let label: Cow = current_server - .and_then(|(_, server_name, worktree_id)| { + .and_then(|(_, server_name, worktree_id, _)| { let worktree = project.worktree_for_id(worktree_id, cx)?; let worktree = &worktree.read(cx); Some(format!("{} - ({})", server_name.0, worktree.root_name()).into()) @@ -325,6 +442,7 @@ impl LspLogToolbarItemView { .unwrap_or_else(|| "No server selected".into()); Label::new(label, theme.context_menu.item.default.label.clone()) }) + .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, view, cx| { view.toggle_menu(cx); }) @@ -334,6 +452,8 @@ impl LspLogToolbarItemView { id: LanguageServerId, name: LanguageServerName, worktree_id: WorktreeId, + logging_enabled: bool, + is_selected: bool, project: &ModelHandle, theme: &Arc, cx: &mut ViewContext, @@ -349,15 +469,34 @@ impl LspLogToolbarItemView { Some( MouseEventHandler::::new(id.0, cx, move |state, cx| { - Label::new(label, theme.context_menu.item.default.label.clone()) + let item_style = theme.context_menu.item.style_for(state, is_selected); + Flex::row() + .with_child(ui::checkbox_with_label::( + Empty::new(), + &theme.welcome.checkbox, + logging_enabled, + id.0, + cx, + move |this, enabled, cx| { + this.toggle_logging_for_server(id, enabled, cx); + }, + )) + .with_child(Label::new(label, item_style.label.clone())) + .contained() + .with_style(item_style.container) }) + .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, view, cx| { - view.activate_log_for_server(id, cx); + view.show_logs_for_server(id, cx); }), ) } } +impl Entity for LogStore { + type Event = (); +} + impl Entity for LspLogView { type Event = (); } diff --git a/crates/theme/src/ui.rs b/crates/theme/src/ui.rs index 4e705b12b8..0f58ee08ad 100644 --- a/crates/theme/src/ui.rs +++ b/crates/theme/src/ui.rs @@ -27,28 +27,40 @@ pub struct CheckboxStyle { pub hovered_and_checked: ContainerStyle, } -pub fn checkbox( +pub fn checkbox( label: &'static str, style: &CheckboxStyle, checked: bool, + id: usize, cx: &mut ViewContext, - change: fn(checked: bool, cx: &mut EventContext) -> (), -) -> MouseEventHandler { + change: F, +) -> MouseEventHandler +where + Tag: 'static, + V: View, + F: 'static + Fn(&mut V, bool, &mut EventContext), +{ let label = Label::new(label, style.label.text.clone()) .contained() .with_style(style.label.container); - - checkbox_with_label(label, style, checked, cx, change) + checkbox_with_label(label, style, checked, id, cx, change) } -pub fn checkbox_with_label, V: View>( +pub fn checkbox_with_label( label: D, style: &CheckboxStyle, checked: bool, + id: usize, cx: &mut ViewContext, - change: fn(checked: bool, cx: &mut EventContext) -> (), -) -> MouseEventHandler { - MouseEventHandler::new(0, cx, |state, _| { + change: F, +) -> MouseEventHandler +where + Tag: 'static, + D: Element, + V: View, + F: 'static + Fn(&mut V, bool, &mut EventContext), +{ + MouseEventHandler::new(id, cx, |state, _| { let indicator = if checked { svg(&style.icon) } else { @@ -75,8 +87,8 @@ pub fn checkbox_with_label, V: View>( .with_child(label) .align_children_center() }) - .on_click(platform::MouseButton::Left, move |_, _, cx| { - change(!checked, cx) + .on_click(platform::MouseButton::Left, move |_, view, cx| { + change(view, !checked, cx) }) .with_cursor_style(platform::CursorStyle::PointingHand) } diff --git a/crates/welcome/src/welcome.rs b/crates/welcome/src/welcome.rs index d75bbea56e..629e6f3989 100644 --- a/crates/welcome/src/welcome.rs +++ b/crates/welcome/src/welcome.rs @@ -126,7 +126,7 @@ impl View for WelcomePage { .with_child( Flex::column() .with_child( - theme::ui::checkbox_with_label::( + theme::ui::checkbox_with_label::( Flex::column() .with_child( Label::new( @@ -146,8 +146,9 @@ impl View for WelcomePage { ), &theme.welcome.checkbox, metrics, + 0, cx, - |checked, cx| { + |_, checked, cx| { SettingsFile::update(cx, move |file| { file.telemetry.set_metrics(checked) }) @@ -157,12 +158,13 @@ impl View for WelcomePage { .with_style(theme.welcome.checkbox_container), ) .with_child( - theme::ui::checkbox::( + theme::ui::checkbox::( "Send crash reports", &theme.welcome.checkbox, diagnostics, + 0, cx, - |checked, cx| { + |_, checked, cx| { SettingsFile::update(cx, move |file| { file.telemetry.set_diagnostics(checked) }) From e7cb996044e924cc7116fc6f67028450703a13f1 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 21 Apr 2023 17:03:37 -0700 Subject: [PATCH 15/23] Improve the LSP log UI --- crates/lsp_log/src/lsp_log.rs | 67 ++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 25 deletions(-) diff --git a/crates/lsp_log/src/lsp_log.rs b/crates/lsp_log/src/lsp_log.rs index 6030070006..0efcd3afc8 100644 --- a/crates/lsp_log/src/lsp_log.rs +++ b/crates/lsp_log/src/lsp_log.rs @@ -123,7 +123,7 @@ impl LogStore { hash_map::Entry::Occupied(entry) => entry.into_mut(), hash_map::Entry::Vacant(entry) => entry.insert(LogStoreProject { servers: HashMap::default(), - _subscription: cx.observe_release(&project, move |this, _, cx| { + _subscription: cx.observe_release(&project, move |this, _, _| { this.projects.remove(&weak_project); }), }), @@ -161,7 +161,7 @@ impl LogStore { &mut self, project: &ModelHandle, server_id: LanguageServerId, - cx: &mut ModelContext, + _: &mut ModelContext, ) { let project = project.downgrade(); if let Some(store) = self.projects.get_mut(&project) { @@ -333,6 +333,8 @@ impl View for LspLogToolbarItemView { } }); + enum Menu {} + Stack::new() .with_child(Self::render_language_server_menu_header( current_server, @@ -343,26 +345,32 @@ impl View for LspLogToolbarItemView { .with_children(if self.menu_open { Some( Overlay::new( - Flex::column() - .with_children(language_servers.into_iter().filter_map( - |(id, name, worktree_id, logging_enabled)| { - Self::render_language_server_menu_item( - id, - name, - worktree_id, - logging_enabled, - Some(id) == current_server_id, - &self.project, - &theme, - cx, - ) - }, - )) - .contained() - .with_style(theme.contacts_popover.container) - .constrained() - .with_width(400.) - .with_height(400.), + MouseEventHandler::::new(0, cx, move |_, cx| { + Flex::column() + .with_children(language_servers.into_iter().filter_map( + |(id, name, worktree_id, logging_enabled)| { + Self::render_language_server_menu_item( + id, + name, + worktree_id, + logging_enabled, + Some(id) == current_server_id, + &self.project, + &theme, + cx, + ) + }, + )) + .contained() + .with_style(theme.context_menu.container) + .constrained() + .with_width(400.) + .with_height(400.) + }) + .on_down_out(MouseButton::Left, |_, this, cx| { + this.menu_open = false; + cx.notify() + }), ) .with_fit_mode(OverlayFitMode::SwitchAnchor) .with_anchor_corner(AnchorCorner::TopLeft) @@ -406,10 +414,10 @@ impl LspLogToolbarItemView { log_view.toggle_logging_for_server(id, enabled, cx); if !enabled && Some(id) == log_view.current_server_id { log_view.current_server_id = None; + log_view.editor = None; cx.notify(); } }); - self.menu_open = false; } cx.notify(); } @@ -440,7 +448,15 @@ impl LspLogToolbarItemView { Some(format!("{} - ({})", server_name.0, worktree.root_name()).into()) }) .unwrap_or_else(|| "No server selected".into()); - Label::new(label, theme.context_menu.item.default.label.clone()) + Label::new( + label, + theme + .context_menu + .item + .style_for(state, false) + .label + .clone(), + ) }) .with_cursor_style(CursorStyle::PointingHand) .on_click(MouseButton::Left, move |_, view, cx| { @@ -481,7 +497,8 @@ impl LspLogToolbarItemView { this.toggle_logging_for_server(id, enabled, cx); }, )) - .with_child(Label::new(label, item_style.label.clone())) + .with_child(Label::new(label, item_style.label.clone()).aligned().left()) + .align_children_center() .contained() .with_style(item_style.container) }) From 1793c5ff6cc802a3613ad1859c570fd05000af08 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 21 Apr 2023 17:13:11 -0700 Subject: [PATCH 16/23] Upgrade tree-sitter-json --- Cargo.lock | 2 +- crates/zed/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5713bddd0d..530042885e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7259,7 +7259,7 @@ dependencies = [ [[package]] name = "tree-sitter-json" version = "0.20.0" -source = "git+https://github.com/tree-sitter/tree-sitter-json?rev=137e1ce6a02698fc246cdb9c6b886ed1de9a1ed8#137e1ce6a02698fc246cdb9c6b886ed1de9a1ed8" +source = "git+https://github.com/tree-sitter/tree-sitter-json?rev=40a81c01a40ac48744e0c8ccabbaba1920441199#40a81c01a40ac48744e0c8ccabbaba1920441199" dependencies = [ "cc", "tree-sitter", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index fe6f7a8758..51a41db2b8 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -110,7 +110,7 @@ tree-sitter-css = { git = "https://github.com/tree-sitter/tree-sitter-css", rev tree-sitter-elixir = { git = "https://github.com/elixir-lang/tree-sitter-elixir", rev = "05e3631c6a0701c1fa518b0fee7be95a2ceef5e2" } tree-sitter-embedded-template = "0.20.0" tree-sitter-go = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "aeb2f33b366fd78d5789ff104956ce23508b85db" } -tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json", rev = "137e1ce6a02698fc246cdb9c6b886ed1de9a1ed8" } +tree-sitter-json = { git = "https://github.com/tree-sitter/tree-sitter-json", rev = "40a81c01a40ac48744e0c8ccabbaba1920441199" } tree-sitter-rust = "0.20.3" tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" } tree-sitter-python = "0.20.2" From f3ada727854ce2376596c60f9b1c4c758511961b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 24 Apr 2023 10:04:45 -0700 Subject: [PATCH 17/23] Avoid accidentally dropping subscription when detaching it --- crates/lsp/src/lsp.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 86352d225d..f4f538b061 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -59,14 +59,13 @@ pub struct LanguageServer { pub struct LanguageServerId(pub usize); pub enum Subscription { - Detached, Notification { method: &'static str, - notification_handlers: Arc>>, + notification_handlers: Option>>>, }, Io { id: usize, - io_handlers: Weak>>, + io_handlers: Option>>>, }, } @@ -501,7 +500,7 @@ impl LanguageServer { self.io_handlers.lock().insert(id, Box::new(f)); Subscription::Io { id, - io_handlers: Arc::downgrade(&self.io_handlers), + io_handlers: Some(Arc::downgrade(&self.io_handlers)), } } @@ -533,7 +532,7 @@ impl LanguageServer { ); Subscription::Notification { method, - notification_handlers: self.notification_handlers.clone(), + notification_handlers: Some(self.notification_handlers.clone()), } } @@ -615,7 +614,7 @@ impl LanguageServer { ); Subscription::Notification { method, - notification_handlers: self.notification_handlers.clone(), + notification_handlers: Some(self.notification_handlers.clone()), } } @@ -726,8 +725,14 @@ impl Drop for LanguageServer { } impl Subscription { - pub fn detach(mut self) { - *(&mut self) = Self::Detached; + pub fn detach(&mut self) { + match self { + Subscription::Notification { + notification_handlers, + .. + } => *notification_handlers = None, + Subscription::Io { io_handlers, .. } => *io_handlers = None, + } } } @@ -740,15 +745,16 @@ impl fmt::Display for LanguageServerId { impl Drop for Subscription { fn drop(&mut self) { match self { - Subscription::Detached => {} Subscription::Notification { method, notification_handlers, } => { - notification_handlers.lock().remove(method); + if let Some(handlers) = notification_handlers { + handlers.lock().remove(method); + } } Subscription::Io { id, io_handlers } => { - if let Some(io_handlers) = io_handlers.upgrade() { + if let Some(io_handlers) = io_handlers.as_ref().and_then(|h| h.upgrade()) { io_handlers.lock().remove(id); } } From ce34bf62fe57d7c1303cb5231c7a40ed51d13aef Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 24 Apr 2023 13:18:37 -0700 Subject: [PATCH 18/23] Add failing test for diagnostic message ordering Co-authored-by: Julia Risley --- crates/collab/src/tests/integration_tests.rs | 140 ++++++++++++++++++- 1 file changed, 139 insertions(+), 1 deletion(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index d42c4b3ebc..5c19226960 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -32,7 +32,10 @@ use std::{ env, future, mem, path::{Path, PathBuf}, rc::Rc, - sync::Arc, + sync::{ + atomic::{AtomicBool, Ordering::SeqCst}, + Arc, + }, }; use unindent::Unindent as _; use workspace::{ @@ -3636,6 +3639,141 @@ async fn test_collaborating_with_diagnostics( }); } +#[gpui::test(iterations = 10)] +async fn test_collaborating_with_lsp_progress_updates_and_diagnostics_ordering( + deterministic: Arc, + cx_a: &mut TestAppContext, + cx_b: &mut TestAppContext, +) { + deterministic.forbid_parking(); + let mut server = TestServer::start(&deterministic).await; + let client_a = server.create_client(cx_a, "user_a").await; + let client_b = server.create_client(cx_b, "user_b").await; + server + .create_room(&mut [(&client_a, cx_a), (&client_b, cx_b)]) + .await; + + // Set up a fake language server. + let mut language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_language_servers = language + .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { + disk_based_diagnostics_progress_token: Some("the-disk-based-token".into()), + disk_based_diagnostics_sources: vec!["the-disk-based-diagnostics-source".into()], + ..Default::default() + })) + .await; + client_a.language_registry.add(Arc::new(language)); + + let file_names = &["one.rs", "two.rs", "three.rs", "four.rs", "five.rs"]; + client_a + .fs + .insert_tree( + "/test", + json!({ + "one.rs": "const ONE: usize = 1;", + "two.rs": "const TWO: usize = 2;", + "three.rs": "const THREE: usize = 3;", + "four.rs": "const FOUR: usize = 3;", + "five.rs": "const FIVE: usize = 3;", + }), + ) + .await; + + let (project_a, worktree_id) = client_a.build_local_project("/test", cx_a).await; + + // Share a project as client A + let active_call_a = cx_a.read(ActiveCall::global); + let project_id = active_call_a + .update(cx_a, |call, cx| call.share_project(project_a.clone(), cx)) + .await + .unwrap(); + + // Join the project as client B and open all three files. + let project_b = client_b.build_remote_project(project_id, cx_b).await; + let guest_buffers = futures::future::try_join_all(file_names.iter().map(|file_name| { + project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, file_name), cx)) + })) + .await + .unwrap(); + + // Simulate a language server reporting errors for a file. + let fake_language_server = fake_language_servers.next().await.unwrap(); + fake_language_server + .request::(lsp::WorkDoneProgressCreateParams { + token: lsp::NumberOrString::String("the-disk-based-token".to_string()), + }) + .await + .unwrap(); + fake_language_server.notify::(lsp::ProgressParams { + token: lsp::NumberOrString::String("the-disk-based-token".to_string()), + value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::Begin( + lsp::WorkDoneProgressBegin { + title: "Progress Began".into(), + ..Default::default() + }, + )), + }); + for file_name in file_names { + fake_language_server.notify::( + lsp::PublishDiagnosticsParams { + uri: lsp::Url::from_file_path(Path::new("/test").join(file_name)).unwrap(), + version: None, + diagnostics: vec![lsp::Diagnostic { + severity: Some(lsp::DiagnosticSeverity::WARNING), + source: Some("the-disk-based-diagnostics-source".into()), + range: lsp::Range::new(lsp::Position::new(0, 0), lsp::Position::new(0, 0)), + message: "message one".to_string(), + ..Default::default() + }], + }, + ); + } + fake_language_server.notify::(lsp::ProgressParams { + token: lsp::NumberOrString::String("the-disk-based-token".to_string()), + value: lsp::ProgressParamsValue::WorkDone(lsp::WorkDoneProgress::End( + lsp::WorkDoneProgressEnd { message: None }, + )), + }); + + // When the "disk base diagnostics finished" message is received, the buffers' + // diagnostics are expected to be present. + let disk_based_diagnostics_finished = Arc::new(AtomicBool::new(false)); + project_b.update(cx_b, { + let project_b = project_b.clone(); + let disk_based_diagnostics_finished = disk_based_diagnostics_finished.clone(); + move |_, cx| { + cx.subscribe(&project_b, move |_, _, event, cx| { + if let project::Event::DiskBasedDiagnosticsFinished { .. } = event { + disk_based_diagnostics_finished.store(true, SeqCst); + for buffer in &guest_buffers { + assert_eq!( + buffer + .read(cx) + .snapshot() + .diagnostics_in_range::<_, usize>(0..5, false) + .count(), + 1, + "expected a diagnostic for buffer {:?}", + buffer.read(cx).file().unwrap().path(), + ); + } + } + }) + .detach(); + } + }); + + deterministic.run_until_parked(); + assert!(disk_based_diagnostics_finished.load(SeqCst)); +} + #[gpui::test(iterations = 10)] async fn test_collaborating_with_completion( deterministic: Arc, From a8ddba55d8728591ae1da62ce16673c2d7c9cb81 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 24 Apr 2023 13:52:03 -0700 Subject: [PATCH 19/23] Send language server updates via the same task that sends buffer operations Co-authored-by: Julia Risley --- crates/project/src/project.rs | 225 +++++++++++++++++++++------------- 1 file changed, 137 insertions(+), 88 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index aad9a50856..976554eab4 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -142,6 +142,10 @@ enum BufferMessage { buffer_id: u64, operation: proto::Operation, }, + LanguageServerUpdate { + language_server_id: LanguageServerId, + message: proto::update_language_server::Variant, + }, Resync, } @@ -1791,9 +1795,35 @@ impl Project { ) -> Option<()> { const MAX_BATCH_SIZE: usize = 128; - let mut needs_resync_with_host = false; let mut operations_by_buffer_id = HashMap::default(); + async fn flush_operations( + this: &ModelHandle, + operations_by_buffer_id: &mut HashMap>, + needs_resync_with_host: &mut bool, + is_local: bool, + cx: &AsyncAppContext, + ) { + for (buffer_id, operations) in operations_by_buffer_id.drain() { + let request = this.read_with(cx, |this, _| { + let project_id = this.remote_id()?; + Some(this.client.request(proto::UpdateBuffer { + buffer_id, + project_id, + operations, + })) + }); + if let Some(request) = request { + if request.await.is_err() && !is_local { + *needs_resync_with_host = true; + break; + } + } + } + } + + let mut needs_resync_with_host = false; let mut changes = rx.ready_chunks(MAX_BATCH_SIZE); + while let Some(changes) = changes.next().await { let this = this.upgrade(&mut cx)?; let is_local = this.read_with(&cx, |this, _| this.is_local()); @@ -1813,6 +1843,7 @@ impl Project { .or_insert(Vec::new()) .push(operation); } + BufferMessage::Resync => { operations_by_buffer_id.clear(); if this @@ -1823,25 +1854,43 @@ impl Project { needs_resync_with_host = false; } } - } - } - for (buffer_id, operations) in operations_by_buffer_id.drain() { - let request = this.read_with(&cx, |this, _| { - let project_id = this.remote_id()?; - Some(this.client.request(proto::UpdateBuffer { - buffer_id, - project_id, - operations, - })) - }); - if let Some(request) = request { - if request.await.is_err() && !is_local { - needs_resync_with_host = true; - break; + BufferMessage::LanguageServerUpdate { + language_server_id, + message, + } => { + flush_operations( + &this, + &mut operations_by_buffer_id, + &mut needs_resync_with_host, + is_local, + &cx, + ) + .await; + + this.read_with(&cx, |this, _| { + if let Some(project_id) = this.remote_id() { + this.client + .send(proto::UpdateLanguageServer { + project_id, + language_server_id: language_server_id.0 as u64, + variant: Some(message), + }) + .log_err(); + } + }); } } } + + flush_operations( + &this, + &mut operations_by_buffer_id, + &mut needs_resync_with_host, + is_local, + &cx, + ) + .await; } None @@ -1962,19 +2011,24 @@ impl Project { Duration::from_secs(1); let task = cx.spawn_weak(|this, mut cx| async move { - cx.background().timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE).await; - if let Some(this) = this.upgrade(&cx) { - this.update(&mut cx, |this, cx | { - this.disk_based_diagnostics_finished(language_server_id, cx); - this.broadcast_language_server_update( - language_server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( - proto::LspDiskBasedDiagnosticsUpdated {}, - ), - ); - }); - } - }); + cx.background().timer(DISK_BASED_DIAGNOSTICS_DEBOUNCE).await; + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |this, cx| { + this.disk_based_diagnostics_finished( + language_server_id, + cx, + ); + this.buffer_changes_tx + .unbounded_send( + BufferMessage::LanguageServerUpdate { + language_server_id, + message:proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(Default::default()) + }, + ) + .ok(); + }); + } + }); *simulate_disk_based_diagnostics_completion = Some(task); } } @@ -2609,7 +2663,7 @@ impl Project { fn on_lsp_progress( &mut self, progress: lsp::ProgressParams, - server_id: LanguageServerId, + language_server_id: LanguageServerId, disk_based_diagnostics_progress_token: Option, cx: &mut ModelContext, ) { @@ -2622,7 +2676,7 @@ impl Project { }; let lsp::ProgressParamsValue::WorkDone(progress) = progress.value; let language_server_status = - if let Some(status) = self.language_server_statuses.get_mut(&server_id) { + if let Some(status) = self.language_server_statuses.get_mut(&language_server_id) { status } else { return; @@ -2642,16 +2696,16 @@ impl Project { lsp::WorkDoneProgress::Begin(report) => { if is_disk_based_diagnostics_progress { language_server_status.has_pending_diagnostic_updates = true; - self.disk_based_diagnostics_started(server_id, cx); - self.broadcast_language_server_update( - server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating( - proto::LspDiskBasedDiagnosticsUpdating {}, - ), - ); + self.disk_based_diagnostics_started(language_server_id, cx); + self.buffer_changes_tx + .unbounded_send(BufferMessage::LanguageServerUpdate { + language_server_id, + message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(Default::default()) + }) + .ok(); } else { self.on_lsp_work_start( - server_id, + language_server_id, token.clone(), LanguageServerProgress { message: report.message.clone(), @@ -2660,20 +2714,24 @@ impl Project { }, cx, ); - self.broadcast_language_server_update( - server_id, - proto::update_language_server::Variant::WorkStart(proto::LspWorkStart { - token, - message: report.message, - percentage: report.percentage.map(|p| p as u32), - }), - ); + self.buffer_changes_tx + .unbounded_send(BufferMessage::LanguageServerUpdate { + language_server_id, + message: proto::update_language_server::Variant::WorkStart( + proto::LspWorkStart { + token, + message: report.message, + percentage: report.percentage.map(|p| p as u32), + }, + ), + }) + .ok(); } } lsp::WorkDoneProgress::Report(report) => { if !is_disk_based_diagnostics_progress { self.on_lsp_work_progress( - server_id, + language_server_id, token.clone(), LanguageServerProgress { message: report.message.clone(), @@ -2682,16 +2740,18 @@ impl Project { }, cx, ); - self.broadcast_language_server_update( - server_id, - proto::update_language_server::Variant::WorkProgress( - proto::LspWorkProgress { - token, - message: report.message, - percentage: report.percentage.map(|p| p as u32), - }, - ), - ); + self.buffer_changes_tx + .unbounded_send(BufferMessage::LanguageServerUpdate { + language_server_id, + message: proto::update_language_server::Variant::WorkProgress( + proto::LspWorkProgress { + token, + message: report.message, + percentage: report.percentage.map(|p| p as u32), + }, + ), + }) + .ok(); } } lsp::WorkDoneProgress::End(_) => { @@ -2699,21 +2759,26 @@ impl Project { if is_disk_based_diagnostics_progress { language_server_status.has_pending_diagnostic_updates = false; - self.disk_based_diagnostics_finished(server_id, cx); - self.broadcast_language_server_update( - server_id, - proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( - proto::LspDiskBasedDiagnosticsUpdated {}, - ), - ); + self.disk_based_diagnostics_finished(language_server_id, cx); + self.buffer_changes_tx + .unbounded_send(BufferMessage::LanguageServerUpdate { + language_server_id, + message: + proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( + Default::default(), + ), + }) + .ok(); } else { - self.on_lsp_work_end(server_id, token.clone(), cx); - self.broadcast_language_server_update( - server_id, - proto::update_language_server::Variant::WorkEnd(proto::LspWorkEnd { - token, - }), - ); + self.on_lsp_work_end(language_server_id, token.clone(), cx); + self.buffer_changes_tx + .unbounded_send(BufferMessage::LanguageServerUpdate { + language_server_id, + message: proto::update_language_server::Variant::WorkEnd( + proto::LspWorkEnd { token }, + ), + }) + .ok(); } } } @@ -2822,22 +2887,6 @@ impl Project { }) } - fn broadcast_language_server_update( - &self, - language_server_id: LanguageServerId, - event: proto::update_language_server::Variant, - ) { - if let Some(project_id) = self.remote_id() { - self.client - .send(proto::UpdateLanguageServer { - project_id, - language_server_id: language_server_id.0 as u64, - variant: Some(event), - }) - .log_err(); - } - } - pub fn language_server_statuses( &self, ) -> impl DoubleEndedIterator { From 7bd51851c2bce6cee5d63b09a26c157b92d2d00c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 24 Apr 2023 13:54:47 -0700 Subject: [PATCH 20/23] :art: Co-authored-by: Julia Risley --- crates/project/src/project.rs | 59 ++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 976554eab4..c82855b03c 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -93,7 +93,7 @@ pub trait Item { pub struct Project { worktrees: Vec, active_entry: Option, - buffer_changes_tx: mpsc::UnboundedSender, + buffer_ordered_messages_tx: mpsc::UnboundedSender, languages: Arc, language_servers: HashMap, language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>, @@ -137,7 +137,8 @@ struct LspBufferSnapshot { snapshot: TextBufferSnapshot, } -enum BufferMessage { +/// Message ordered with respect to buffer operations +enum BufferOrderedMessage { Operation { buffer_id: u64, operation: proto::Operation, @@ -447,11 +448,11 @@ impl Project { ) -> ModelHandle { cx.add_model(|cx: &mut ModelContext| { let (tx, rx) = mpsc::unbounded(); - cx.spawn_weak(|this, cx| Self::send_buffer_messages(this, rx, cx)) + cx.spawn_weak(|this, cx| Self::send_buffer_ordered_messages(this, rx, cx)) .detach(); Self { worktrees: Default::default(), - buffer_changes_tx: tx, + buffer_ordered_messages_tx: tx, collaborators: Default::default(), opened_buffers: Default::default(), shared_buffers: Default::default(), @@ -515,11 +516,11 @@ impl Project { } let (tx, rx) = mpsc::unbounded(); - cx.spawn_weak(|this, cx| Self::send_buffer_messages(this, rx, cx)) + cx.spawn_weak(|this, cx| Self::send_buffer_ordered_messages(this, rx, cx)) .detach(); let mut this = Self { worktrees: Vec::new(), - buffer_changes_tx: tx, + buffer_ordered_messages_tx: tx, loading_buffers_by_path: Default::default(), opened_buffer: watch::channel(), shared_buffers: Default::default(), @@ -1172,8 +1173,8 @@ impl Project { ) }) .collect(); - self.buffer_changes_tx - .unbounded_send(BufferMessage::Resync) + self.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::Resync) .unwrap(); cx.notify(); Ok(()) @@ -1788,9 +1789,9 @@ impl Project { } } - async fn send_buffer_messages( + async fn send_buffer_ordered_messages( this: WeakModelHandle, - rx: UnboundedReceiver, + rx: UnboundedReceiver, mut cx: AsyncAppContext, ) -> Option<()> { const MAX_BATCH_SIZE: usize = 128; @@ -1830,7 +1831,7 @@ impl Project { for change in changes { match change { - BufferMessage::Operation { + BufferOrderedMessage::Operation { buffer_id, operation, } => { @@ -1844,7 +1845,7 @@ impl Project { .push(operation); } - BufferMessage::Resync => { + BufferOrderedMessage::Resync => { operations_by_buffer_id.clear(); if this .update(&mut cx, |this, cx| this.synchronize_remote_buffers(cx)) @@ -1855,7 +1856,7 @@ impl Project { } } - BufferMessage::LanguageServerUpdate { + BufferOrderedMessage::LanguageServerUpdate { language_server_id, message, } => { @@ -1904,8 +1905,8 @@ impl Project { ) -> Option<()> { match event { BufferEvent::Operation(operation) => { - self.buffer_changes_tx - .unbounded_send(BufferMessage::Operation { + self.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::Operation { buffer_id: buffer.read(cx).remote_id(), operation: language::proto::serialize_operation(operation), }) @@ -2018,9 +2019,9 @@ impl Project { language_server_id, cx, ); - this.buffer_changes_tx + this.buffer_ordered_messages_tx .unbounded_send( - BufferMessage::LanguageServerUpdate { + BufferOrderedMessage::LanguageServerUpdate { language_server_id, message:proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(Default::default()) }, @@ -2697,8 +2698,8 @@ impl Project { if is_disk_based_diagnostics_progress { language_server_status.has_pending_diagnostic_updates = true; self.disk_based_diagnostics_started(language_server_id, cx); - self.buffer_changes_tx - .unbounded_send(BufferMessage::LanguageServerUpdate { + self.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::LanguageServerUpdate { language_server_id, message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdating(Default::default()) }) @@ -2714,8 +2715,8 @@ impl Project { }, cx, ); - self.buffer_changes_tx - .unbounded_send(BufferMessage::LanguageServerUpdate { + self.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::LanguageServerUpdate { language_server_id, message: proto::update_language_server::Variant::WorkStart( proto::LspWorkStart { @@ -2740,8 +2741,8 @@ impl Project { }, cx, ); - self.buffer_changes_tx - .unbounded_send(BufferMessage::LanguageServerUpdate { + self.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::LanguageServerUpdate { language_server_id, message: proto::update_language_server::Variant::WorkProgress( proto::LspWorkProgress { @@ -2760,8 +2761,8 @@ impl Project { if is_disk_based_diagnostics_progress { language_server_status.has_pending_diagnostic_updates = false; self.disk_based_diagnostics_finished(language_server_id, cx); - self.buffer_changes_tx - .unbounded_send(BufferMessage::LanguageServerUpdate { + self.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::LanguageServerUpdate { language_server_id, message: proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated( @@ -2771,8 +2772,8 @@ impl Project { .ok(); } else { self.on_lsp_work_end(language_server_id, token.clone(), cx); - self.buffer_changes_tx - .unbounded_send(BufferMessage::LanguageServerUpdate { + self.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::LanguageServerUpdate { language_server_id, message: proto::update_language_server::Variant::WorkEnd( proto::LspWorkEnd { token }, @@ -4915,8 +4916,8 @@ impl Project { if is_host { this.opened_buffers .retain(|_, buffer| !matches!(buffer, OpenBuffer::Operations(_))); - this.buffer_changes_tx - .unbounded_send(BufferMessage::Resync) + this.buffer_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::Resync) .unwrap(); } From dd3f6ff4ca6a06aa73b8e14700e10d1c2ccc6aee Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 24 Apr 2023 16:09:12 -0700 Subject: [PATCH 21/23] Avoid treating snippet completions' details as their variable types --- crates/zed/src/languages/rust.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/zed/src/languages/rust.rs b/crates/zed/src/languages/rust.rs index d5a6773129..3808444ad9 100644 --- a/crates/zed/src/languages/rust.rs +++ b/crates/zed/src/languages/rust.rs @@ -133,7 +133,8 @@ impl LspAdapter for RustLspAdapter { }); } Some(lsp::CompletionItemKind::CONSTANT | lsp::CompletionItemKind::VARIABLE) - if completion.detail.is_some() => + if completion.detail.is_some() + && completion.insert_text_format != Some(lsp::InsertTextFormat::SNIPPET) => { let detail = completion.detail.as_ref().unwrap(); let name = &completion.label; From ebbe52e6b0a33458956e1db400ba07f0e33398c3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 24 Apr 2023 17:41:55 -0700 Subject: [PATCH 22/23] :art: Specify more dependencies at the workspace level --- Cargo.lock | 3 --- Cargo.toml | 20 +++++++++++--- crates/activity_indicator/Cargo.toml | 4 +-- crates/assets/Cargo.toml | 3 +-- crates/auto_update/Cargo.toml | 16 +++++------ crates/call/Cargo.toml | 8 +++--- crates/cli/Cargo.toml | 6 ++--- crates/client/Cargo.toml | 27 ++++++++++--------- crates/clock/Cargo.toml | 2 +- crates/collab/Cargo.toml | 32 +++++++++++----------- crates/collab_ui/Cargo.toml | 13 ++++----- crates/command_palette/Cargo.toml | 6 ++--- crates/context_menu/Cargo.toml | 2 +- crates/copilot/Cargo.toml | 12 ++++----- crates/copilot_button/Cargo.toml | 6 ++--- crates/db/Cargo.toml | 20 +++++++------- crates/diagnostics/Cargo.toml | 14 +++++----- crates/editor/Cargo.toml | 33 ++++++++++++----------- crates/feedback/Cargo.toml | 14 +++++----- crates/file_finder/Cargo.toml | 8 +++--- crates/fs/Cargo.toml | 22 +++++++-------- crates/fsevent/Cargo.toml | 4 +-- crates/git/Cargo.toml | 16 +++++------ crates/go_to_line/Cargo.toml | 2 +- crates/gpui/Cargo.toml | 34 +++++++++++------------ crates/install_cli/Cargo.toml | 6 ++--- crates/journal/Cargo.toml | 4 +-- crates/language/Cargo.toml | 36 ++++++++++++------------- crates/language_selector/Cargo.toml | 2 +- crates/live_kit_client/Cargo.toml | 34 +++++++++++------------ crates/live_kit_server/Cargo.toml | 12 ++++----- crates/lsp/Cargo.toml | 26 +++++++++--------- crates/lsp_log/Cargo.toml | 8 +++--- crates/media/Cargo.toml | 2 +- crates/node_runtime/Cargo.toml | 14 +++++----- crates/outline/Cargo.toml | 6 ++--- crates/picker/Cargo.toml | 8 +++--- crates/plugin/Cargo.toml | 4 +-- crates/plugin_macros/Cargo.toml | 4 +-- crates/plugin_runtime/Cargo.toml | 10 +++---- crates/project/Cargo.toml | 36 ++++++++++++------------- crates/project_panel/Cargo.toml | 6 ++--- crates/project_symbols/Cargo.toml | 10 +++---- crates/recent_projects/Cargo.toml | 9 ++++--- crates/rope/Cargo.toml | 6 ++--- crates/rpc/Cargo.toml | 20 +++++++------- crates/rpc/proto/zed.proto | 6 ++--- crates/search/Cargo.toml | 20 +++++++------- crates/settings/Cargo.toml | 16 ++++++----- crates/snippet/Cargo.toml | 4 +-- crates/sqlez/Cargo.toml | 12 ++++----- crates/sqlez_macros/Cargo.toml | 4 +-- crates/staff_mode/Cargo.toml | 2 +- crates/sum_tree/Cargo.toml | 8 +++--- crates/terminal/Cargo.toml | 20 +++++++------- crates/terminal_view/Cargo.toml | 20 +++++++------- crates/text/Cargo.toml | 24 ++++++++--------- crates/theme/Cargo.toml | 10 +++---- crates/theme_selector/Cargo.toml | 8 +++--- crates/theme_testbench/Cargo.toml | 2 +- crates/util/Cargo.toml | 20 +++++++------- crates/vim/Cargo.toml | 14 +++++----- crates/welcome/Cargo.toml | 6 ++--- crates/workspace/Cargo.toml | 26 +++++++++--------- crates/workspace/src/workspace.rs | 10 ++----- crates/zed/Cargo.toml | 40 +++++++++++++--------------- 66 files changed, 437 insertions(+), 425 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 530042885e..2fca74cd7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,9 +148,6 @@ name = "anyhow" version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" -dependencies = [ - "backtrace", -] [[package]] name = "arrayref" diff --git a/Cargo.toml b/Cargo.toml index 94a0b0d402..1ef283d135 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,13 +72,27 @@ default-members = ["crates/zed"] resolver = "2" [workspace.dependencies] +anyhow = { version = "1.0.57" } +async-trait = { version = "0.1" } +ctor = { version = "0.1" } +env_logger = { version = "0.9" } +futures = { version = "0.3" } +lazy_static = { version = "1.4.0" } +log = { version = "0.4.16", features = ["kv_unstable_serde"] } +ordered-float = { version = "2.1.1" } +parking_lot = { version = "0.11.1" } +postage = { version = "0.5", features = ["futures-traits"] } +rand = { version = "0.8.5" } +regex = { version = "1.5" } serde = { version = "1.0", features = ["derive", "rc"] } serde_derive = { version = "1.0", features = ["deserialize_in_place"] } serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] } -rand = { version = "0.8" } -postage = { version = "0.5", features = ["futures-traits"] } smallvec = { version = "1.6", features = ["union"] } -futures = { version = "0.3" } +smol = { version = "1.2" } +tempdir = { version = "0.3.7" } +thiserror = { version = "1.0.29" } +time = { version = "0.3", features = ["serde", "serde-well-known"] } +unindent = { version = "0.1.7" } [patch.crates-io] tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "c51896d32dcc11a38e41f36e3deb1a6a9c4f4b14" } diff --git a/crates/activity_indicator/Cargo.toml b/crates/activity_indicator/Cargo.toml index a11174357b..629aa2c032 100644 --- a/crates/activity_indicator/Cargo.toml +++ b/crates/activity_indicator/Cargo.toml @@ -17,5 +17,5 @@ project = { path = "../project" } settings = { path = "../settings" } util = { path = "../util" } workspace = { path = "../workspace" } -futures = { workspace = true } -smallvec = { workspace = true } +futures.workspace = true +smallvec.workspace = true diff --git a/crates/assets/Cargo.toml b/crates/assets/Cargo.toml index ca96c92602..eec60ff84c 100644 --- a/crates/assets/Cargo.toml +++ b/crates/assets/Cargo.toml @@ -10,6 +10,5 @@ doctest = false [dependencies] gpui = { path = "../gpui" } -anyhow = "1.0.38" +anyhow.workspace = true rust-embed = { version = "6.3", features = ["include-exclude"] } - diff --git a/crates/auto_update/Cargo.toml b/crates/auto_update/Cargo.toml index 6b11f5ddbc..f2b5cea854 100644 --- a/crates/auto_update/Cargo.toml +++ b/crates/auto_update/Cargo.toml @@ -18,12 +18,12 @@ settings = { path = "../settings" } theme = { path = "../theme" } workspace = { path = "../workspace" } util = { path = "../util" } -anyhow = "1.0.38" +anyhow.workspace = true isahc = "1.7" -lazy_static = "1.4" -log = "0.4" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } -smol = "1.2.5" -tempdir = "0.3.7" +lazy_static.workspace = true +log.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true +smol.workspace = true +tempdir.workspace = true diff --git a/crates/call/Cargo.toml b/crates/call/Cargo.toml index c1d8baa118..4e83b552fb 100644 --- a/crates/call/Cargo.toml +++ b/crates/call/Cargo.toml @@ -22,7 +22,7 @@ test-support = [ client = { path = "../client" } collections = { path = "../collections" } gpui = { path = "../gpui" } -log = "0.4" +log.workspace = true live_kit_client = { path = "../live_kit_client" } fs = { path = "../fs" } language = { path = "../language" } @@ -31,10 +31,10 @@ project = { path = "../project" } settings = { path = "../settings" } util = { path = "../util" } -anyhow = "1.0.38" +anyhow.workspace = true async-broadcast = "0.4" -futures = { workspace = true } -postage = { workspace = true } +futures.workspace = true +postage.workspace = true [dev-dependencies] client = { path = "../client", features = ["test-support"] } diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 6b814941b8..9b8009dd69 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -13,12 +13,12 @@ name = "cli" path = "src/main.rs" [dependencies] -anyhow = "1.0" +anyhow.workspace = true clap = { version = "3.1", features = ["derive"] } dirs = "3.0" ipc-channel = "0.16" -serde = { workspace = true } -serde_derive = { workspace = true } +serde.workspace = true +serde_derive.workspace = true [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.9" diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index a3b75e3aba..99c492d638 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -17,27 +17,28 @@ db = { path = "../db" } gpui = { path = "../gpui" } util = { path = "../util" } rpc = { path = "../rpc" } +settings = { path = "../settings" } staff_mode = { path = "../staff_mode" } sum_tree = { path = "../sum_tree" } -anyhow = "1.0.38" + +anyhow.workspace = true async-recursion = "0.3" async-tungstenite = { version = "0.16", features = ["async-tls"] } -futures = { workspace = true } +futures.workspace = true image = "0.23" -lazy_static = "1.4.0" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11.1" -postage = { workspace = true } -rand = "0.8.3" -smol = "1.2.5" -thiserror = "1.0.29" -time = { version = "0.3", features = ["serde", "serde-well-known"] } +lazy_static.workspace = true +log.workspace = true +parking_lot.workspace = true +postage.workspace = true +rand.workspace = true +smol.workspace = true +thiserror.workspace = true +time.workspace = true tiny_http = "0.8" uuid = { version = "1.1.2", features = ["v4"] } url = "2.2" -serde = { workspace = true } -serde_derive = { workspace = true } -settings = { path = "../settings" } +serde.workspace = true +serde_derive.workspace = true tempfile = "3" [dev-dependencies] diff --git a/crates/clock/Cargo.toml b/crates/clock/Cargo.toml index 2ea2779659..2fc79db3b3 100644 --- a/crates/clock/Cargo.toml +++ b/crates/clock/Cargo.toml @@ -9,4 +9,4 @@ path = "src/clock.rs" doctest = false [dependencies] -smallvec = { workspace = true } +smallvec.workspace = true diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 4a86a33d71..b768709be4 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -19,7 +19,7 @@ live_kit_server = { path = "../live_kit_server" } rpc = { path = "../rpc" } util = { path = "../util" } -anyhow = "1.0.40" +anyhow.workspace = true async-tungstenite = "0.16" axum = { version = "0.5", features = ["json", "headers", "ws"] } axum-extra = { version = "0.3", features = ["erased-json"] } @@ -27,26 +27,26 @@ base64 = "0.13" clap = { version = "3.1", features = ["derive"], optional = true } dashmap = "5.4" envy = "0.4.2" -futures = { workspace = true } +futures.workspace = true hyper = "0.14" -lazy_static = "1.4" +lazy_static.workspace = true lipsum = { version = "0.8", optional = true } -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +log.workspace = true nanoid = "0.4" -parking_lot = "0.11.1" +parking_lot.workspace = true prometheus = "0.13" -rand = "0.8" +rand.workspace = true reqwest = { version = "0.11", features = ["json"], optional = true } scrypt = "0.7" # Remove fork dependency when a version with https://github.com/SeaQL/sea-orm/pull/1283 is released. sea-orm = { git = "https://github.com/zed-industries/sea-orm", rev = "18f4c691085712ad014a51792af75a9044bacee6", features = ["sqlx-postgres", "postgres-array", "runtime-tokio-rustls"] } sea-query = "0.27" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true sha-1 = "0.9" sqlx = { version = "0.6", features = ["runtime-tokio-rustls", "postgres", "json", "time", "uuid", "any"] } -time = { version = "0.3", features = ["serde", "serde-well-known"] } +time.workspace = true tokio = { version = "1", features = ["full"] } tokio-tungstenite = "0.17" tonic = "0.6" @@ -55,7 +55,6 @@ toml = "0.5.8" tracing = "0.1.34" tracing-log = "0.1.3" tracing-subscriber = { version = "0.3.11", features = ["env-filter", "json"] } -indoc = "1.0.4" [dev-dependencies] collections = { path = "../collections", features = ["test-support"] } @@ -75,14 +74,15 @@ settings = { path = "../settings", features = ["test-support"] } theme = { path = "../theme" } workspace = { path = "../workspace", features = ["test-support"] } -ctor = "0.1" -env_logger = "0.9" +ctor.workspace = true +env_logger.workspace = true +indoc = "1.0.4" util = { path = "../util" } -lazy_static = "1.4" +lazy_static.workspace = true sea-orm = { git = "https://github.com/zed-industries/sea-orm", rev = "18f4c691085712ad014a51792af75a9044bacee6", features = ["sqlx-sqlite"] } -serde_json = { workspace = true } +serde_json.workspace = true sqlx = { version = "0.6", features = ["sqlite"] } -unindent = "0.1" +unindent.workspace = true [features] seed-support = ["clap", "lipsum", "reqwest"] diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index 994e61a386..16cc6b5277 100644 --- a/crates/collab_ui/Cargo.toml +++ b/crates/collab_ui/Cargo.toml @@ -39,12 +39,13 @@ settings = { path = "../settings" } theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } -anyhow = "1.0" -futures = { workspace = true } -log = "0.4" -postage = { workspace = true } -serde = { workspace = true } -serde_derive = { workspace = true } + +anyhow.workspace = true +futures.workspace = true +log.workspace = true +postage.workspace = true +serde.workspace = true +serde_derive.workspace = true [dev-dependencies] call = { path = "../call", features = ["test-support"] } diff --git a/crates/command_palette/Cargo.toml b/crates/command_palette/Cargo.toml index 6965a3f183..8ad1843cb6 100644 --- a/crates/command_palette/Cargo.toml +++ b/crates/command_palette/Cargo.toml @@ -24,7 +24,7 @@ workspace = { path = "../workspace" } gpui = { path = "../gpui", features = ["test-support"] } editor = { path = "../editor", features = ["test-support"] } project = { path = "../project", features = ["test-support"] } -serde_json = { workspace = true } +serde_json.workspace = true workspace = { path = "../workspace", features = ["test-support"] } -ctor = "0.1" -env_logger = "0.9" +ctor.workspace = true +env_logger.workspace = true diff --git a/crates/context_menu/Cargo.toml b/crates/context_menu/Cargo.toml index 64449bdc92..097f89f822 100644 --- a/crates/context_menu/Cargo.toml +++ b/crates/context_menu/Cargo.toml @@ -13,4 +13,4 @@ gpui = { path = "../gpui" } menu = { path = "../menu" } settings = { path = "../settings" } theme = { path = "../theme" } -smallvec = { workspace = true } +smallvec.workspace = true diff --git a/crates/copilot/Cargo.toml b/crates/copilot/Cargo.toml index a837df97dd..bac335f7b7 100644 --- a/crates/copilot/Cargo.toml +++ b/crates/copilot/Cargo.toml @@ -30,12 +30,12 @@ node_runtime = { path = "../node_runtime"} util = { path = "../util" } async-compression = { version = "0.3", features = ["gzip", "futures-bufread"] } async-tar = "0.4.2" -anyhow = "1.0" -log = "0.4" -serde = { workspace = true } -serde_derive = { workspace = true } -smol = "1.2.5" -futures = { workspace = true } +anyhow.workspace = true +log.workspace = true +serde.workspace = true +serde_derive.workspace = true +smol.workspace = true +futures.workspace = true [dev-dependencies] clock = { path = "../clock" } diff --git a/crates/copilot_button/Cargo.toml b/crates/copilot_button/Cargo.toml index 67d44f8bd4..04e9165a75 100644 --- a/crates/copilot_button/Cargo.toml +++ b/crates/copilot_button/Cargo.toml @@ -17,6 +17,6 @@ settings = { path = "../settings" } theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } -anyhow = "1.0" -smol = "1.2.5" -futures = { workspace = true } +anyhow.workspace = true +smol.workspace = true +futures.workspace = true diff --git a/crates/db/Cargo.toml b/crates/db/Cargo.toml index 767bf57ba9..8cb7170ef6 100644 --- a/crates/db/Cargo.toml +++ b/crates/db/Cargo.toml @@ -17,17 +17,17 @@ gpui = { path = "../gpui" } sqlez = { path = "../sqlez" } sqlez_macros = { path = "../sqlez_macros" } util = { path = "../util" } -anyhow = "1.0.57" +anyhow.workspace = true indoc = "1.0.4" -async-trait = "0.1" -lazy_static = "1.4.0" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11.1" -serde = { workspace = true } -serde_derive = { workspace = true } -smol = "1.2" +async-trait.workspace = true +lazy_static.workspace = true +log.workspace = true +parking_lot.workspace = true +serde.workspace = true +serde_derive.workspace = true +smol.workspace = true [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } -env_logger = "0.9.1" -tempdir = { version = "0.3.7" } +env_logger.workspace = true +tempdir.workspace = true diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index 45621f10c6..9d455f520e 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -9,26 +9,28 @@ path = "src/diagnostics.rs" doctest = false [dependencies] -anyhow = "1.0" -smallvec = { workspace = true } collections = { path = "../collections" } editor = { path = "../editor" } +gpui = { path = "../gpui" } language = { path = "../language" } lsp = { path = "../lsp" } -gpui = { path = "../gpui" } project = { path = "../project" } settings = { path = "../settings" } theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } -postage = { workspace = true } + +anyhow.workspace = true +smallvec.workspace = true +postage.workspace = true [dev-dependencies] -unindent = "0.1" client = { path = "../client", features = ["test-support"] } editor = { path = "../editor", features = ["test-support"] } language = { path = "../language", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } workspace = { path = "../workspace", features = ["test-support"] } -serde_json = { workspace = true } + +serde_json.workspace = true +unindent.workspace = true diff --git a/crates/editor/Cargo.toml b/crates/editor/Cargo.toml index 47c5aaa715..37b4dccb81 100644 --- a/crates/editor/Cargo.toml +++ b/crates/editor/Cargo.toml @@ -46,20 +46,20 @@ sqlez = { path = "../sqlez" } workspace = { path = "../workspace" } aho-corasick = "0.7" -anyhow = "1.0" -futures = { workspace = true } +anyhow.workspace = true +futures.workspace = true indoc = "1.0.4" itertools = "0.10" -lazy_static = "1.4" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -ordered-float = "2.1.1" -parking_lot = "0.11" -postage = { workspace = true } -rand = { version = "0.8.3", optional = true } -serde = { workspace = true } -serde_derive = { workspace = true } -smallvec = { workspace = true } -smol = "1.2" +lazy_static.workspace = true +log.workspace = true +ordered-float.workspace = true +parking_lot.workspace = true +postage.workspace = true +rand = { workspace = true, optional = true } +serde.workspace = true +serde_derive.workspace = true +smallvec.workspace = true +smol.workspace = true tree-sitter-rust = { version = "*", optional = true } tree-sitter-html = { version = "*", optional = true } tree-sitter-javascript = { version = "*", optional = true } @@ -75,10 +75,11 @@ util = { path = "../util", features = ["test-support"] } project = { path = "../project", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } workspace = { path = "../workspace", features = ["test-support"] } -ctor = "0.1" -env_logger = "0.9" -rand = "0.8" -unindent = "0.1.7" + +ctor.workspace = true +env_logger.workspace = true +rand.workspace = true +unindent.workspace = true tree-sitter = "0.20" tree-sitter-rust = "0.20" tree-sitter-html = "0.19" diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index 1acc14892c..e94243bd30 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -11,21 +11,21 @@ path = "src/feedback.rs" test-support = [] [dependencies] -anyhow = "1.0.38" +anyhow.workspace = true client = { path = "../client" } editor = { path = "../editor" } language = { path = "../language" } -log = "0.4" -futures = { workspace = true } +log.workspace = true +futures.workspace = true gpui = { path = "../gpui" } human_bytes = "0.4.1" isahc = "1.7" -lazy_static = "1.4.0" -postage = { workspace = true } +lazy_static.workspace = true +postage.workspace = true project = { path = "../project" } search = { path = "../search" } -serde = { workspace = true } -serde_derive = { workspace = true } +serde.workspace = true +serde_derive.workspace = true settings = { path = "../settings" } sysinfo = "0.27.1" theme = { path = "../theme" } diff --git a/crates/file_finder/Cargo.toml b/crates/file_finder/Cargo.toml index 8c4d853234..30a4650ad7 100644 --- a/crates/file_finder/Cargo.toml +++ b/crates/file_finder/Cargo.toml @@ -19,11 +19,11 @@ settings = { path = "../settings" } util = { path = "../util" } theme = { path = "../theme" } workspace = { path = "../workspace" } -postage = { workspace = true } +postage.workspace = true [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } -serde_json = { workspace = true } +serde_json.workspace = true workspace = { path = "../workspace", features = ["test-support"] } -ctor = "0.1" -env_logger = "0.9" +ctor.workspace = true +env_logger.workspace = true diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index 5eab919b7c..d080fe3cd1 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -13,20 +13,20 @@ gpui = { path = "../gpui" } lsp = { path = "../lsp" } rope = { path = "../rope" } util = { path = "../util" } -anyhow = "1.0.57" -async-trait = "0.1" -futures = { workspace = true } +anyhow.workspace = true +async-trait.workspace = true +futures.workspace = true tempfile = "3" fsevent = { path = "../fsevent" } -lazy_static = "1.4.0" -parking_lot = "0.11.1" -smol = "1.2.5" -regex = "1.5" +lazy_static.workspace = true +parking_lot.workspace = true +smol.workspace = true +regex.workspace = true git2 = { version = "0.15", default-features = false } -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true +log.workspace = true libc = "0.2" [features] diff --git a/crates/fsevent/Cargo.toml b/crates/fsevent/Cargo.toml index e71e247bf2..6120742696 100644 --- a/crates/fsevent/Cargo.toml +++ b/crates/fsevent/Cargo.toml @@ -12,10 +12,10 @@ doctest = false [dependencies] bitflags = "1" fsevent-sys = "3.0.2" -parking_lot = "0.11.1" +parking_lot.workspace = true [dev-dependencies] -tempdir = "0.3.7" +tempdir.workspace = true [package.metadata.docs.rs] targets = ["x86_64-apple-darwin"] diff --git a/crates/git/Cargo.toml b/crates/git/Cargo.toml index b1fa0eda78..8b91ee5373 100644 --- a/crates/git/Cargo.toml +++ b/crates/git/Cargo.toml @@ -8,22 +8,22 @@ publish = false path = "src/git.rs" [dependencies] -anyhow = "1.0.38" +anyhow.workspace = true clock = { path = "../clock" } -lazy_static = "1.4.0" +lazy_static.workspace = true sum_tree = { path = "../sum_tree" } text = { path = "../text" } collections = { path = "../collections" } util = { path = "../util" } -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -smol = "1.2" -parking_lot = "0.11.1" -async-trait = "0.1" -futures = { workspace = true } +log.workspace = true +smol.workspace = true +parking_lot.workspace = true +async-trait.workspace = true +futures.workspace = true git2 = { version = "0.15", default-features = false } [dev-dependencies] -unindent = "0.1.7" +unindent.workspace = true [features] test-support = [] diff --git a/crates/go_to_line/Cargo.toml b/crates/go_to_line/Cargo.toml index 54567b2440..f279aca569 100644 --- a/crates/go_to_line/Cargo.toml +++ b/crates/go_to_line/Cargo.toml @@ -15,4 +15,4 @@ menu = { path = "../menu" } settings = { path = "../settings" } text = { path = "../text" } workspace = { path = "../workspace" } -postage = { workspace = true } +postage.workspace = true diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 858f67cf5f..35c5010cdd 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -21,32 +21,32 @@ sum_tree = { path = "../sum_tree" } sqlez = { path = "../sqlez" } async-task = "4.0.3" backtrace = { version = "0.3", optional = true } -ctor = "0.1" +ctor.workspace = true dhat = { version = "0.3", optional = true } env_logger = { version = "0.9", optional = true } etagere = "0.2" -futures = { workspace = true } +futures.workspace = true image = "0.23" itertools = "0.10" -lazy_static = "1.4.0" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +lazy_static.workspace = true +log.workspace = true num_cpus = "1.13" -ordered-float = "2.1.1" +ordered-float.workspace = true parking = "2.0.0" -parking_lot = "0.11.1" +parking_lot.workspace = true pathfinder_color = "0.5" pathfinder_geometry = "0.5" -postage = { workspace = true } -rand = "0.8.3" +postage.workspace = true +rand.workspace = true resvg = "0.14" schemars = "0.8" seahash = "4.1" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } -smallvec = { workspace = true } -smol = "1.2" -time = { version = "0.3", features = ["serde", "serde-well-known"] } +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true +smallvec.workspace = true +smol.workspace = true +time.workspace = true tiny-skia = "0.5" usvg = "0.14" uuid = { version = "1.1.2", features = ["v4"] } @@ -60,13 +60,13 @@ cc = "1.0.67" backtrace = "0.3" collections = { path = "../collections", features = ["test-support"] } dhat = "0.3" -env_logger = "0.9" +env_logger.workspace = true png = "0.16" simplelog = "0.9" [target.'cfg(target_os = "macos")'.dependencies] media = { path = "../media" } -anyhow = "1" +anyhow.workspace = true block = "0.1" cocoa = "0.24" core-foundation = { version = "0.9.3", features = ["with-uuid"] } @@ -74,6 +74,6 @@ core-graphics = "0.22.3" core-text = "19.2" font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "8eaf7a918eafa28b0a37dc759e2e0e7683fa24f1" } foreign-types = "0.3" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +log.workspace = true metal = "0.21.0" objc = "0.2" diff --git a/crates/install_cli/Cargo.toml b/crates/install_cli/Cargo.toml index bbbe989920..21928e319e 100644 --- a/crates/install_cli/Cargo.toml +++ b/crates/install_cli/Cargo.toml @@ -11,8 +11,8 @@ path = "src/install_cli.rs" test-support = [] [dependencies] -smol = "1.2.5" -anyhow = "1.0.38" -log = "0.4" +smol.workspace = true +anyhow.workspace = true +log.workspace = true gpui = { path = "../gpui" } util = { path = "../util" } diff --git a/crates/journal/Cargo.toml b/crates/journal/Cargo.toml index a2656ad219..b88e3e093a 100644 --- a/crates/journal/Cargo.toml +++ b/crates/journal/Cargo.toml @@ -13,9 +13,9 @@ editor = { path = "../editor" } gpui = { path = "../gpui" } util = { path = "../util" } workspace = { path = "../workspace" } -anyhow = "1.0" +anyhow.workspace = true chrono = "0.4" dirs = "4.0" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +log.workspace = true settings = { path = "../settings" } shellexpand = "2.1.0" diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index d09b346348..6e03a07bc3 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -36,22 +36,22 @@ sum_tree = { path = "../sum_tree" } text = { path = "../text" } theme = { path = "../theme" } util = { path = "../util" } -anyhow = "1.0.38" +anyhow.workspace = true async-broadcast = "0.4" -async-trait = "0.1" -futures = { workspace = true } -lazy_static = "1.4" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11.1" -postage = { workspace = true } -rand = { version = "0.8.3", optional = true } -regex = "1.5" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +async-trait.workspace = true +futures.workspace = true +lazy_static.workspace = true +log.workspace = true +parking_lot.workspace = true +postage.workspace = true +rand = { workspace = true, optional = true } +regex.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true similar = "1.3" -smallvec = { workspace = true } -smol = "1.2" +smallvec.workspace = true +smol.workspace = true tree-sitter = "0.20" tree-sitter-rust = { version = "*", optional = true } tree-sitter-typescript = { version = "*", optional = true } @@ -65,10 +65,10 @@ lsp = { path = "../lsp", features = ["test-support"] } text = { path = "../text", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } util = { path = "../util", features = ["test-support"] } -ctor = "0.1" -env_logger = "0.9" +ctor.workspace = true +env_logger.workspace = true indoc = "1.0.4" -rand = "0.8.3" +rand.workspace = true tree-sitter-embedded-template = "*" tree-sitter-html = "*" tree-sitter-javascript = "*" @@ -78,4 +78,4 @@ tree-sitter-rust = "*" tree-sitter-python = "*" tree-sitter-typescript = "*" tree-sitter-ruby = "*" -unindent = "0.1.7" +unindent.workspace = true diff --git a/crates/language_selector/Cargo.toml b/crates/language_selector/Cargo.toml index c77057f42b..e7b3d8d4be 100644 --- a/crates/language_selector/Cargo.toml +++ b/crates/language_selector/Cargo.toml @@ -19,4 +19,4 @@ theme = { path = "../theme" } settings = { path = "../settings" } util = { path = "../util" } workspace = { path = "../workspace" } -anyhow = "1.0" +anyhow.workspace = true diff --git a/crates/live_kit_client/Cargo.toml b/crates/live_kit_client/Cargo.toml index 95057b3d0e..2d61e75732 100644 --- a/crates/live_kit_client/Cargo.toml +++ b/crates/live_kit_client/Cargo.toml @@ -28,17 +28,17 @@ gpui = { path = "../gpui", optional = true } live_kit_server = { path = "../live_kit_server", optional = true } media = { path = "../media" } -anyhow = "1.0.38" +anyhow.workspace = true async-broadcast = "0.4" core-foundation = "0.9.3" core-graphics = "0.22.3" -futures = { workspace = true } -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11.1" -postage = { workspace = true } +futures.workspace = true +log.workspace = true +parking_lot.workspace = true +postage.workspace = true -async-trait = { version = "0.1", optional = true } -lazy_static = { version = "1.4", optional = true } +async-trait = { workspace = true, optional = true } +lazy_static = { workspace = true, optional = true } nanoid = { version ="0.4", optional = true} [dev-dependencies] @@ -47,8 +47,8 @@ gpui = { path = "../gpui", features = ["test-support"] } live_kit_server = { path = "../live_kit_server" } media = { path = "../media" } -anyhow = "1.0.38" -async-trait = "0.1" +anyhow.workspace = true +async-trait.workspace = true block = "0.1" bytes = "1.2" byteorder = "1.4" @@ -56,18 +56,18 @@ cocoa = "0.24" core-foundation = "0.9.3" core-graphics = "0.22.3" foreign-types = "0.3" -futures = { workspace = true } +futures.workspace = true hmac = "0.12" jwt = "0.16" -lazy_static = "1.4" +lazy_static.workspace = true objc = "0.2" -parking_lot = "0.11.1" -serde = { workspace = true } -serde_derive = { workspace = true } +parking_lot.workspace = true +serde.workspace = true +serde_derive.workspace = true sha2 = "0.10" simplelog = "0.9" [build-dependencies] -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true diff --git a/crates/live_kit_server/Cargo.toml b/crates/live_kit_server/Cargo.toml index cfb3a9c885..2167a041b9 100644 --- a/crates/live_kit_server/Cargo.toml +++ b/crates/live_kit_server/Cargo.toml @@ -10,17 +10,17 @@ path = "src/live_kit_server.rs" doctest = false [dependencies] -anyhow = "1.0.38" -async-trait = "0.1" -futures = { workspace = true } +anyhow.workspace = true +async-trait.workspace = true +futures.workspace = true hmac = "0.12" -log = "0.4" +log.workspace = true jwt = "0.16" prost = "0.8" prost-types = "0.8" reqwest = "0.11" -serde = { workspace = true } -serde_derive = { workspace = true } +serde.workspace = true +serde_derive.workspace = true sha2 = "0.10" [build-dependencies] diff --git a/crates/lsp/Cargo.toml b/crates/lsp/Cargo.toml index 86b4ed9e40..c766dacd2a 100644 --- a/crates/lsp/Cargo.toml +++ b/crates/lsp/Cargo.toml @@ -15,22 +15,24 @@ test-support = ["async-pipe"] collections = { path = "../collections" } gpui = { path = "../gpui" } util = { path = "../util" } -anyhow = "1.0" + +anyhow.workspace = true async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "82d00a04211cf4e1236029aa03e6b6ce2a74c553", optional = true } -futures = { workspace = true } -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +futures.workspace = true +log.workspace = true lsp-types = "0.91" -parking_lot = "0.11" -postage = { workspace = true } -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } -smol = "1.2" +parking_lot.workspace = true +postage.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true +smol.workspace = true [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } util = { path = "../util", features = ["test-support"] } + async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "82d00a04211cf4e1236029aa03e6b6ce2a74c553" } -ctor = "0.1" -env_logger = "0.9" -unindent = "0.1.7" +ctor.workspace = true +env_logger.workspace = true +unindent.workspace = true diff --git a/crates/lsp_log/Cargo.toml b/crates/lsp_log/Cargo.toml index 4eeebef9a4..8741f0a4cf 100644 --- a/crates/lsp_log/Cargo.toml +++ b/crates/lsp_log/Cargo.toml @@ -19,11 +19,11 @@ workspace = { path = "../workspace" } gpui = { path = "../gpui" } util = { path = "../util" } lsp = { path = "../lsp" } -futures = { workspace = true } -serde = { workspace = true } -anyhow = "1.0" +futures.workspace = true +serde.workspace = true +anyhow.workspace = true [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } util = { path = "../util", features = ["test-support"] } -unindent = "0.1.7" +unindent.workspace = true diff --git a/crates/media/Cargo.toml b/crates/media/Cargo.toml index 4c230819e2..22a494d754 100644 --- a/crates/media/Cargo.toml +++ b/crates/media/Cargo.toml @@ -9,7 +9,7 @@ path = "src/media.rs" doctest = false [dependencies] -anyhow = "1.0" +anyhow.workspace = true block = "0.1" bytes = "1.2" core-foundation = "0.9.3" diff --git a/crates/node_runtime/Cargo.toml b/crates/node_runtime/Cargo.toml index eb43be61ce..fce0fdfe50 100644 --- a/crates/node_runtime/Cargo.toml +++ b/crates/node_runtime/Cargo.toml @@ -13,10 +13,10 @@ gpui = { path = "../gpui" } util = { path = "../util" } async-compression = { version = "0.3", features = ["gzip", "futures-bufread"] } async-tar = "0.4.2" -futures = { workspace = true } -anyhow = "1.0.38" -parking_lot = "0.11.1" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } -smol = "1.2.5" +futures.workspace = true +anyhow.workspace = true +parking_lot.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true +smol.workspace = true diff --git a/crates/outline/Cargo.toml b/crates/outline/Cargo.toml index 552cf54892..91e5011b2a 100644 --- a/crates/outline/Cargo.toml +++ b/crates/outline/Cargo.toml @@ -17,6 +17,6 @@ picker = { path = "../picker" } settings = { path = "../settings" } text = { path = "../text" } workspace = { path = "../workspace" } -ordered-float = "2.1.1" -postage = { workspace = true } -smol = "1.2" +ordered-float.workspace = true +postage.workspace = true +smol.workspace = true diff --git a/crates/picker/Cargo.toml b/crates/picker/Cargo.toml index 2371cfa9fd..b723cd788c 100644 --- a/crates/picker/Cargo.toml +++ b/crates/picker/Cargo.toml @@ -17,11 +17,11 @@ util = { path = "../util" } theme = { path = "../theme" } workspace = { path = "../workspace" } -parking_lot = "0.11.1" +parking_lot.workspace = true [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } -serde_json = { workspace = true } +serde_json.workspace = true workspace = { path = "../workspace", features = ["test-support"] } -ctor = "0.1" -env_logger = "0.9" +ctor.workspace = true +env_logger.workspace = true diff --git a/crates/plugin/Cargo.toml b/crates/plugin/Cargo.toml index 8c3a2fb83f..6983465150 100644 --- a/crates/plugin/Cargo.toml +++ b/crates/plugin/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -serde = { workspace = true } -serde_derive = { workspace = true } +serde.workspace = true +serde_derive.workspace = true bincode = "1.3" plugin_macros = { path = "../plugin_macros" } diff --git a/crates/plugin_macros/Cargo.toml b/crates/plugin_macros/Cargo.toml index 51cb78c7a1..05402f33c8 100644 --- a/crates/plugin_macros/Cargo.toml +++ b/crates/plugin_macros/Cargo.toml @@ -11,6 +11,6 @@ proc-macro = true syn = { version = "1.0", features = ["full", "extra-traits"] } quote = "1.0" proc-macro2 = "1.0" -serde = { workspace = true } -serde_derive = { workspace = true } +serde.workspace = true +serde_derive.workspace = true bincode = "1.3" diff --git a/crates/plugin_runtime/Cargo.toml b/crates/plugin_runtime/Cargo.toml index cf509a20d3..04337741c4 100644 --- a/crates/plugin_runtime/Cargo.toml +++ b/crates/plugin_runtime/Cargo.toml @@ -8,13 +8,13 @@ publish = false wasmtime = "0.38" wasmtime-wasi = "0.38" wasi-common = "0.38" -anyhow = { version = "1.0", features = ["std"] } -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +anyhow.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true bincode = "1.3" pollster = "0.2.5" -smol = "1.2.5" +smol.workspace = true [build-dependencies] wasmtime = { version = "0.38", features = ["all-arch"] } diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index 4ce5f24e9d..a0e6b31ec8 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -38,30 +38,30 @@ sum_tree = { path = "../sum_tree" } terminal = { path = "../terminal" } util = { path = "../util" } aho-corasick = "0.7" -anyhow = "1.0.57" -async-trait = "0.1" +anyhow.workspace = true +async-trait.workspace = true backtrace = "0.3" -futures = { workspace = true } +futures.workspace = true ignore = "0.4" -lazy_static = "1.4.0" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11.1" -postage = { workspace = true } +lazy_static.workspace = true +log.workspace = true +parking_lot.workspace = true +postage.workspace = true pulldown-cmark = { version = "0.9.1", default-features = false } -rand = "0.8.3" -regex = "1.5" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +rand.workspace = true +regex.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true sha2 = "0.10" similar = "1.3" -smol = "1.2.5" -thiserror = "1.0.29" +smol.workspace = true +thiserror.workspace = true toml = "0.5" [dev-dependencies] -ctor = "0.1" -env_logger = "0.9" +ctor.workspace = true +env_logger.workspace = true pretty_assertions = "1.3.0" client = { path = "../client", features = ["test-support"] } collections = { path = "../collections", features = ["test-support"] } @@ -73,5 +73,5 @@ lsp = { path = "../lsp", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } util = { path = "../util", features = ["test-support"] } rpc = { path = "../rpc", features = ["test-support"] } -tempdir = { version = "0.3.7" } -unindent = "0.1.7" +tempdir.workspace = true +unindent.workspace = true diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 195bcee10a..d3b2876675 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -19,12 +19,12 @@ settings = { path = "../settings" } theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } -postage = { workspace = true } -futures = { workspace = true } +postage.workspace = true +futures.workspace = true unicase = "2.6" [dev-dependencies] editor = { path = "../editor", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } workspace = { path = "../workspace", features = ["test-support"] } -serde_json = { workspace = true } +serde_json.workspace = true diff --git a/crates/project_symbols/Cargo.toml b/crates/project_symbols/Cargo.toml index b03e62cc55..1c0d3a6165 100644 --- a/crates/project_symbols/Cargo.toml +++ b/crates/project_symbols/Cargo.toml @@ -18,13 +18,13 @@ text = { path = "../text" } settings = { path = "../settings" } workspace = { path = "../workspace" } util = { path = "../util" } -anyhow = "1.0.38" -ordered-float = "2.1.1" -postage = { workspace = true } -smol = "1.2" +anyhow.workspace = true +ordered-float.workspace = true +postage.workspace = true +smol.workspace = true [dev-dependencies] -futures = { workspace = true } +futures.workspace = true settings = { path = "../settings", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } language = { path = "../language", features = ["test-support"] } diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index c056b68852..968ae8e9a4 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -17,8 +17,9 @@ language = { path = "../language" } picker = { path = "../picker" } settings = { path = "../settings" } text = { path = "../text" } -workspace = { path = "../workspace" } -ordered-float = "2.1.1" -postage = { workspace = true } -smol = "1.2" util = { path = "../util"} +workspace = { path = "../workspace" } + +ordered-float.workspace = true +postage.workspace = true +smol.workspace = true diff --git a/crates/rope/Cargo.toml b/crates/rope/Cargo.toml index bd72c7c263..e83ca5cd86 100644 --- a/crates/rope/Cargo.toml +++ b/crates/rope/Cargo.toml @@ -9,13 +9,13 @@ path = "src/rope.rs" [dependencies] bromberg_sl2 = { git = "https://github.com/zed-industries/bromberg_sl2", rev = "950bc5482c216c395049ae33ae4501e08975f17f" } -smallvec = { workspace = true } +smallvec.workspace = true sum_tree = { path = "../sum_tree" } arrayvec = "0.7.1" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +log.workspace = true util = { path = "../util" } [dev-dependencies] -rand = "0.8.3" +rand.workspace = true util = { path = "../util", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index 78f37fd5ae..008fa9c316 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -17,17 +17,17 @@ clock = { path = "../clock" } collections = { path = "../collections" } gpui = { path = "../gpui", optional = true } util = { path = "../util" } -anyhow = "1.0" +anyhow.workspace = true async-lock = "2.4" async-tungstenite = "0.16" base64 = "0.13" -futures = { workspace = true } -parking_lot = "0.11.1" +futures.workspace = true +parking_lot.workspace = true prost = "0.8" -rand = "0.8" +rand.workspace = true rsa = "0.4" -serde = { workspace = true } -serde_derive = { workspace = true } +serde.workspace = true +serde_derive.workspace = true smol-timeout = "0.6" tracing = { version = "0.1.34", features = ["log"] } zstd = "0.11" @@ -38,7 +38,7 @@ prost-build = "0.9" [dev-dependencies] collections = { path = "../collections", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } -smol = "1.2.5" -tempdir = "0.3.7" -ctor = "0.1" -env_logger = "0.9" +smol.workspace = true +tempdir.workspace = true +ctor.workspace = true +env_logger.workspace = true diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index d8272f21f2..599d80e2ba 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -240,13 +240,13 @@ message ParticipantLocation { UnsharedProject unshared_project = 2; External external = 3; } - + message SharedProject { uint64 id = 1; } - + message UnsharedProject {} - + message External {} } diff --git a/crates/search/Cargo.toml b/crates/search/Cargo.toml index fc8737e73f..eec0dd0e22 100644 --- a/crates/search/Cargo.toml +++ b/crates/search/Cargo.toml @@ -19,18 +19,18 @@ settings = { path = "../settings" } theme = { path = "../theme" } util = { path = "../util" } workspace = { path = "../workspace" } -anyhow = "1.0" -futures = { workspace = true } -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -postage = { workspace = true } -serde = { workspace = true } -serde_derive = { workspace = true } -smallvec = { workspace = true } -smol = "1.2" +anyhow.workspace = true +futures.workspace = true +log.workspace = true +postage.workspace = true +serde.workspace = true +serde_derive.workspace = true +smallvec.workspace = true +smol.workspace = true [dev-dependencies] editor = { path = "../editor", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } -serde_json = { workspace = true } +serde_json.workspace = true workspace = { path = "../workspace", features = ["test-support"] } -unindent = "0.1" +unindent.workspace = true diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index ab5e428b7b..3a87832e15 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -17,24 +17,26 @@ collections = { path = "../collections" } gpui = { path = "../gpui" } sqlez = { path = "../sqlez" } fs = { path = "../fs" } -anyhow = "1.0.38" -futures = { workspace = true } +anyhow.workspace = true +futures.workspace = true theme = { path = "../theme" } staff_mode = { path = "../staff_mode" } util = { path = "../util" } + json_comments = "0.2" -postage = { workspace = true } +postage.workspace = true schemars = "0.8" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true serde_path_to_error = "0.1.4" toml = "0.5" tree-sitter = "*" tree-sitter-json = "*" [dev-dependencies] -unindent = "0.1" gpui = { path = "../gpui", features = ["test-support"] } fs = { path = "../fs", features = ["test-support"] } + pretty_assertions = "1.3.0" +unindent.workspace = true diff --git a/crates/snippet/Cargo.toml b/crates/snippet/Cargo.toml index 67f77e4483..b2e330e88b 100644 --- a/crates/snippet/Cargo.toml +++ b/crates/snippet/Cargo.toml @@ -9,5 +9,5 @@ path = "src/snippet.rs" doctest = false [dependencies] -anyhow = "1.0" -smallvec = { workspace = true } +anyhow.workspace = true +smallvec.workspace = true diff --git a/crates/sqlez/Cargo.toml b/crates/sqlez/Cargo.toml index 7e82a50247..7371a7863a 100644 --- a/crates/sqlez/Cargo.toml +++ b/crates/sqlez/Cargo.toml @@ -4,15 +4,13 @@ version = "0.1.0" edition = "2021" publish = false -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -anyhow = { version = "1.0.38", features = ["backtrace"] } +anyhow.workspace = true indoc = "1.0.7" libsqlite3-sys = { version = "0.24", features = ["bundled"] } -smol = "1.2" +smol.workspace = true thread_local = "1.1.4" -lazy_static = "1.4" -parking_lot = "0.11.1" -futures = { workspace = true } +lazy_static.workspace = true +parking_lot.workspace = true +futures.workspace = true uuid = { version = "1.1.2", features = ["v4"] } diff --git a/crates/sqlez_macros/Cargo.toml b/crates/sqlez_macros/Cargo.toml index 8d650074c3..11a18aeacb 100644 --- a/crates/sqlez_macros/Cargo.toml +++ b/crates/sqlez_macros/Cargo.toml @@ -13,6 +13,6 @@ doctest = false syn = "1.0" quote = "1.0" proc-macro2 = "1.0" -lazy_static = "1.4" +lazy_static.workspace = true sqlez = { path = "../sqlez" } -sqlformat = "0.2" \ No newline at end of file +sqlformat = "0.2" diff --git a/crates/staff_mode/Cargo.toml b/crates/staff_mode/Cargo.toml index cb8729f382..2193bd11b1 100644 --- a/crates/staff_mode/Cargo.toml +++ b/crates/staff_mode/Cargo.toml @@ -9,4 +9,4 @@ path = "src/staff_mode.rs" [dependencies] gpui = { path = "../gpui" } -anyhow = "1.0.38" +anyhow.workspace = true diff --git a/crates/sum_tree/Cargo.toml b/crates/sum_tree/Cargo.toml index 3aab16cc3e..89fb3d5566 100644 --- a/crates/sum_tree/Cargo.toml +++ b/crates/sum_tree/Cargo.toml @@ -10,9 +10,9 @@ doctest = false [dependencies] arrayvec = "0.7.1" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +log.workspace = true [dev-dependencies] -ctor = "0.1" -env_logger = "0.9" -rand = "0.8.3" +ctor.workspace = true +env_logger.workspace = true +rand.workspace = true diff --git a/crates/terminal/Cargo.toml b/crates/terminal/Cargo.toml index f46bdad5d5..725b102c04 100644 --- a/crates/terminal/Cargo.toml +++ b/crates/terminal/Cargo.toml @@ -17,20 +17,20 @@ theme = { path = "../theme" } util = { path = "../util" } alacritty_terminal = { git = "https://github.com/zed-industries/alacritty", rev = "a51dbe25d67e84d6ed4261e640d3954fbdd9be45" } procinfo = { git = "https://github.com/zed-industries/wezterm", rev = "5cd757e5f2eb039ed0c6bb6512223e69d5efc64d", default-features = false } -smallvec = { workspace = true } -smol = "1.2.5" +smallvec.workspace = true +smol.workspace = true mio-extras = "2.0.6" -futures = { workspace = true } -ordered-float = "2.1.1" +futures.workspace = true +ordered-float.workspace = true itertools = "0.10" dirs = "4.0.0" shellexpand = "2.1.0" libc = "0.2" -anyhow = "1" -thiserror = "1.0" -lazy_static = "1.4.0" -serde = { workspace = true } -serde_derive = { workspace = true } +anyhow.workspace = true +thiserror.workspace = true +lazy_static.workspace = true +serde.workspace = true +serde_derive.workspace = true [dev-dependencies] -rand = "0.8.5" +rand.workspace = true diff --git a/crates/terminal_view/Cargo.toml b/crates/terminal_view/Cargo.toml index fe7dd833e9..3a25317870 100644 --- a/crates/terminal_view/Cargo.toml +++ b/crates/terminal_view/Cargo.toml @@ -21,20 +21,20 @@ workspace = { path = "../workspace" } db = { path = "../db" } procinfo = { git = "https://github.com/zed-industries/wezterm", rev = "5cd757e5f2eb039ed0c6bb6512223e69d5efc64d", default-features = false } terminal = { path = "../terminal" } -smallvec = { workspace = true } -smol = "1.2.5" +smallvec.workspace = true +smol.workspace = true mio-extras = "2.0.6" -futures = { workspace = true } -ordered-float = "2.1.1" +futures.workspace = true +ordered-float.workspace = true itertools = "0.10" dirs = "4.0.0" shellexpand = "2.1.0" libc = "0.2" -anyhow = "1" -thiserror = "1.0" -lazy_static = "1.4.0" -serde = { workspace = true } -serde_derive = { workspace = true } +anyhow.workspace = true +thiserror.workspace = true +lazy_static.workspace = true +serde.workspace = true +serde_derive.workspace = true @@ -43,4 +43,4 @@ gpui = { path = "../gpui", features = ["test-support"] } client = { path = "../client", features = ["test-support"]} project = { path = "../project", features = ["test-support"]} workspace = { path = "../workspace", features = ["test-support"] } -rand = "0.8.5" +rand.workspace = true diff --git a/crates/text/Cargo.toml b/crates/text/Cargo.toml index d85464a446..adec2d4fd0 100644 --- a/crates/text/Cargo.toml +++ b/crates/text/Cargo.toml @@ -17,21 +17,21 @@ collections = { path = "../collections" } fs = { path = "../fs" } rope = { path = "../rope" } sum_tree = { path = "../sum_tree" } -anyhow = "1.0.38" -digest = { version = "0.9", features = ["std"] } -lazy_static = "1.4" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11" -postage = { workspace = true } -rand = { version = "0.8.3", optional = true } -smallvec = { workspace = true } util = { path = "../util" } -regex = "1.5" +anyhow.workspace = true +digest = { version = "0.9", features = ["std"] } +lazy_static.workspace = true +log.workspace = true +parking_lot.workspace = true +postage.workspace = true +rand = { workspace = true, optional = true } +smallvec.workspace = true +regex.workspace = true [dev-dependencies] collections = { path = "../collections", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } -ctor = "0.1" -env_logger = "0.9" -rand = "0.8.3" +ctor.workspace = true +env_logger.workspace = true +rand.workspace = true diff --git a/crates/theme/Cargo.toml b/crates/theme/Cargo.toml index cf8ff1db14..e6acbda562 100644 --- a/crates/theme/Cargo.toml +++ b/crates/theme/Cargo.toml @@ -10,11 +10,11 @@ doctest = false [dependencies] gpui = { path = "../gpui" } -anyhow = "1.0.38" +anyhow.workspace = true indexmap = "1.6.2" -parking_lot = "0.11.1" -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +parking_lot.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true serde_path_to_error = "0.1.4" toml = "0.5" diff --git a/crates/theme_selector/Cargo.toml b/crates/theme_selector/Cargo.toml index db9d21fbd9..a404e43f29 100644 --- a/crates/theme_selector/Cargo.toml +++ b/crates/theme_selector/Cargo.toml @@ -18,7 +18,7 @@ settings = { path = "../settings" } staff_mode = { path = "../staff_mode" } workspace = { path = "../workspace" } util = { path = "../util" } -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11.1" -postage = { workspace = true } -smol = "1.2.5" +log.workspace = true +parking_lot.workspace = true +postage.workspace = true +smol.workspace = true diff --git a/crates/theme_testbench/Cargo.toml b/crates/theme_testbench/Cargo.toml index ade8e39550..32dca6a07a 100644 --- a/crates/theme_testbench/Cargo.toml +++ b/crates/theme_testbench/Cargo.toml @@ -16,4 +16,4 @@ settings = { path = "../settings" } workspace = { path = "../workspace" } project = { path = "../project" } -smallvec = { workspace = true } +smallvec.workspace = true diff --git a/crates/util/Cargo.toml b/crates/util/Cargo.toml index faf88c5c9d..319d815d17 100644 --- a/crates/util/Cargo.toml +++ b/crates/util/Cargo.toml @@ -12,21 +12,21 @@ doctest = true test-support = ["tempdir", "git2"] [dependencies] -anyhow = "1.0.38" +anyhow.workspace = true backtrace = "0.3" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -lazy_static = "1.4.0" -futures = { workspace = true } +log.workspace = true +lazy_static.workspace = true +futures.workspace = true isahc = "1.7" -smol = "1.2.5" +smol.workspace = true url = "2.2" -rand = { workspace = true } -tempdir = { version = "0.3.7", optional = true } -serde = { workspace = true } -serde_json = { workspace = true } +rand.workspace = true +tempdir = { workspace = true, optional = true } +serde.workspace = true +serde_json.workspace = true git2 = { version = "0.15", default-features = false, optional = true } dirs = "3.0" [dev-dependencies] -tempdir = { version = "0.3.7" } +tempdir.workspace = true git2 = { version = "0.15", default-features = false } diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index bafa2c7a55..5f7cf0a5a3 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -12,16 +12,16 @@ doctest = false neovim = ["nvim-rs", "async-compat", "async-trait", "tokio"] [dependencies] -serde = { workspace = true } -serde_derive = { workspace = true } +serde.workspace = true +serde_derive.workspace = true itertools = "0.10" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +log.workspace = true async-compat = { version = "0.2.1", "optional" = true } -async-trait = { version = "0.1", "optional" = true } +async-trait = { workspace = true, "optional" = true } nvim-rs = { git = "https://github.com/KillTheMule/nvim-rs", branch = "master", features = ["use_tokio"], optional = true } tokio = { version = "1.15", "optional" = true } -serde_json = { workspace = true } +serde_json.workspace = true assets = { path = "../assets" } collections = { path = "../collections" } @@ -35,8 +35,8 @@ workspace = { path = "../workspace" } [dev-dependencies] indoc = "1.0.4" -parking_lot = "0.11.1" -lazy_static = "1.4" +parking_lot.workspace = true +lazy_static.workspace = true editor = { path = "../editor", features = ["test-support"] } gpui = { path = "../gpui", features = ["test-support"] } diff --git a/crates/welcome/Cargo.toml b/crates/welcome/Cargo.toml index 3da90deb2d..d35cced642 100644 --- a/crates/welcome/Cargo.toml +++ b/crates/welcome/Cargo.toml @@ -11,8 +11,8 @@ path = "src/welcome.rs" test-support = [] [dependencies] -anyhow = "1.0.38" -log = "0.4" +anyhow.workspace = true +log.workspace = true editor = { path = "../editor" } fuzzy = { path = "../fuzzy" } gpui = { path = "../gpui" } @@ -24,4 +24,4 @@ theme = { path = "../theme" } theme_selector = { path = "../theme_selector" } util = { path = "../util" } picker = { path = "../picker" } -workspace = { path = "../workspace" } \ No newline at end of file +workspace = { path = "../workspace" } diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 69ee515a91..bd32522e4d 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -35,20 +35,19 @@ settings = { path = "../settings" } terminal = { path = "../terminal" } theme = { path = "../theme" } util = { path = "../util" } + async-recursion = "1.0.0" bincode = "1.2.1" -anyhow = "1.0.38" -futures = { workspace = true } -lazy_static = "1.4" -env_logger = "0.9.1" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } -parking_lot = "0.11.1" -postage = { workspace = true } -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } -smallvec = { workspace = true } -indoc = "1.0.4" +anyhow.workspace = true +futures.workspace = true +lazy_static.workspace = true +log.workspace = true +parking_lot.workspace = true +postage.workspace = true +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true +smallvec.workspace = true uuid = { version = "1.1.2", features = ["v4"] } [dev-dependencies] @@ -59,3 +58,6 @@ project = { path = "../project", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } fs = { path = "../fs", features = ["test-support"] } db = { path = "../db", features = ["test-support"] } + +indoc = "1.0.4" +env_logger.workspace = true diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 68f8555393..a1b9a543c6 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -2784,9 +2784,7 @@ fn notify_if_database_failed(workspace: &ViewHandle, cx: &mut AsyncAp workspace.show_notification_once(0, cx, |cx| { cx.add_view(|_| { MessageNotification::new( - indoc::indoc! {" - Failed to load any database file :( - "}, + "Failed to load any database file.", OsOpen::new("https://github.com/zed-industries/community/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml".to_string()), "Click to let us know about this error" ) @@ -2800,11 +2798,7 @@ fn notify_if_database_failed(workspace: &ViewHandle, cx: &mut AsyncAp let backup_path = backup_path.to_string_lossy(); MessageNotification::new( format!( - indoc::indoc! {" - Database file was corrupted :( - Old database backed up to: - {} - "}, + "Database file was corrupted. Old database backed up to {}", backup_path ), OsOpen::new(backup_path.to_string()), diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 51a41db2b8..2f7f221eac 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -67,40 +67,41 @@ util = { path = "../util" } vim = { path = "../vim" } workspace = { path = "../workspace" } welcome = { path = "../welcome" } -anyhow = "1.0.38" + +anyhow.workspace = true async-compression = { version = "0.3", features = ["gzip", "futures-bufread"] } async-tar = "0.4.2" async-recursion = "0.3" -async-trait = "0.1" +async-trait.workspace = true backtrace = "0.3" chrono = "0.4" ctor = "0.1.20" easy-parallel = "3.1.0" -env_logger = "0.9" -futures = { workspace = true } +env_logger.workspace = true +futures.workspace = true ignore = "0.4" image = "0.23" indexmap = "1.6.2" isahc = "1.7" -lazy_static = "1.4.0" +lazy_static.workspace = true libc = "0.2" -log = { version = "0.4.16", features = ["kv_unstable_serde"] } +log.workspace = true num_cpus = "1.13.0" -parking_lot = "0.11.1" -postage = { workspace = true } -rand = "0.8.3" -regex = "1.5" +parking_lot.workspace = true +postage.workspace = true +rand.workspace = true +regex.workspace = true rsa = "0.4" rust-embed = { version = "6.3", features = ["include-exclude"] } -serde = { workspace = true } -serde_derive = { workspace = true } -serde_json = { workspace = true } +serde.workspace = true +serde_derive.workspace = true +serde_json.workspace = true serde_path_to_error = "0.1.4" simplelog = "0.9" -smallvec = { workspace = true } -smol = "1.2.5" -tempdir = { version = "0.3.7" } -thiserror = "1.0.29" +smallvec.workspace = true +smol.workspace = true +tempdir.workspace = true +thiserror.workspace = true tiny_http = "0.8" toml = "0.5" tree-sitter = "0.20" @@ -116,7 +117,6 @@ tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", tree-sitter-python = "0.20.2" tree-sitter-toml = { git = "https://github.com/tree-sitter/tree-sitter-toml", rev = "342d9be207c2dba869b9967124c679b5e6fd0ebe" } tree-sitter-typescript = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = "5d20856f34315b068c41edaee2ac8a100081d259" } - tree-sitter-ruby = "0.20.0" tree-sitter-html = "0.19.0" tree-sitter-scheme = { git = "https://github.com/6cdh/tree-sitter-scheme", rev = "af0fd1fa452cb2562dc7b5c8a8c55551c39273b9"} @@ -141,9 +141,7 @@ text = { path = "../text", features = ["test-support"] } util = { path = "../util", features = ["test-support"] } workspace = { path = "../workspace", features = ["test-support"] } -env_logger = "0.9" -serde_json = { workspace = true } -unindent = "0.1.7" +unindent.workspace = true [package.metadata.bundle-dev] icon = ["resources/app-icon-preview@2x.png", "resources/app-icon-preview.png"] From 3db67a48b5ace2eef88d530fd838464588570486 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 25 Apr 2023 09:28:50 -0700 Subject: [PATCH 23/23] Preserve previous focus when re-focusing project search --- crates/search/src/project_search.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 18a3171209..986a4b4bfb 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -85,6 +85,7 @@ pub struct ProjectSearchView { query_contains_error: bool, active_match_index: Option, search_id: usize, + query_editor_was_focused: bool, } pub struct ProjectSearchBar { @@ -218,7 +219,11 @@ impl View for ProjectSearchView { }); if cx.is_self_focused() { - self.focus_query_editor(cx); + if self.query_editor_was_focused { + cx.focus(&self.query_editor); + } else { + cx.focus(&self.results_editor); + } } } } @@ -448,6 +453,7 @@ impl ProjectSearchView { regex, query_contains_error: false, active_match_index: None, + query_editor_was_focused: false, }; this.model_changed(cx); this @@ -549,10 +555,11 @@ impl ProjectSearchView { } } - fn focus_query_editor(&self, cx: &mut ViewContext) { + fn focus_query_editor(&mut self, cx: &mut ViewContext) { self.query_editor.update(cx, |query_editor, cx| { query_editor.select_all(&SelectAll, cx); }); + self.query_editor_was_focused = true; cx.focus(&self.query_editor); } @@ -561,11 +568,12 @@ impl ProjectSearchView { .update(cx, |query_editor, cx| query_editor.set_text(query, cx)); } - fn focus_results_editor(&self, cx: &mut ViewContext) { + fn focus_results_editor(&mut self, cx: &mut ViewContext) { self.query_editor.update(cx, |query_editor, cx| { let cursor = query_editor.selections.newest_anchor().head(); query_editor.change_selections(None, cx, |s| s.select_ranges([cursor.clone()..cursor])); }); + self.query_editor_was_focused = false; cx.focus(&self.results_editor); }