lsp: Remove Attach enum, default to Shared behaviour (#35248)

This should be a no-op PR, behavior-wise.

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2025-07-29 12:07:36 +02:00 committed by GitHub
parent 691b3ca238
commit 6c5791532e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 14 additions and 101 deletions

View file

@ -166,7 +166,6 @@ pub struct CachedLspAdapter {
pub reinstall_attempt_count: AtomicU64, pub reinstall_attempt_count: AtomicU64,
cached_binary: futures::lock::Mutex<Option<LanguageServerBinary>>, cached_binary: futures::lock::Mutex<Option<LanguageServerBinary>>,
manifest_name: OnceLock<Option<ManifestName>>, manifest_name: OnceLock<Option<ManifestName>>,
attach_kind: OnceLock<Attach>,
} }
impl Debug for CachedLspAdapter { impl Debug for CachedLspAdapter {
@ -202,7 +201,6 @@ impl CachedLspAdapter {
adapter, adapter,
cached_binary: Default::default(), cached_binary: Default::default(),
reinstall_attempt_count: AtomicU64::new(0), reinstall_attempt_count: AtomicU64::new(0),
attach_kind: Default::default(),
manifest_name: Default::default(), manifest_name: Default::default(),
}) })
} }
@ -288,29 +286,6 @@ impl CachedLspAdapter {
.get_or_init(|| self.adapter.manifest_name()) .get_or_init(|| self.adapter.manifest_name())
.clone() .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<Path>),
) -> (WorktreeId, Arc<Path>) {
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 /// Determines what gets sent out as a workspace folders content
@ -611,10 +586,6 @@ pub trait LspAdapter: 'static + Send + Sync {
Ok(original) Ok(original)
} }
fn attach_kind(&self) -> Attach {
Attach::Shared
}
/// Determines whether a language server supports workspace folders. /// Determines whether a language server supports workspace folders.
/// ///
/// And does not trip over itself in the process. /// And does not trip over itself in the process.

View file

