From 36a1a7a81909d83b82ca77a7c7f645b64b1db8d1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 9 Jun 2022 10:08:11 +0200 Subject: [PATCH] Start/stop language servers when `enable_language_server` changes --- crates/language/src/language.rs | 4 ++ crates/project/src/project.rs | 69 ++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index fbc8182d30..1d54bd35cd 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -240,6 +240,10 @@ impl LanguageRegistry { .cloned() } + pub fn to_vec(&self) -> Vec> { + self.languages.read().iter().cloned().collect() + } + pub fn language_names(&self) -> Vec { self.languages .read() diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index e49f3b424c..c2859078ca 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -90,7 +90,8 @@ pub struct Project { fs: Arc, client_state: ProjectClientState, collaborators: HashMap, - subscriptions: Vec, + client_subscriptions: Vec, + _subscriptions: Vec, opened_buffer: (Rc>>, watch::Receiver<()>), shared_buffers: HashMap>, loading_buffers: HashMap< @@ -418,7 +419,8 @@ impl Project { _maintain_remote_id_task, }, opened_buffer: (Rc::new(RefCell::new(opened_buffer_tx)), opened_buffer_rx), - subscriptions: Vec::new(), + client_subscriptions: Vec::new(), + _subscriptions: vec![cx.observe_global::(Self::on_settings_changed)], active_entry: None, languages, client, @@ -503,7 +505,8 @@ impl Project { fs, next_entry_id: Default::default(), next_diagnostic_group_id: Default::default(), - subscriptions: vec![client.add_model_for_remote_entity(remote_id, cx)], + client_subscriptions: vec![client.add_model_for_remote_entity(remote_id, cx)], + _subscriptions: Default::default(), client: client.clone(), client_state: ProjectClientState::Remote { sharing_has_stopped: false, @@ -650,6 +653,55 @@ impl Project { }) } + fn on_settings_changed(&mut self, cx: &mut ModelContext) { + let settings = cx.global::(); + + let mut language_servers_to_start = Vec::new(); + for buffer in self.opened_buffers.values() { + if let Some(buffer) = buffer.upgrade(cx) { + let buffer = buffer.read(cx); + if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) + { + if settings.enable_language_server(Some(&language.name())) { + let worktree = file.worktree.read(cx); + language_servers_to_start.push(( + worktree.id(), + worktree.as_local().unwrap().abs_path().clone(), + language.clone(), + )); + } + } + } + } + + let mut language_servers_to_stop = Vec::new(); + for language in self.languages.to_vec() { + if let Some(lsp_adapter) = language.lsp_adapter() { + if !settings.enable_language_server(Some(&language.name())) { + let lsp_name = lsp_adapter.name(); + for (worktree_id, started_lsp_name) in self.started_language_servers.keys() { + if lsp_name == *started_lsp_name { + language_servers_to_stop.push((*worktree_id, started_lsp_name.clone())); + } + } + } + } + } + + // Stop all newly-disabled language servers. + for (worktree_id, adapter_name) in language_servers_to_stop { + self.stop_language_server(worktree_id, adapter_name, cx) + .detach(); + } + + // Start all the newly-enabled language servers. + for (worktree_id, worktree_path, language) in language_servers_to_start { + self.start_language_server(worktree_id, worktree_path, language, cx); + } + + cx.notify(); + } + pub fn buffer_for_id(&self, remote_id: u64, cx: &AppContext) -> Option> { self.opened_buffers .get(&remote_id) @@ -775,7 +827,7 @@ impl Project { { *remote_id_tx.borrow_mut() = None; } - this.subscriptions.clear(); + this.client_subscriptions.clear(); this.metadata_changed(false, cx); }); response.map(drop) @@ -802,7 +854,7 @@ impl Project { this.metadata_changed(false, cx); cx.emit(Event::RemoteIdChanged(Some(remote_id))); - this.subscriptions + this.client_subscriptions .push(this.client.add_model_for_remote_entity(remote_id, cx)); Ok(()) }) @@ -1858,6 +1910,13 @@ impl Project { language: Arc, cx: &mut ModelContext, ) { + if !cx + .global::() + .enable_language_server(Some(&language.name())) + { + return; + } + let adapter = if let Some(adapter) = language.lsp_adapter() { adapter } else {