Reuse existing language servers for invisible worktrees (#30707)

Closes https://github.com/zed-industries/zed/issues/20767

Before:


https://github.com/user-attachments/assets/6438eb26-796a-4586-9b20-f49d9a133624


After:



https://github.com/user-attachments/assets/b3fc2f8b-2873-443f-8d80-ab4a35cf0c09



Release Notes:

- Fixed external files spawning extra language servers
This commit is contained in:
Kirill Bulatov 2025-05-14 18:24:17 +02:00 committed by GitHub
parent ef511976be
commit fcfe4e2c14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 400 additions and 107 deletions

View file

@ -28,8 +28,8 @@ use crate::{LanguageServerId, ProjectPath, project_settings::LspSettings};
use super::{ManifestTree, ManifestTreeEvent};
#[derive(Debug, Default)]
struct ServersForWorktree {
roots: BTreeMap<
pub(crate) struct ServersForWorktree {
pub(crate) roots: BTreeMap<
Arc<Path>,
BTreeMap<LanguageServerName, (Arc<InnerTreeNode>, BTreeSet<LanguageName>)>,
>,
@ -37,7 +37,7 @@ struct ServersForWorktree {
pub struct LanguageServerTree {
manifest_tree: Entity<ManifestTree>,
instances: BTreeMap<WorktreeId, ServersForWorktree>,
pub(crate) instances: BTreeMap<WorktreeId, ServersForWorktree>,
attach_kind_cache: HashMap<LanguageServerName, Attach>,
languages: Arc<LanguageRegistry>,
_subscriptions: Subscription,
@ -47,7 +47,7 @@ pub struct LanguageServerTree {
/// - A language server that has already been initialized/updated for a given project
/// - A soon-to-be-initialized language server.
#[derive(Clone)]
pub(crate) struct LanguageServerTreeNode(Weak<InnerTreeNode>);
pub struct LanguageServerTreeNode(Weak<InnerTreeNode>);
/// Describes a request to launch a language server.
#[derive(Debug)]
@ -96,7 +96,7 @@ impl From<Weak<InnerTreeNode>> for LanguageServerTreeNode {
}
#[derive(Debug)]
struct InnerTreeNode {
pub struct InnerTreeNode {
id: OnceLock<LanguageServerId>,
name: LanguageServerName,
attach: Attach,
@ -336,6 +336,28 @@ impl LanguageServerTree {
}
}
}
pub(crate) fn register_reused(
&mut self,
worktree_id: WorktreeId,
language_name: LanguageName,
reused: LanguageServerTreeNode,
) {
let Some(node) = reused.0.upgrade() else {
return;
};
self.instances
.entry(worktree_id)
.or_default()
.roots
.entry(Arc::from(Path::new("")))
.or_default()
.entry(node.name.clone())
.or_insert_with(|| (node, BTreeSet::new()))
.1
.insert(language_name);
}
}
pub(crate) struct ServerTreeRebase<'a> {
@ -441,4 +463,8 @@ impl<'tree> ServerTreeRebase<'tree> {
.filter(|(id, _)| !self.rebased_server_ids.contains(id))
.collect()
}
pub(crate) fn server_tree(&mut self) -> &mut LanguageServerTree {
&mut self.new_tree
}
}