From c0e8ae5dfa9bd00917d94cdb887feadbe77fe005 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 23 Oct 2023 11:53:24 +0200 Subject: [PATCH] WIP --- crates/gpui2/src/subscription.rs | 6 +- crates/project2/src/project2.rs | 78 ++++++++++++------------- crates/project2/src/project_settings.rs | 5 +- crates/project2/src/terminals.rs | 10 ++-- 4 files changed, 47 insertions(+), 52 deletions(-) diff --git a/crates/gpui2/src/subscription.rs b/crates/gpui2/src/subscription.rs index 884a28649b..214006b754 100644 --- a/crates/gpui2/src/subscription.rs +++ b/crates/gpui2/src/subscription.rs @@ -21,8 +21,8 @@ struct SubscriberSetState { impl SubscriberSet where - EmitterKey: 'static + Ord + Clone + Debug, - Callback: 'static, + EmitterKey: 'static + Send + Sync + Ord + Clone + Debug, + Callback: 'static + Send + Sync, { pub fn new() -> Self { Self(Arc::new(Mutex::new(SubscriberSetState { @@ -96,7 +96,7 @@ where #[must_use] pub struct Subscription { - unsubscribe: Option>, + unsubscribe: Option>, } impl Subscription { diff --git a/crates/project2/src/project2.rs b/crates/project2/src/project2.rs index 81d19c7861..7e6c7efa35 100644 --- a/crates/project2/src/project2.rs +++ b/crates/project2/src/project2.rs @@ -26,7 +26,8 @@ use futures::{ }; use globset::{Glob, GlobSet, GlobSetBuilder}; use gpui2::{ - AnyHandle, AppContext, AsyncAppContext, EventEmitter, Handle, ModelContext, Task, WeakHandle, + AnyHandle, AppContext, AsyncAppContext, EventEmitter, Executor, Handle, ModelContext, Task, + WeakHandle, }; use itertools::Itertools; use language2::{ @@ -648,6 +649,7 @@ impl Project { _subscriptions: vec![ cx.observe_global::(Self::on_settings_changed), cx.on_release(Self::release), + cx.on_app_quit(Self::shutdown_language_servers), ], _maintain_buffer_languages: Self::maintain_buffer_languages(languages.clone(), cx), _maintain_workspace_config: Self::maintain_workspace_config(cx), @@ -733,7 +735,10 @@ impl Project { next_entry_id: Default::default(), next_diagnostic_group_id: Default::default(), client_subscriptions: Default::default(), - _subscriptions: vec![cx.on_release(Self::release)], + _subscriptions: vec![ + cx.on_release(Self::release), + cx.on_app_quit(Self::shutdown_language_servers), + ], client: client.clone(), client_state: Some(ProjectClientState::Remote { sharing_has_stopped: false, @@ -816,6 +821,24 @@ impl Project { } } + fn shutdown_language_servers(&mut self) -> impl Future { + let shutdown_futures = self + .language_servers + .drain() + .map(|(_, server_state)| async { + use LanguageServerState::*; + match server_state { + Running { server, .. } => server.shutdown()?.await, + Starting(task) => task.await?.shutdown()?.await, + } + }) + .collect::>(); + + async move { + futures::future::join_all(shutdown_futures).await; + } + } + // #[cfg(any(test, feature = "test-support"))] // pub async fn test( // fs: Arc, @@ -2948,7 +2971,7 @@ impl Project { let this = this; let adapter = adapter.clone(); adapter.process_diagnostics(&mut params); - if let Some(this) = this.upgrade(&cx) { + if let Some(this) = this.upgrade() { this.update(&mut cx, |this, cx| { this.update_diagnostics( server_id, @@ -2996,7 +3019,7 @@ impl Project { language_server .on_request::( move |params, mut cx| async move { - if let Some(this) = this.upgrade(&cx) { + if let Some(this) = this.upgrade() { this.update(&mut cx, |this, _| { if let Some(status) = this.language_server_statuses.get_mut(&server_id) { @@ -3013,9 +3036,7 @@ impl Project { language_server .on_request::({ move |params, mut cx| async move { - let this = this - .upgrade(&cx) - .ok_or_else(|| anyhow!("project dropped"))?; + let this = this.upgrade().ok_or_else(|| anyhow!("project dropped"))?; for reg in params.registrations { if reg.method == "workspace/didChangeWatchedFiles" { if let Some(options) = reg.register_options { @@ -3043,9 +3064,7 @@ impl Project { language_server .on_request::({ move |(), mut cx| async move { - let this = this - .upgrade(&cx) - .ok_or_else(|| anyhow!("project dropped"))?; + let this = this.upgrade().ok_or_else(|| anyhow!("project dropped"))?; this.update(&mut cx, |project, cx| { cx.emit(Event::RefreshInlayHints); project.remote_id().map(|project_id| { @@ -3063,7 +3082,7 @@ impl Project { language_server .on_notification::(move |params, mut cx| { - if let Some(this) = this.upgrade(&cx) { + if let Some(this) = this.upgrade() { this.update(&mut cx, |this, cx| { this.on_lsp_progress( params, @@ -3694,7 +3713,7 @@ impl Project { mut cx: AsyncAppContext, ) -> Result { let this = this - .upgrade(&cx) + .upgrade() .ok_or_else(|| anyhow!("project project closed"))?; let language_server = this .read_with(&cx, |this, _| this.language_server_for_id(server_id)) @@ -4823,7 +4842,7 @@ impl Project { None }; Ok(transaction) - }) + })? } else { Ok(None) } @@ -5659,11 +5678,12 @@ impl Project { .detach(); result_rx } + /// Pick paths that might potentially contain a match of a given search query. async fn background_search( unnamed_buffers: Vec>, opened_buffers: HashMap, (Handle, BufferSnapshot)>, - background: Arc, + executor: Executor, fs: Arc, workers: usize, query: SearchQuery, @@ -5694,7 +5714,7 @@ impl Project { .await .log_err(); } - background + executor .scoped(|scope| { for worker_ix in 0..workers { let worker_start_ix = worker_ix * paths_per_worker; @@ -8104,7 +8124,7 @@ impl Project { fn edits_from_lsp( &mut self, buffer: &Handle, - lsp2_edits: impl 'static + Send + IntoIterator, + lsp_edits: impl 'static + Send + IntoIterator, server_id: LanguageServerId, version: Option, cx: &mut ModelContext, @@ -8698,32 +8718,6 @@ impl EventEmitter for Project { type Event = Event; } -impl Entity for Project { - fn app_will_quit( - &mut self, - _: &mut AppContext, - ) -> Option>>> { - let shutdown_futures = self - .language_servers - .drain() - .map(|(_, server_state)| async { - use LanguageServerState::*; - match server_state { - Running { server, .. } => server.shutdown()?.await, - Starting(task) => task.await?.shutdown()?.await, - } - }) - .collect::>(); - - Some( - async move { - futures::future::join_all(shutdown_futures).await; - } - .boxed(), - ) - } -} - impl> From<(WorktreeId, P)> for ProjectPath { fn from((worktree_id, path): (WorktreeId, P)) -> Self { Self { diff --git a/crates/project2/src/project_settings.rs b/crates/project2/src/project_settings.rs index 607b284813..155a976540 100644 --- a/crates/project2/src/project_settings.rs +++ b/crates/project2/src/project_settings.rs @@ -1,7 +1,8 @@ use collections::HashMap; +use gpui2::AppContext; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use settings::Setting; +use settings2::Setting; use std::sync::Arc; #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)] @@ -40,7 +41,7 @@ impl Setting for ProjectSettings { fn load( default_value: &Self::FileContent, user_values: &[&Self::FileContent], - _: &gpui::AppContext, + _: &AppContext, ) -> anyhow::Result { Self::load_via_json_merge(default_value, user_values) } diff --git a/crates/project2/src/terminals.rs b/crates/project2/src/terminals.rs index a47fb39105..e7b18aaef5 100644 --- a/crates/project2/src/terminals.rs +++ b/crates/project2/src/terminals.rs @@ -1,5 +1,5 @@ use crate::Project; -use gpui::{AnyWindowHandle, ModelContext, ModelHandle, WeakModelHandle}; +use gpui2::{AnyWindowHandle, Handle, ModelContext, WeakHandle}; use std::path::{Path, PathBuf}; use terminal::{ terminal_settings::{self, TerminalSettings, VenvSettingsContent}, @@ -10,7 +10,7 @@ use terminal::{ use std::os::unix::ffi::OsStrExt; pub struct Terminals { - pub(crate) local_handles: Vec>, + pub(crate) local_handles: Vec>, } impl Project { @@ -19,13 +19,13 @@ impl Project { working_directory: Option, window: AnyWindowHandle, cx: &mut ModelContext, - ) -> anyhow::Result> { + ) -> anyhow::Result> { if self.is_remote() { return Err(anyhow::anyhow!( "creating terminals as a guest is not supported yet" )); } else { - let settings = settings::get::(cx); + let settings = settings2::get::(cx); let python_settings = settings.detect_venv.clone(); let shell = settings.shell.clone(); @@ -103,7 +103,7 @@ impl Project { fn activate_python_virtual_environment( &mut self, activate_script: Option, - terminal_handle: &ModelHandle, + terminal_handle: &Handle, cx: &mut ModelContext, ) { if let Some(activate_script) = activate_script {