Hack extensions language servers to record their IDs

This commit is contained in:
Lukas Wirth 2025-08-23 16:37:32 +02:00
parent 4292d883b0
commit 557fbe5c68
3 changed files with 36 additions and 9 deletions

View file

@ -281,7 +281,7 @@ pub trait ExtensionLanguageServerProxy: Send + Sync + 'static {
fn update_language_server_status( fn update_language_server_status(
&self, &self,
language_server_id: LanguageServerName, language_server_name: LanguageServerName,
status: BinaryStatus, status: BinaryStatus,
); );
} }
@ -315,14 +315,14 @@ impl ExtensionLanguageServerProxy for ExtensionHostProxy {
fn update_language_server_status( fn update_language_server_status(
&self, &self,
language_server_id: LanguageServerName, language_server_name: LanguageServerName,
status: BinaryStatus, status: BinaryStatus,
) { ) {
let Some(proxy) = self.language_server_proxy.read().clone() else { let Some(proxy) = self.language_server_proxy.read().clone() else {
return; return;
}; };
proxy.update_language_server_status(language_server_id, status) proxy.update_language_server_status(language_server_name, status)
} }
} }

View file

@ -1,8 +1,8 @@
use std::any::Any;
use std::ops::Range; use std::ops::Range;
use std::path::PathBuf; use std::path::PathBuf;
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use std::{any::Any, sync::OnceLock};
use anyhow::{Context as _, Result}; use anyhow::{Context as _, Result};
use async_trait::async_trait; use async_trait::async_trait;
@ -61,12 +61,18 @@ impl ExtensionLanguageServerProxy for LanguageServerRegistryProxy {
language_server_name: LanguageServerName, language_server_name: LanguageServerName,
language: LanguageName, language: LanguageName,
) { ) {
let language_server_id = Arc::new(OnceLock::new());
self.language_server_ids
.write()
.unwrap()
.insert(language_server_name.clone(), language_server_id.clone());
self.language_registry.register_lsp_adapter( self.language_registry.register_lsp_adapter(
language.clone(), language.clone(),
Arc::new(ExtensionLspAdapter::new( Arc::new(ExtensionLspAdapter::new(
extension, extension,
language_server_name, language_server_name,
language, language,
language_server_id,
)), )),
); );
} }
@ -125,8 +131,16 @@ impl ExtensionLanguageServerProxy for LanguageServerRegistryProxy {
language_server_name: LanguageServerName, language_server_name: LanguageServerName,
status: BinaryStatus, status: BinaryStatus,
) { ) {
// self.language_registry if let Some(id) = self
// .update_lsp_binary_status(language_server_name, status); .language_server_ids
.read()
.unwrap()
.get(&language_server_name)
&& let Some(&id) = id.get()
{
self.language_registry
.update_lsp_binary_status(id, language_server_name, status);
}
} }
} }
@ -134,6 +148,7 @@ struct ExtensionLspAdapter {
extension: Arc<dyn Extension>, extension: Arc<dyn Extension>,
language_server_name: LanguageServerName, language_server_name: LanguageServerName,
language_name: LanguageName, language_name: LanguageName,
language_server_id: Arc<OnceLock<LanguageServerId>>,
} }
impl ExtensionLspAdapter { impl ExtensionLspAdapter {
@ -141,11 +156,13 @@ impl ExtensionLspAdapter {
extension: Arc<dyn Extension>, extension: Arc<dyn Extension>,
language_server_name: LanguageServerName, language_server_name: LanguageServerName,
language_name: LanguageName, language_name: LanguageName,
language_server_id: Arc<OnceLock<LanguageServerId>>,
) -> Self { ) -> Self {
Self { Self {
extension, extension,
language_server_name, language_server_name,
language_name, language_name,
language_server_id,
} }
} }
} }
@ -162,7 +179,7 @@ impl LspAdapter for ExtensionLspAdapter {
_: Option<Toolchain>, _: Option<Toolchain>,
_: LanguageServerBinaryOptions, _: LanguageServerBinaryOptions,
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>, _: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
_: LanguageServerId, language_server_id: LanguageServerId,
_: &'a mut AsyncApp, _: &'a mut AsyncApp,
) -> Pin<Box<dyn 'a + Future<Output = Result<LanguageServerBinary>>>> { ) -> Pin<Box<dyn 'a + Future<Output = Result<LanguageServerBinary>>>> {
async move { async move {
@ -192,6 +209,10 @@ impl LspAdapter for ExtensionLspAdapter {
.await .await
.context("failed to set file permissions")?; .context("failed to set file permissions")?;
} }
self.language_server_id
.set(language_server_id)
.ok()
.context("failed to set language server id")?;
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path, path,

View file

@ -1,12 +1,14 @@
mod extension_lsp_adapter; mod extension_lsp_adapter;
use std::path::PathBuf; use std::sync::{Arc, OnceLock};
use std::sync::Arc; use std::{path::PathBuf, sync::RwLock};
use anyhow::Result; use anyhow::Result;
use collections::FxHashMap;
use extension::{ExtensionGrammarProxy, ExtensionHostProxy, ExtensionLanguageProxy}; use extension::{ExtensionGrammarProxy, ExtensionHostProxy, ExtensionLanguageProxy};
use gpui::{App, Entity}; use gpui::{App, Entity};
use language::{LanguageMatcher, LanguageName, LanguageRegistry, LoadedLanguage}; use language::{LanguageMatcher, LanguageName, LanguageRegistry, LoadedLanguage};
use lsp::{LanguageServerId, LanguageServerName};
use project::LspStore; use project::LspStore;
#[derive(Clone)] #[derive(Clone)]
@ -23,6 +25,7 @@ pub fn init(
) { ) {
let language_server_registry_proxy = LanguageServerRegistryProxy { let language_server_registry_proxy = LanguageServerRegistryProxy {
language_registry, language_registry,
language_server_ids: Default::default(),
lsp_access, lsp_access,
}; };
extension_host_proxy.register_grammar_proxy(language_server_registry_proxy.clone()); extension_host_proxy.register_grammar_proxy(language_server_registry_proxy.clone());
@ -33,6 +36,9 @@ pub fn init(
#[derive(Clone)] #[derive(Clone)]
struct LanguageServerRegistryProxy { struct LanguageServerRegistryProxy {
language_registry: Arc<LanguageRegistry>, language_registry: Arc<LanguageRegistry>,
// extensions can only spawn one language server currently
language_server_ids:
Arc<RwLock<FxHashMap<LanguageServerName, Arc<OnceLock<LanguageServerId>>>>>,
lsp_access: LspAccess, lsp_access: LspAccess,
} }