Refactor language server startup

Avoid parallel vecs

Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
Julia 2023-04-19 16:30:24 -04:00 committed by Max Brunsfeld
parent c59204c5e6
commit 9e2949e7ba
2 changed files with 325 additions and 333 deletions

View file

@ -782,13 +782,14 @@ impl LanguageRegistry {
self.state.read().languages.iter().cloned().collect() self.state.read().languages.iter().cloned().collect()
} }
pub fn start_language_servers( pub fn start_language_server(
self: &Arc<Self>, self: &Arc<Self>,
language: Arc<Language>, language: Arc<Language>,
adapter: Arc<CachedLspAdapter>,
root_path: Arc<Path>, root_path: Arc<Path>,
http_client: Arc<dyn HttpClient>, http_client: Arc<dyn HttpClient>,
cx: &mut AppContext, cx: &mut AppContext,
) -> Vec<PendingLanguageServer> { ) -> Option<PendingLanguageServer> {
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
if language.fake_adapter.is_some() { if language.fake_adapter.is_some() {
let task = cx.spawn(|cx| async move { let task = cx.spawn(|cx| async move {
@ -819,22 +820,15 @@ impl LanguageRegistry {
}); });
let server_id = post_inc(&mut self.state.write().next_language_server_id); let server_id = post_inc(&mut self.state.write().next_language_server_id);
return vec![PendingLanguageServer { server_id, task }]; return Some(PendingLanguageServer { server_id, task });
} }
let download_dir = self let download_dir = self
.language_server_download_dir .language_server_download_dir
.clone() .clone()
.ok_or_else(|| anyhow!("language server download directory has not been assigned")) .ok_or_else(|| anyhow!("language server download directory has not been assigned"))
.log_err(); .log_err()?;
let download_dir = match download_dir {
Some(download_dir) => download_dir,
None => return Vec::new(),
};
let mut results = Vec::new();
for adapter in &language.adapters {
let this = self.clone(); let this = self.clone();
let language = language.clone(); let language = language.clone();
let http_client = http_client.clone(); let http_client = http_client.clone();
@ -879,10 +873,7 @@ impl LanguageRegistry {
Ok(server) Ok(server)
}); });
results.push(PendingLanguageServer { server_id, task }); Some(PendingLanguageServer { server_id, task })
}
results
} }
pub fn language_server_binary_statuses( pub fn language_server_binary_statuses(

View file

@ -2137,17 +2137,23 @@ impl Project {
return; return;
} }
let adapters = language.lsp_adapters(); for adapter in language.lsp_adapters() {
let language_servers = self.languages.start_language_servers( let key = (worktree_id, adapter.name.clone());
if self.language_server_ids.contains_key(&key) {
continue;
}
let pending_server = match self.languages.start_language_server(
language.clone(), language.clone(),
adapter.clone(),
worktree_path.clone(), worktree_path.clone(),
self.client.http_client(), self.client.http_client(),
cx, cx,
); ) {
debug_assert_eq!(adapters.len(), language_servers.len()); Some(pending_server) => pending_server,
None => continue,
};
for (adapter, pending_server) in adapters.into_iter().zip(language_servers.into_iter()) {
let key = (worktree_id, adapter.name.clone());
let lsp = &cx.global::<Settings>().lsp.get(&adapter.name.0); let lsp = &cx.global::<Settings>().lsp.get(&adapter.name.0);
let override_options = lsp.map(|s| s.initialization_options.clone()).flatten(); let override_options = lsp.map(|s| s.initialization_options.clone()).flatten();
@ -2160,8 +2166,8 @@ impl Project {
_ => {} _ => {}
} }
if !self.language_server_ids.contains_key(&key) { let server_id = pending_server.server_id;
let adapter = self.setup_pending_language_server( let state = self.setup_pending_language_server(
initialization_options, initialization_options,
pending_server, pending_server,
adapter.clone(), adapter.clone(),
@ -2169,8 +2175,8 @@ impl Project {
key.clone(), key.clone(),
cx, cx,
); );
self.language_server_ids.insert(key.clone(), adapter); self.language_servers.insert(server_id, state);
} self.language_server_ids.insert(key.clone(), server_id);
} }
} }
@ -2182,12 +2188,10 @@ impl Project {
language: Arc<Language>, language: Arc<Language>,
key: (WorktreeId, LanguageServerName), key: (WorktreeId, LanguageServerName),
cx: &mut ModelContext<Project>, cx: &mut ModelContext<Project>,
) -> usize { ) -> LanguageServerState {
let server_id = pending_server.server_id; let server_id = pending_server.server_id;
let languages = self.languages.clone(); let languages = self.languages.clone();
self.language_servers.insert(
server_id,
LanguageServerState::Starting(cx.spawn_weak(|this, mut cx| async move { LanguageServerState::Starting(cx.spawn_weak(|this, mut cx| async move {
let workspace_config = cx.update(|cx| languages.workspace_configuration(cx)).await; let workspace_config = cx.update(|cx| languages.workspace_configuration(cx)).await;
let language_server = pending_server.task.await.log_err()?; let language_server = pending_server.task.await.log_err()?;
@ -2229,7 +2233,6 @@ impl Project {
move |params, mut cx| { move |params, mut cx| {
let languages = languages.clone(); let languages = languages.clone();
async move { async move {
dbg!(&params.items);
let workspace_config = let workspace_config =
cx.update(|cx| languages.workspace_configuration(cx)).await; cx.update(|cx| languages.workspace_configuration(cx)).await;
Ok(params Ok(params
@ -2459,9 +2462,7 @@ impl Project {
cx.notify(); cx.notify();
Some(language_server) Some(language_server)
}) })
})), }))
);
server_id
} }
// Returns a list of all of the worktrees which no longer have a language server and the root path // Returns a list of all of the worktrees which no longer have a language server and the root path