From 6c5791532ea2dbea26167ed79a832f075707ad9a Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 29 Jul 2025 12:07:36 +0200 Subject: [PATCH] lsp: Remove Attach enum, default to Shared behaviour (#35248) This should be a no-op PR, behavior-wise. Release Notes: - N/A --- crates/language/src/language.rs | 29 --------- crates/project/src/lsp_store.rs | 63 +++---------------- .../project/src/manifest_tree/server_tree.rs | 23 +++---- 3 files changed, 14 insertions(+), 101 deletions(-) diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 7cda2b4b5a..549afc931c 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -166,7 +166,6 @@ pub struct CachedLspAdapter { pub reinstall_attempt_count: AtomicU64, cached_binary: futures::lock::Mutex>, manifest_name: OnceLock>, - attach_kind: OnceLock, } impl Debug for CachedLspAdapter { @@ -202,7 +201,6 @@ impl CachedLspAdapter { adapter, cached_binary: Default::default(), reinstall_attempt_count: AtomicU64::new(0), - attach_kind: Default::default(), manifest_name: Default::default(), }) } @@ -288,29 +286,6 @@ impl CachedLspAdapter { .get_or_init(|| self.adapter.manifest_name()) .clone() } - pub fn attach_kind(&self) -> Attach { - *self.attach_kind.get_or_init(|| self.adapter.attach_kind()) - } -} - -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum Attach { - /// Create a single language server instance per subproject root. - InstancePerRoot, - /// Use one shared language server instance for all subprojects within a project. - Shared, -} - -impl Attach { - pub fn root_path( - &self, - root_subproject_path: (WorktreeId, Arc), - ) -> (WorktreeId, Arc) { - match self { - Attach::InstancePerRoot => root_subproject_path, - Attach::Shared => (root_subproject_path.0, Arc::from(Path::new(""))), - } - } } /// Determines what gets sent out as a workspace folders content @@ -611,10 +586,6 @@ pub trait LspAdapter: 'static + Send + Sync { Ok(original) } - fn attach_kind(&self) -> Attach { - Attach::Shared - } - /// Determines whether a language server supports workspace folders. /// /// And does not trip over itself in the process. diff --git a/crates/project/src/lsp_store.rs b/crates/project/src/lsp_store.rs index defe056dd8..5b523c9a03 100644 --- a/crates/project/src/lsp_store.rs +++ b/crates/project/src/lsp_store.rs @@ -2425,36 +2425,12 @@ impl LocalLspStore { let server_id = server_node.server_id_or_init( |LaunchDisposition { server_name, - attach, + path, settings, }| { - let server_id = match attach { - language::Attach::InstancePerRoot => { - // todo: handle instance per root proper. - if let Some(server_ids) = self - .language_server_ids - .get(&(worktree_id, server_name.clone())) - { - server_ids.iter().cloned().next().unwrap() - } else { - let language_name = language.name(); - let adapter = self.languages - .lsp_adapters(&language_name) - .into_iter() - .find(|adapter| &adapter.name() == server_name) - .expect("To find LSP adapter"); - let server_id = self.start_language_server( - &worktree, - delegate.clone(), - adapter, - settings, - cx, - ); - server_id - } - } - language::Attach::Shared => { + let server_id = + { let uri = Url::from_file_path( worktree.read(cx).abs_path().join(&path.path), ); @@ -2489,7 +2465,7 @@ impl LocalLspStore { } else { unreachable!("Language server ID should be available, as it's registered on demand") } - } + }; let lsp_store = self.weak.clone(); let server_name = server_node.name(); @@ -4705,35 +4681,11 @@ impl LspStore { let server_id = node.server_id_or_init( |LaunchDisposition { server_name, - attach, + path, settings, - }| match attach { - language::Attach::InstancePerRoot => { - // todo: handle instance per root proper. - if let Some(server_ids) = local - .language_server_ids - .get(&(worktree_id, server_name.clone())) - { - server_ids.iter().cloned().next().unwrap() - } else { - let adapter = local - .languages - .lsp_adapters(&language) - .into_iter() - .find(|adapter| &adapter.name() == server_name) - .expect("To find LSP adapter"); - let server_id = local.start_language_server( - &worktree, - delegate.clone(), - adapter, - settings, - cx, - ); - server_id - } - } - language::Attach::Shared => { + }| + { let uri = Url::from_file_path( worktree.read(cx).abs_path().join(&path.path), ); @@ -4762,7 +4714,6 @@ impl LspStore { } server_id } - }, ); if let Some(language_server_id) = server_id { diff --git a/crates/project/src/manifest_tree/server_tree.rs b/crates/project/src/manifest_tree/server_tree.rs index 0283f06eec..81cb1c450c 100644 --- a/crates/project/src/manifest_tree/server_tree.rs +++ b/crates/project/src/manifest_tree/server_tree.rs @@ -13,10 +13,10 @@ use std::{ sync::{Arc, Weak}, }; -use collections::{HashMap, IndexMap}; +use collections::IndexMap; use gpui::{App, AppContext as _, Entity, Subscription}; use language::{ - Attach, CachedLspAdapter, LanguageName, LanguageRegistry, ManifestDelegate, + CachedLspAdapter, LanguageName, LanguageRegistry, ManifestDelegate, language_settings::AllLanguageSettings, }; use lsp::LanguageServerName; @@ -38,7 +38,6 @@ pub(crate) struct ServersForWorktree { pub struct LanguageServerTree { manifest_tree: Entity, pub(crate) instances: BTreeMap, - attach_kind_cache: HashMap, languages: Arc, _subscriptions: Subscription, } @@ -53,7 +52,6 @@ pub struct LanguageServerTreeNode(Weak); #[derive(Debug)] pub(crate) struct LaunchDisposition<'a> { pub(crate) server_name: &'a LanguageServerName, - pub(crate) attach: Attach, pub(crate) path: ProjectPath, pub(crate) settings: Arc, } @@ -62,7 +60,6 @@ impl<'a> From<&'a InnerTreeNode> for LaunchDisposition<'a> { fn from(value: &'a InnerTreeNode) -> Self { LaunchDisposition { server_name: &value.name, - attach: value.attach, path: value.path.clone(), settings: value.settings.clone(), } @@ -105,7 +102,6 @@ impl From> for LanguageServerTreeNode { pub struct InnerTreeNode { id: OnceLock, name: LanguageServerName, - attach: Attach, path: ProjectPath, settings: Arc, } @@ -113,14 +109,12 @@ pub struct InnerTreeNode { impl InnerTreeNode { fn new( name: LanguageServerName, - attach: Attach, path: ProjectPath, settings: impl Into>, ) -> Self { InnerTreeNode { id: Default::default(), name, - attach, path, settings: settings.into(), } @@ -130,8 +124,11 @@ impl InnerTreeNode { /// Determines how the list of adapters to query should be constructed. pub(crate) enum AdapterQuery<'a> { /// Search for roots of all adapters associated with a given language name. + /// Layman: Look for all project roots along the queried path that have any + /// language server associated with this language running. Language(&'a LanguageName), /// Search for roots of adapter with a given name. + /// Layman: Look for all project roots along the queried path that have this server running. Adapter(&'a LanguageServerName), } @@ -147,7 +144,7 @@ impl LanguageServerTree { }), manifest_tree, instances: Default::default(), - attach_kind_cache: Default::default(), + languages, }) } @@ -223,7 +220,6 @@ impl LanguageServerTree { .and_then(|name| roots.get(&name)) .cloned() .unwrap_or_else(|| root_path.clone()); - let attach = adapter.attach_kind(); let inner_node = self .instances @@ -237,7 +233,6 @@ impl LanguageServerTree { ( Arc::new(InnerTreeNode::new( adapter.name(), - attach, root_path.clone(), settings.clone(), )), @@ -379,7 +374,6 @@ pub(crate) struct ServerTreeRebase<'a> { impl<'tree> ServerTreeRebase<'tree> { fn new(new_tree: &'tree mut LanguageServerTree) -> Self { let old_contents = std::mem::take(&mut new_tree.instances); - new_tree.attach_kind_cache.clear(); let all_server_ids = old_contents .values() .flat_map(|nodes| { @@ -446,10 +440,7 @@ impl<'tree> ServerTreeRebase<'tree> { .get(&disposition.path.worktree_id) .and_then(|worktree_nodes| worktree_nodes.roots.get(&disposition.path.path)) .and_then(|roots| roots.get(&disposition.name)) - .filter(|(old_node, _)| { - disposition.attach == old_node.attach - && disposition.settings == old_node.settings - }) + .filter(|(old_node, _)| disposition.settings == old_node.settings) else { return Some(node); };