diff --git a/Cargo.lock b/Cargo.lock index 7c2f043193..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" @@ -3612,6 +3609,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" @@ -7239,7 +7256,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", @@ -8571,6 +8588,7 @@ dependencies = [ "libc", "log", "lsp", + "lsp_log", "node_runtime", "num_cpus", "outline", diff --git a/Cargo.toml b/Cargo.toml index 1275571668..1ef283d135 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", @@ -71,12 +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"] } +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 b54271ee2d..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 = "0.3" -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 4e738c0651..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 = "0.3" -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 560a754bf7..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 = "0.3" +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 778ae42ec4..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 = "0.3" +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/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, diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index 50f81c335c..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 = "0.3" -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/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/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 f4d75cc582..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 = "0.3" +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 f44493b323..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 = "0.3" +anyhow.workspace = true +smol.workspace = true +futures.workspace = true diff --git a/crates/copilot_button/src/copilot_button.rs b/crates/copilot_button/src/copilot_button.rs index da13ce4413..c8bfcc7550 100644 --- a/crates/copilot_button/src/copilot_button.rs +++ b/crates/copilot_button/src/copilot_button.rs @@ -272,7 +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("Hide Copilot", HideCopilot)); + menu_options.push(ContextMenuItem::item("Disable Copilot", HideCopilot)); self.popup_menu.update(cx, |menu, cx| { menu.show( 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 4cd81df1dc..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 = "0.3" +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/editor/src/editor.rs b/crates/editor/src/editor.rs index 41f9a3fd3f..2fa5eabcd9 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/feedback/Cargo.toml b/crates/feedback/Cargo.toml index 57b91876e3..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 = "0.3" +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 f4981ac13a..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 = "0.3" +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 3e88d72313..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 = "0.3" +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 88c40665c2..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 = "0.3" +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/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index 3c5ab96a86..908f58e33e 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -419,6 +419,11 @@ impl<'a> WindowContext<'a> { .map(|action_type| (action_type, depth)), ); } + } else { + log::error!( + "view {} not found when computing available actions", + view_id + ); } } 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 4e15ccf679..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 = "0.3" -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 70032d83aa..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 = "0.3" -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 = "0.3" +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 8cced6d089..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 = "0.3" +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 4370aaab06..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 = "0.3" -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/src/lsp.rs b/crates/lsp/src/lsp.rs index b6a4d8513e..f4f538b061 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,15 @@ pub struct LanguageServer { #[repr(transparent)] pub struct LanguageServerId(pub usize); -pub struct Subscription { - method: &'static str, - notification_handlers: Arc>>, +pub enum Subscription { + Notification { + method: &'static str, + notification_handlers: Option>>>, + }, + Io { + id: usize, + io_handlers: Option>>>, + }, } #[derive(Serialize, Deserialize)] @@ -177,33 +185,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 +241,7 @@ impl LanguageServer { mut on_unhandled_notification: F, notification_handlers: Arc>>, response_handlers: Arc>>>, + io_handlers: Arc>>, cx: AsyncAppContext, ) -> anyhow::Result<()> where @@ -252,7 +268,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 +313,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 +330,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 +491,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: Some(Arc::downgrade(&self.io_handlers)), + } + } + pub fn remove_request_handler(&self) { self.notification_handlers.lock().remove(T::METHOD); } @@ -490,9 +530,9 @@ impl LanguageServer { prev_handler.is_none(), "registered multiple handlers for the same LSP method" ); - Subscription { + Subscription::Notification { method, - notification_handlers: self.notification_handlers.clone(), + notification_handlers: Some(self.notification_handlers.clone()), } } @@ -537,7 +577,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 +600,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,9 +612,9 @@ impl LanguageServer { prev_handler.is_none(), "registered multiple handlers for the same LSP method" ); - Subscription { + Subscription::Notification { method, - notification_handlers: self.notification_handlers.clone(), + notification_handlers: Some(self.notification_handlers.clone()), } } @@ -612,14 +652,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 +702,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, @@ -685,8 +725,14 @@ impl Drop for LanguageServer { } impl Subscription { - pub fn detach(mut self) { - self.method = ""; + pub fn detach(&mut self) { + match self { + Subscription::Notification { + notification_handlers, + .. + } => *notification_handlers = None, + Subscription::Io { io_handlers, .. } => *io_handlers = None, + } } } @@ -698,7 +744,21 @@ impl fmt::Display for LanguageServerId { impl Drop for Subscription { fn drop(&mut self) { - self.notification_handlers.lock().remove(self.method); + match self { + Subscription::Notification { + method, + notification_handlers, + } => { + if let Some(handlers) = notification_handlers { + handlers.lock().remove(method); + } + } + Subscription::Io { id, io_handlers } => { + if let Some(io_handlers) = io_handlers.as_ref().and_then(|h| h.upgrade()) { + io_handlers.lock().remove(id); + } + } + } } } diff --git a/crates/lsp_log/Cargo.toml b/crates/lsp_log/Cargo.toml new file mode 100644 index 0000000000..8741f0a4cf --- /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.workspace = true + +[dev-dependencies] +gpui = { path = "../gpui", features = ["test-support"] } +util = { path = "../util", features = ["test-support"] } +unindent.workspace = true diff --git a/crates/lsp_log/src/lsp_log.rs b/crates/lsp_log/src/lsp_log.rs new file mode 100644 index 0000000000..0efcd3afc8 --- /dev/null +++ b/crates/lsp_log/src/lsp_log.rs @@ -0,0 +1,523 @@ +use collections::{hash_map, HashMap}; +use editor::Editor; +use futures::{channel::mpsc, StreamExt}; +use gpui::{ + actions, + elements::{ + AnchorCorner, ChildView, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, + ParentElement, Stack, + }, + 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::{ui, Theme}; +use workspace::{ + item::{Item, ItemHandle}, + ToolbarItemLocation, ToolbarItemView, 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 { + log_store: ModelHandle, + current_server_id: Option, + editor: Option>, + project: ModelHandle, +} + +pub struct LspLogToolbarItemView { + log_view: Option>, + menu_open: bool, + project: ModelHandle, +} + +#[derive(Copy, Clone, PartialEq, Eq)] +enum MessageKind { + Send, + Receive, +} + +actions!(log, [OpenLanguageServerLogs]); + +pub fn init(cx: &mut AppContext) { + 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 LogStore { + fn new(cx: &mut ModelContext) -> Self { + let (io_tx, mut io_rx) = mpsc::unbounded(); + let this = Self { + projects: HashMap::default(), + io_tx, + }; + cx.spawn_weak(|this, mut cx| async move { + 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(project, server_id, is_output, &message, cx); + }); + } + } + anyhow::Ok(()) + }) + .detach(); + this + } + + 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, _, _| { + 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, + _: &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, + ) { + 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); + } + }); + } +} + +impl View for LspLogView { + fn ui_name() -> &'static str { + "LspLogView" + } + + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { + if let Some(editor) = &self.editor { + ChildView::new(&editor, cx).into_any() + } else { + Empty::new().into_any() + } + } +} + +impl Item for LspLogView { + fn tab_content( + &self, + _: Option, + style: &theme::Tab, + _: &AppContext, + ) -> AnyElement { + Label::new("LSP Logs", style.label.clone()).into_any() + } +} + +impl ToolbarItemView for LspLogToolbarItemView { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + _: &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 ViewContext) -> AnyElement { + 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 log_view = log_view.read(cx); + let log_store = log_view.log_store.read(cx); + + 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()) + } else { + None + } + }); + + enum Menu {} + + 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( + 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) + .with_z_index(999) + .aligned() + .bottom() + .left(), + ) + } else { + None + }) + .aligned() + .left() + .clipped() + .into_any() + } +} + +impl LspLogToolbarItemView { + pub fn new(project: ModelHandle) -> Self { + Self { + menu_open: false, + log_view: None, + project, + } + } + + fn toggle_menu(&mut self, cx: &mut ViewContext) { + self.menu_open = !self.menu_open; + cx.notify(); + } + + 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.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(); + } + }); + } + 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; + } + cx.notify(); + } + + fn render_language_server_menu_header( + current_server: Option<(LanguageServerId, LanguageServerName, WorktreeId, bool)>, + project: &ModelHandle, + theme: &Arc, + 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, _)| { + 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 + .style_for(state, false) + .label + .clone(), + ) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| { + view.toggle_menu(cx); + }) + } + + fn render_language_server_menu_item( + id: LanguageServerId, + name: LanguageServerName, + worktree_id: WorktreeId, + logging_enabled: bool, + is_selected: bool, + project: &ModelHandle, + theme: &Arc, + 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); + if !worktree.is_visible() { + return None; + } + let label = format!("{} - ({})", name.0, worktree.root_name()); + + Some( + MouseEventHandler::::new(id.0, cx, move |state, cx| { + 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()).aligned().left()) + .align_children_center() + .contained() + .with_style(item_style.container) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| { + view.show_logs_for_server(id, cx); + }), + ) + } +} + +impl Entity for LogStore { + type Event = (); +} + +impl Entity for LspLogView { + type Event = (); +} + +impl Entity for LspLogToolbarItemView { + type Event = (); +} 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 32ab6abbb3..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 = "0.3" -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 e30ab56e45..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 = "0.3" +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/src/project.rs b/crates/project/src/project.rs index e5fc1e1b3b..d543f225b2 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,11 +137,16 @@ struct LspBufferSnapshot { snapshot: TextBufferSnapshot, } -enum BufferMessage { +/// Message ordered with respect to buffer operations +enum BufferOrderedMessage { Operation { buffer_id: u64, operation: proto::Operation, }, + LanguageServerUpdate { + language_server_id: LanguageServerId, + message: proto::update_language_server::Variant, + }, Resync, } @@ -185,6 +190,8 @@ pub struct Collaborator { #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { + LanguageServerAdded(LanguageServerId), + LanguageServerRemoved(LanguageServerId), ActiveEntryChanged(Option), WorktreeAdded, WorktreeRemoved(WorktreeId), @@ -441,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(), @@ -509,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(), @@ -1166,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(()) @@ -1782,23 +1789,49 @@ 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; - 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()); for change in changes { match change { - BufferMessage::Operation { + BufferOrderedMessage::Operation { buffer_id, operation, } => { @@ -1811,7 +1844,8 @@ impl Project { .or_insert(Vec::new()) .push(operation); } - BufferMessage::Resync => { + + BufferOrderedMessage::Resync => { operations_by_buffer_id.clear(); if this .update(&mut cx, |this, cx| this.synchronize_remote_buffers(cx)) @@ -1821,25 +1855,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; + BufferOrderedMessage::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 @@ -1853,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), }) @@ -1869,7 +1921,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(); @@ -1960,19 +2012,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_ordered_messages_tx + .unbounded_send( + BufferOrderedMessage::LanguageServerUpdate { + language_server_id, + message:proto::update_language_server::Variant::DiskBasedDiagnosticsUpdated(Default::default()) + }, + ) + .ok(); + }); + } + }); *simulate_disk_based_diagnostics_completion = Some(task); } } @@ -2607,7 +2664,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, ) { @@ -2620,7 +2677,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; @@ -2640,16 +2697,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_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::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(), @@ -2658,20 +2715,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_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::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(), @@ -2680,16 +2741,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_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::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(_) => { @@ -2697,21 +2760,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_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::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_ordered_messages_tx + .unbounded_send(BufferOrderedMessage::LanguageServerUpdate { + language_server_id, + message: proto::update_language_server::Variant::WorkEnd( + proto::LspWorkEnd { token }, + ), + }) + .ok(); } } } @@ -2820,22 +2888,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 { @@ -4864,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(); } @@ -6279,7 +6331,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 +6369,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 +6383,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/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 2b72959e25..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 = "0.3" +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 9e79b09d72..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 = "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/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 2773dd2f3b..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 = "0.3" -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 fb4e79a703..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 = "0.3" -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/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); } diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index fbb3ad63f3..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 = "0.3" +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 716ec76644..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 = "0.3" -uuid = { version = "1.1.2", features = ["v4"] } \ No newline at end of file +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 107d325677..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 = "0.3" -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/src/terminal.rs b/crates/terminal/src/terminal.rs index d951633bb3..25852875c3 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, @@ -664,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); @@ -1024,6 +1026,8 @@ impl Terminal { self.last_content.size, self.last_content.display_offset, ); + + // Use .opposite so that selection is inclusive of the cell clicked. let side = mouse_side(position, self.last_content.size); let selection_type = match e.click_count { @@ -1074,7 +1078,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 +1258,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 +1277,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 +1298,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 +1335,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 +1376,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() + } } } diff --git a/crates/terminal_view/Cargo.toml b/crates/terminal_view/Cargo.toml index f271cd118d..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 = "0.3" -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/terminal_view/src/terminal_element.rs b/crates/terminal_view/src/terminal_element.rs index b34c78b58b..55e10a3195 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 Element 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) { @@ -713,6 +718,7 @@ impl Element for TerminalElement { mode: *mode, display_offset: *display_offset, hyperlink_tooltip, + gutter, }, ) } @@ -732,7 +738,7 @@ impl Element 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); 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/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/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 38124dcc11..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 = "0.3" +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/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) }) diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 84db04e9a6..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 = "0.3" -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 bc493f9aba..c0fb1a9448 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 7eb35f3b3e..2f7f221eac 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" } @@ -66,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 = "0.3" +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" @@ -109,13 +111,12 @@ 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" 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"} @@ -140,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"] 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; 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); }) }); }