@ -2425,36 +2425,12 @@ impl LocalLspStore {
let server_id = server_node.server_id_or_init( let server_id = server_node.server_id_or_init(
|LaunchDisposition { |LaunchDisposition {
server_name, server_name,
attach,
path, path,
settings, settings,
}| { }| {
let server_id = match attach { let server_id =
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 uri = Url::from_file_path( let uri = Url::from_file_path(
worktree.read(cx).abs_path().join(&path.path), worktree.read(cx).abs_path().join(&path.path),
); );
@ -2489,7 +2465,7 @@ impl LocalLspStore {
} else { } else {
unreachable!("Language server ID should be available, as it's registered on demand") unreachable!("Language server ID should be available, as it's registered on demand")
} }
}
}; };
let lsp_store = self.weak.clone(); let lsp_store = self.weak.clone();
let server_name = server_node.name(); let server_name = server_node.name();
@ -4705,35 +4681,11 @@ impl LspStore {
let server_id = node.server_id_or_init( let server_id = node.server_id_or_init(
|LaunchDisposition { |LaunchDisposition {
server_name, server_name,
attach,
path, path,
settings, 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( let uri = Url::from_file_path(
worktree.read(cx).abs_path().join(&path.path), worktree.read(cx).abs_path().join(&path.path),
); );
@ -4762,7 +4714,6 @@ impl LspStore {
} }
server_id server_id
} }
},
); );
if let Some(language_server_id) = server_id { if let Some(language_server_id) = server_id {

View file

@ -13,10 +13,10 @@ use std::{
sync::{Arc, Weak}, sync::{Arc, Weak},
}; };
use collections::{HashMap, IndexMap}; use collections::IndexMap;
use gpui::{App, AppContext as _, Entity, Subscription}; use gpui::{App, AppContext as _, Entity, Subscription};
use language::{ use language::{
Attach, CachedLspAdapter, LanguageName, LanguageRegistry, ManifestDelegate, CachedLspAdapter, LanguageName, LanguageRegistry, ManifestDelegate,
language_settings::AllLanguageSettings, language_settings::AllLanguageSettings,
}; };
use lsp::LanguageServerName; use lsp::LanguageServerName;
@ -38,7 +38,6 @@ pub(crate) struct ServersForWorktree {
pub struct LanguageServerTree { pub struct LanguageServerTree {
manifest_tree: Entity<ManifestTree>, manifest_tree: Entity<ManifestTree>,
pub(crate) instances: BTreeMap<WorktreeId, ServersForWorktree>, pub(crate) instances: BTreeMap<WorktreeId, ServersForWorktree>,
attach_kind_cache: HashMap<LanguageServerName, Attach>,
languages: Arc<LanguageRegistry>, languages: Arc<LanguageRegistry>,
_subscriptions: Subscription, _subscriptions: Subscription,
} }
@ -53,7 +52,6 @@ pub struct LanguageServerTreeNode(Weak<InnerTreeNode>);
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct LaunchDisposition<'a> { pub(crate) struct LaunchDisposition<'a> {
pub(crate) server_name: &'a LanguageServerName, pub(crate) server_name: &'a LanguageServerName,
pub(crate) attach: Attach,
pub(crate) path: ProjectPath, pub(crate) path: ProjectPath,
pub(crate) settings: Arc<LspSettings>, pub(crate) settings: Arc<LspSettings>,
} }
@ -62,7 +60,6 @@ impl<'a> From<&'a InnerTreeNode> for LaunchDisposition<'a> {
fn from(value: &'a InnerTreeNode) -> Self { fn from(value: &'a InnerTreeNode) -> Self {
LaunchDisposition { LaunchDisposition {
server_name: &value.name, server_name: &value.name,
attach: value.attach,
path: value.path.clone(), path: value.path.clone(),
settings: value.settings.clone(), settings: value.settings.clone(),
} }
@ -105,7 +102,6 @@ impl From<Weak<InnerTreeNode>> for LanguageServerTreeNode {
pub struct InnerTreeNode { pub struct InnerTreeNode {
id: OnceLock<LanguageServerId>, id: OnceLock<LanguageServerId>,
name: LanguageServerName, name: LanguageServerName,
attach: Attach,
path: ProjectPath, path: ProjectPath,
settings: Arc<LspSettings>, settings: Arc<LspSettings>,
} }
@ -113,14 +109,12 @@ pub struct InnerTreeNode {
impl InnerTreeNode { impl InnerTreeNode {
fn new( fn new(
name: LanguageServerName, name: LanguageServerName,
attach: Attach,
path: ProjectPath, path: ProjectPath,
settings: impl Into<Arc<LspSettings>>, settings: impl Into<Arc<LspSettings>>,
) -> Self { ) -> Self {
InnerTreeNode { InnerTreeNode {
id: Default::default(), id: Default::default(),
name, name,
attach,
path, path,
settings: settings.into(), settings: settings.into(),
} }
@ -130,8 +124,11 @@ impl InnerTreeNode {
/// Determines how the list of adapters to query should be constructed. /// Determines how the list of adapters to query should be constructed.
pub(crate) enum AdapterQuery<'a> { pub(crate) enum AdapterQuery<'a> {
/// Search for roots of all adapters associated with a given language name. /// 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), Language(&'a LanguageName),
/// Search for roots of adapter with a given name. /// 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), Adapter(&'a LanguageServerName),
} }
@ -147,7 +144,7 @@ impl LanguageServerTree {
}), }),
manifest_tree, manifest_tree,
instances: Default::default(), instances: Default::default(),
attach_kind_cache: Default::default(),
languages, languages,
}) })
} }
@ -223,7 +220,6 @@ impl LanguageServerTree {
.and_then(|name| roots.get(&name)) .and_then(|name| roots.get(&name))
.cloned() .cloned()
.unwrap_or_else(|| root_path.clone()); .unwrap_or_else(|| root_path.clone());
let attach = adapter.attach_kind();
let inner_node = self let inner_node = self
.instances .instances
@ -237,7 +233,6 @@ impl LanguageServerTree {
( (
Arc::new(InnerTreeNode::new( Arc::new(InnerTreeNode::new(
adapter.name(), adapter.name(),
attach,
root_path.clone(), root_path.clone(),
settings.clone(), settings.clone(),
)), )),
@ -379,7 +374,6 @@ pub(crate) struct ServerTreeRebase<'a> {
impl<'tree> ServerTreeRebase<'tree> { impl<'tree> ServerTreeRebase<'tree> {
fn new(new_tree: &'tree mut LanguageServerTree) -> Self { fn new(new_tree: &'tree mut LanguageServerTree) -> Self {
let old_contents = std::mem::take(&mut new_tree.instances); let old_contents = std::mem::take(&mut new_tree.instances);
new_tree.attach_kind_cache.clear();
let all_server_ids = old_contents let all_server_ids = old_contents
.values() .values()
.flat_map(|nodes| { .flat_map(|nodes| {
@ -446,10 +440,7 @@ impl<'tree> ServerTreeRebase<'tree> {
.get(&disposition.path.worktree_id) .get(&disposition.path.worktree_id)
.and_then(|worktree_nodes| worktree_nodes.roots.get(&disposition.path.path)) .and_then(|worktree_nodes| worktree_nodes.roots.get(&disposition.path.path))
.and_then(|roots| roots.get(&disposition.name)) .and_then(|roots| roots.get(&disposition.name))
.filter(|(old_node, _)| { .filter(|(old_node, _)| disposition.settings == old_node.settings)
disposition.attach == old_node.attach
&& disposition.settings == old_node.settings
})
else { else {
return Some(node); return Some(node);
}; };