Use language server ids for lsp tool
This commit is contained in:
parent
70575d1115
commit
4292d883b0
9 changed files with 186 additions and 138 deletions
|
@ -56,6 +56,7 @@ pub struct ActivityIndicator {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ServerStatus {
|
struct ServerStatus {
|
||||||
name: LanguageServerName,
|
name: LanguageServerName,
|
||||||
|
id: LanguageServerId,
|
||||||
status: LanguageServerStatusUpdate,
|
status: LanguageServerStatusUpdate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,11 +87,12 @@ impl ActivityIndicator {
|
||||||
let this = cx.new(|cx| {
|
let this = cx.new(|cx| {
|
||||||
let mut status_events = languages.language_server_binary_statuses();
|
let mut status_events = languages.language_server_binary_statuses();
|
||||||
cx.spawn(async move |this, cx| {
|
cx.spawn(async move |this, cx| {
|
||||||
while let Some((name, binary_status)) = status_events.next().await {
|
while let Some((id, name, binary_status)) = status_events.next().await {
|
||||||
this.update(cx, |this: &mut ActivityIndicator, cx| {
|
this.update(cx, |this: &mut ActivityIndicator, cx| {
|
||||||
this.statuses.retain(|s| s.name != name);
|
this.statuses.retain(|s| s.id != id);
|
||||||
this.statuses.push(ServerStatus {
|
this.statuses.push(ServerStatus {
|
||||||
name,
|
name,
|
||||||
|
id,
|
||||||
status: LanguageServerStatusUpdate::Binary(binary_status),
|
status: LanguageServerStatusUpdate::Binary(binary_status),
|
||||||
});
|
});
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -117,7 +119,13 @@ impl ActivityIndicator {
|
||||||
cx.subscribe(
|
cx.subscribe(
|
||||||
&project.read(cx).lsp_store(),
|
&project.read(cx).lsp_store(),
|
||||||
|activity_indicator, _, event, cx| {
|
|activity_indicator, _, event, cx| {
|
||||||
if let LspStoreEvent::LanguageServerUpdate { name, message, .. } = event {
|
if let LspStoreEvent::LanguageServerUpdate {
|
||||||
|
language_server_id,
|
||||||
|
name,
|
||||||
|
message,
|
||||||
|
..
|
||||||
|
} = event
|
||||||
|
{
|
||||||
if let proto::update_language_server::Variant::StatusUpdate(status_update) =
|
if let proto::update_language_server::Variant::StatusUpdate(status_update) =
|
||||||
message
|
message
|
||||||
{
|
{
|
||||||
|
@ -180,9 +188,11 @@ impl ActivityIndicator {
|
||||||
};
|
};
|
||||||
|
|
||||||
activity_indicator.statuses.retain(|s| s.name != name);
|
activity_indicator.statuses.retain(|s| s.name != name);
|
||||||
activity_indicator
|
activity_indicator.statuses.push(ServerStatus {
|
||||||
.statuses
|
name,
|
||||||
.push(ServerStatus { name, status });
|
id: *language_server_id,
|
||||||
|
status,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
cx.notify()
|
cx.notify()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1361,11 +1361,12 @@ impl ExtensionStore {
|
||||||
for (manifest, wasm_extension) in &wasm_extensions {
|
for (manifest, wasm_extension) in &wasm_extensions {
|
||||||
let extension = Arc::new(wasm_extension.clone());
|
let extension = Arc::new(wasm_extension.clone());
|
||||||
|
|
||||||
for (language_server_id, language_server_config) in &manifest.language_servers {
|
for (language_server_name, language_server_config) in &manifest.language_servers
|
||||||
|
{
|
||||||
for language in language_server_config.languages() {
|
for language in language_server_config.languages() {
|
||||||
this.proxy.register_language_server(
|
this.proxy.register_language_server(
|
||||||
extension.clone(),
|
extension.clone(),
|
||||||
language_server_id.clone(),
|
language_server_name.clone(),
|
||||||
language.clone(),
|
language.clone(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use gpui::{AppContext as _, SemanticVersion, TestAppContext};
|
||||||
use http_client::{FakeHttpClient, Response};
|
use http_client::{FakeHttpClient, Response};
|
||||||
use language::{BinaryStatus, LanguageMatcher, LanguageName, LanguageRegistry};
|
use language::{BinaryStatus, LanguageMatcher, LanguageName, LanguageRegistry};
|
||||||
use language_extension::LspAccess;
|
use language_extension::LspAccess;
|
||||||
use lsp::LanguageServerName;
|
use lsp::{LanguageServerId, LanguageServerName};
|
||||||
use node_runtime::NodeRuntime;
|
use node_runtime::NodeRuntime;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use project::{DEFAULT_COMPLETION_CONTEXT, Project};
|
use project::{DEFAULT_COMPLETION_CONTEXT, Project};
|
||||||
|
@ -737,18 +737,25 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) {
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
(
|
(
|
||||||
|
LanguageServerId(0),
|
||||||
LanguageServerName::new_static("gleam"),
|
LanguageServerName::new_static("gleam"),
|
||||||
BinaryStatus::Starting
|
BinaryStatus::Starting
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
LanguageServerId(0),
|
||||||
LanguageServerName::new_static("gleam"),
|
LanguageServerName::new_static("gleam"),
|
||||||
BinaryStatus::CheckingForUpdate
|
BinaryStatus::CheckingForUpdate
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
LanguageServerId(0),
|
||||||
LanguageServerName::new_static("gleam"),
|
LanguageServerName::new_static("gleam"),
|
||||||
BinaryStatus::Downloading
|
BinaryStatus::Downloading
|
||||||
),
|
),
|
||||||
(LanguageServerName::new_static("gleam"), BinaryStatus::None)
|
(
|
||||||
|
LanguageServerId(0),
|
||||||
|
LanguageServerName::new_static("gleam"),
|
||||||
|
BinaryStatus::None
|
||||||
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -177,21 +177,21 @@ impl HeadlessExtensionStore {
|
||||||
let wasm_extension: Arc<dyn Extension> =
|
let wasm_extension: Arc<dyn Extension> =
|
||||||
Arc::new(WasmExtension::load(&extension_dir, &manifest, wasm_host.clone(), cx).await?);
|
Arc::new(WasmExtension::load(&extension_dir, &manifest, wasm_host.clone(), cx).await?);
|
||||||
|
|
||||||
for (language_server_id, language_server_config) in &manifest.language_servers {
|
for (language_server_name, language_server_config) in &manifest.language_servers {
|
||||||
for language in language_server_config.languages() {
|
for language in language_server_config.languages() {
|
||||||
this.update(cx, |this, _cx| {
|
this.update(cx, |this, _cx| {
|
||||||
this.loaded_language_servers
|
this.loaded_language_servers
|
||||||
.entry(manifest.id.clone())
|
.entry(manifest.id.clone())
|
||||||
.or_default()
|
.or_default()
|
||||||
.push((language_server_id.clone(), language.clone()));
|
.push((language_server_name.clone(), language.clone()));
|
||||||
this.proxy.register_language_server(
|
this.proxy.register_language_server(
|
||||||
wasm_extension.clone(),
|
wasm_extension.clone(),
|
||||||
language_server_id.clone(),
|
language_server_name.clone(),
|
||||||
language.clone(),
|
language.clone(),
|
||||||
);
|
);
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
log::info!("Loaded language server: {}", language_server_id);
|
log::info!("Loaded language server: {}", language_server_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (debug_adapter, meta) in &manifest.debug_adapters {
|
for (debug_adapter, meta) in &manifest.debug_adapters {
|
||||||
|
|
|
@ -214,12 +214,20 @@ impl CachedLspAdapter {
|
||||||
delegate: Arc<dyn LspAdapterDelegate>,
|
delegate: Arc<dyn LspAdapterDelegate>,
|
||||||
toolchains: Option<Toolchain>,
|
toolchains: Option<Toolchain>,
|
||||||
binary_options: LanguageServerBinaryOptions,
|
binary_options: LanguageServerBinaryOptions,
|
||||||
|
server_id: LanguageServerId,
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Result<LanguageServerBinary> {
|
) -> Result<LanguageServerBinary> {
|
||||||
let cached_binary = self.cached_binary.lock().await;
|
let cached_binary = self.cached_binary.lock().await;
|
||||||
self.adapter
|
self.adapter
|
||||||
.clone()
|
.clone()
|
||||||
.get_language_server_command(delegate, toolchains, binary_options, cached_binary, cx)
|
.get_language_server_command(
|
||||||
|
delegate,
|
||||||
|
toolchains,
|
||||||
|
binary_options,
|
||||||
|
cached_binary,
|
||||||
|
server_id,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +299,12 @@ pub trait LspAdapterDelegate: Send + Sync {
|
||||||
fn http_client(&self) -> Arc<dyn HttpClient>;
|
fn http_client(&self) -> Arc<dyn HttpClient>;
|
||||||
fn worktree_id(&self) -> WorktreeId;
|
fn worktree_id(&self) -> WorktreeId;
|
||||||
fn worktree_root_path(&self) -> &Path;
|
fn worktree_root_path(&self) -> &Path;
|
||||||
fn update_status(&self, language: LanguageServerName, status: BinaryStatus);
|
fn update_status(
|
||||||
|
&self,
|
||||||
|
language: LanguageServerId,
|
||||||
|
server_name: LanguageServerName,
|
||||||
|
status: BinaryStatus,
|
||||||
|
);
|
||||||
fn registered_lsp_adapters(&self) -> Vec<Arc<dyn LspAdapter>>;
|
fn registered_lsp_adapters(&self) -> Vec<Arc<dyn LspAdapter>>;
|
||||||
async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
|
async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
|
||||||
|
|
||||||
|
@ -315,6 +328,7 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||||
toolchains: Option<Toolchain>,
|
toolchains: Option<Toolchain>,
|
||||||
binary_options: LanguageServerBinaryOptions,
|
binary_options: LanguageServerBinaryOptions,
|
||||||
mut cached_binary: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
mut cached_binary: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
||||||
|
server_id: LanguageServerId,
|
||||||
cx: &'a mut AsyncApp,
|
cx: &'a mut AsyncApp,
|
||||||
) -> Pin<Box<dyn 'a + Future<Output = Result<LanguageServerBinary>>>> {
|
) -> Pin<Box<dyn 'a + Future<Output = Result<LanguageServerBinary>>>> {
|
||||||
async move {
|
async move {
|
||||||
|
@ -330,7 +344,10 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||||
// because we don't want to download and overwrite our global one
|
// because we don't want to download and overwrite our global one
|
||||||
// for each worktree we might have open.
|
// for each worktree we might have open.
|
||||||
if binary_options.allow_path_lookup
|
if binary_options.allow_path_lookup
|
||||||
&& let Some(binary) = self.check_if_user_installed(delegate.as_ref(), toolchains, cx).await {
|
&& let Some(binary) = self
|
||||||
|
.check_if_user_installed(delegate.as_ref(), toolchains, cx)
|
||||||
|
.await
|
||||||
|
{
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"found user-installed language server for {}. path: {:?}, arguments: {:?}",
|
"found user-installed language server for {}. path: {:?}, arguments: {:?}",
|
||||||
self.name().0,
|
self.name().0,
|
||||||
|
@ -340,17 +357,28 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||||
return Ok(binary);
|
return Ok(binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
anyhow::ensure!(binary_options.allow_binary_download, "downloading language servers disabled");
|
anyhow::ensure!(
|
||||||
|
binary_options.allow_binary_download,
|
||||||
|
"downloading language servers disabled"
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(cached_binary) = cached_binary.as_ref() {
|
if let Some(cached_binary) = cached_binary.as_ref() {
|
||||||
return Ok(cached_binary.clone());
|
return Ok(cached_binary.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(container_dir) = delegate.language_server_download_dir(&self.name()).await else {
|
let Some(container_dir) = delegate.language_server_download_dir(&self.name()).await
|
||||||
|
else {
|
||||||
anyhow::bail!("no language server download dir defined")
|
anyhow::bail!("no language server download dir defined")
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut binary = try_fetch_server_binary(self.as_ref(), &delegate, container_dir.to_path_buf(), cx).await;
|
let mut binary = try_fetch_server_binary(
|
||||||
|
self.as_ref(),
|
||||||
|
&delegate,
|
||||||
|
container_dir.to_path_buf(),
|
||||||
|
server_id,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
if let Err(error) = binary.as_ref() {
|
if let Err(error) = binary.as_ref() {
|
||||||
if let Some(prev_downloaded_binary) = self
|
if let Some(prev_downloaded_binary) = self
|
||||||
|
@ -358,7 +386,8 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
log::info!(
|
log::info!(
|
||||||
"failed to fetch newest version of language server {:?}. error: {:?}, falling back to using {:?}",
|
"failed to fetch newest version of language server {:?}. \
|
||||||
|
error: {:?}, falling back to using {:?}",
|
||||||
self.name(),
|
self.name(),
|
||||||
error,
|
error,
|
||||||
prev_downloaded_binary.path
|
prev_downloaded_binary.path
|
||||||
|
@ -366,6 +395,7 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||||
binary = Ok(prev_downloaded_binary);
|
binary = Ok(prev_downloaded_binary);
|
||||||
} else {
|
} else {
|
||||||
delegate.update_status(
|
delegate.update_status(
|
||||||
|
server_id,
|
||||||
self.name(),
|
self.name(),
|
||||||
BinaryStatus::Failed {
|
BinaryStatus::Failed {
|
||||||
error: format!("{error:?}"),
|
error: format!("{error:?}"),
|
||||||
|
@ -594,6 +624,7 @@ async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>
|
||||||
adapter: &L,
|
adapter: &L,
|
||||||
delegate: &Arc<dyn LspAdapterDelegate>,
|
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||||
container_dir: PathBuf,
|
container_dir: PathBuf,
|
||||||
|
server_id: LanguageServerId,
|
||||||
cx: &mut AsyncApp,
|
cx: &mut AsyncApp,
|
||||||
) -> Result<LanguageServerBinary> {
|
) -> Result<LanguageServerBinary> {
|
||||||
if let Some(task) = adapter.will_fetch_server(delegate, cx) {
|
if let Some(task) = adapter.will_fetch_server(delegate, cx) {
|
||||||
|
@ -602,7 +633,7 @@ async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>
|
||||||
|
|
||||||
let name = adapter.name();
|
let name = adapter.name();
|
||||||
log::debug!("fetching latest version of language server {:?}", name.0);
|
log::debug!("fetching latest version of language server {:?}", name.0);
|
||||||
delegate.update_status(name.clone(), BinaryStatus::CheckingForUpdate);
|
delegate.update_status(server_id, adapter.name(), BinaryStatus::CheckingForUpdate);
|
||||||
|
|
||||||
let latest_version = adapter
|
let latest_version = adapter
|
||||||
.fetch_latest_server_version(delegate.as_ref())
|
.fetch_latest_server_version(delegate.as_ref())
|
||||||
|
@ -613,16 +644,16 @@ async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
log::debug!("language server {:?} is already installed", name.0);
|
log::debug!("language server {:?} is already installed", name.0);
|
||||||
delegate.update_status(name.clone(), BinaryStatus::None);
|
delegate.update_status(server_id, adapter.name(), BinaryStatus::None);
|
||||||
Ok(binary)
|
Ok(binary)
|
||||||
} else {
|
} else {
|
||||||
log::info!("downloading language server {:?}", name.0);
|
log::info!("downloading language server {:?}", name.0);
|
||||||
delegate.update_status(adapter.name(), BinaryStatus::Downloading);
|
delegate.update_status(server_id, adapter.name(), BinaryStatus::Downloading);
|
||||||
let binary = adapter
|
let binary = adapter
|
||||||
.fetch_server_binary(latest_version, container_dir, delegate.as_ref())
|
.fetch_server_binary(latest_version, container_dir, delegate.as_ref())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
delegate.update_status(name.clone(), BinaryStatus::None);
|
delegate.update_status(server_id, adapter.name(), BinaryStatus::None);
|
||||||
binary
|
binary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2197,6 +2228,7 @@ impl LspAdapter for FakeLspAdapter {
|
||||||
_: Option<Toolchain>,
|
_: Option<Toolchain>,
|
||||||
_: LanguageServerBinaryOptions,
|
_: LanguageServerBinaryOptions,
|
||||||
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
||||||
|
_: 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 { Ok(self.language_server_binary.clone()) }.boxed_local()
|
async move { Ok(self.language_server_binary.clone()) }.boxed_local()
|
||||||
|
|
|
@ -252,7 +252,9 @@ pub struct LanguageQueries {
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
struct ServerStatusSender {
|
struct ServerStatusSender {
|
||||||
txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(LanguageServerName, BinaryStatus)>>>>,
|
txs: Arc<
|
||||||
|
Mutex<Vec<mpsc::UnboundedSender<(LanguageServerId, LanguageServerName, BinaryStatus)>>>,
|
||||||
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LoadedLanguage {
|
pub struct LoadedLanguage {
|
||||||
|
@ -1077,8 +1079,13 @@ impl LanguageRegistry {
|
||||||
self.state.read().all_lsp_adapters.get(name).cloned()
|
self.state.read().all_lsp_adapters.get(name).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_lsp_binary_status(&self, server_name: LanguageServerName, status: BinaryStatus) {
|
pub fn update_lsp_binary_status(
|
||||||
self.lsp_binary_status_tx.send(server_name, status);
|
&self,
|
||||||
|
server_id: LanguageServerId,
|
||||||
|
name: LanguageServerName,
|
||||||
|
status: BinaryStatus,
|
||||||
|
) {
|
||||||
|
self.lsp_binary_status_tx.send(server_id, name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_language_server_id(&self) -> LanguageServerId {
|
pub fn next_language_server_id(&self) -> LanguageServerId {
|
||||||
|
@ -1133,7 +1140,7 @@ impl LanguageRegistry {
|
||||||
|
|
||||||
pub fn language_server_binary_statuses(
|
pub fn language_server_binary_statuses(
|
||||||
&self,
|
&self,
|
||||||
) -> mpsc::UnboundedReceiver<(LanguageServerName, BinaryStatus)> {
|
) -> mpsc::UnboundedReceiver<(LanguageServerId, LanguageServerName, BinaryStatus)> {
|
||||||
self.lsp_binary_status_tx.subscribe()
|
self.lsp_binary_status_tx.subscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1247,14 +1254,19 @@ impl LanguageRegistryState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerStatusSender {
|
impl ServerStatusSender {
|
||||||
fn subscribe(&self) -> mpsc::UnboundedReceiver<(LanguageServerName, BinaryStatus)> {
|
fn subscribe(
|
||||||
|
&self,
|
||||||
|
) -> mpsc::UnboundedReceiver<(LanguageServerId, LanguageServerName, BinaryStatus)> {
|
||||||
let (tx, rx) = mpsc::unbounded();
|
let (tx, rx) = mpsc::unbounded();
|
||||||
self.txs.lock().push(tx);
|
self.txs.lock().push(tx);
|
||||||
rx
|
rx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send(&self, name: LanguageServerName, status: BinaryStatus) {
|
fn send(&self, id: LanguageServerId, name: LanguageServerName, status: BinaryStatus) {
|
||||||
let mut txs = self.txs.lock();
|
let mut txs = self.txs.lock();
|
||||||
txs.retain(|tx| tx.unbounded_send((name.clone(), status.clone())).is_ok());
|
txs.retain(|tx| {
|
||||||
|
tx.unbounded_send((id, name.clone(), status.clone()))
|
||||||
|
.is_ok()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@ use language::{
|
||||||
Toolchain,
|
Toolchain,
|
||||||
};
|
};
|
||||||
use lsp::{
|
use lsp::{
|
||||||
CodeActionKind, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerName,
|
CodeActionKind, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerId,
|
||||||
LanguageServerSelector,
|
LanguageServerName, LanguageServerSelector,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -58,14 +58,14 @@ impl ExtensionLanguageServerProxy for LanguageServerRegistryProxy {
|
||||||
fn register_language_server(
|
fn register_language_server(
|
||||||
&self,
|
&self,
|
||||||
extension: Arc<dyn Extension>,
|
extension: Arc<dyn Extension>,
|
||||||
language_server_id: LanguageServerName,
|
language_server_name: LanguageServerName,
|
||||||
language: LanguageName,
|
language: LanguageName,
|
||||||
) {
|
) {
|
||||||
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_id,
|
language_server_name,
|
||||||
language,
|
language,
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
@ -122,29 +122,29 @@ impl ExtensionLanguageServerProxy for LanguageServerRegistryProxy {
|
||||||
|
|
||||||
fn update_language_server_status(
|
fn update_language_server_status(
|
||||||
&self,
|
&self,
|
||||||
language_server_id: LanguageServerName,
|
language_server_name: LanguageServerName,
|
||||||
status: BinaryStatus,
|
status: BinaryStatus,
|
||||||
) {
|
) {
|
||||||
self.language_registry
|
// self.language_registry
|
||||||
.update_lsp_binary_status(language_server_id, status);
|
// .update_lsp_binary_status(language_server_name, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExtensionLspAdapter {
|
struct ExtensionLspAdapter {
|
||||||
extension: Arc<dyn Extension>,
|
extension: Arc<dyn Extension>,
|
||||||
language_server_id: LanguageServerName,
|
language_server_name: LanguageServerName,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtensionLspAdapter {
|
impl ExtensionLspAdapter {
|
||||||
fn new(
|
fn new(
|
||||||
extension: Arc<dyn Extension>,
|
extension: Arc<dyn Extension>,
|
||||||
language_server_id: LanguageServerName,
|
language_server_name: LanguageServerName,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
extension,
|
extension,
|
||||||
language_server_id,
|
language_server_name,
|
||||||
language_name,
|
language_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ impl ExtensionLspAdapter {
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
impl LspAdapter for ExtensionLspAdapter {
|
impl LspAdapter for ExtensionLspAdapter {
|
||||||
fn name(&self) -> LanguageServerName {
|
fn name(&self) -> LanguageServerName {
|
||||||
self.language_server_id.clone()
|
self.language_server_name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_language_server_command<'a>(
|
fn get_language_server_command<'a>(
|
||||||
|
@ -162,6 +162,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
_: Option<Toolchain>,
|
_: Option<Toolchain>,
|
||||||
_: LanguageServerBinaryOptions,
|
_: LanguageServerBinaryOptions,
|
||||||
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
|
||||||
|
_: 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 {
|
||||||
|
@ -169,7 +170,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
let command = self
|
let command = self
|
||||||
.extension
|
.extension
|
||||||
.language_server_command(
|
.language_server_command(
|
||||||
self.language_server_id.clone(),
|
self.language_server_name.clone(),
|
||||||
self.language_name.clone(),
|
self.language_name.clone(),
|
||||||
delegate,
|
delegate,
|
||||||
)
|
)
|
||||||
|
@ -230,7 +231,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
.extension
|
.extension
|
||||||
.manifest()
|
.manifest()
|
||||||
.language_servers
|
.language_servers
|
||||||
.get(&self.language_server_id)
|
.get(&self.language_server_name)
|
||||||
.and_then(|server| server.code_action_kinds.clone());
|
.and_then(|server| server.code_action_kinds.clone());
|
||||||
|
|
||||||
code_action_kinds.or(Some(vec![
|
code_action_kinds.or(Some(vec![
|
||||||
|
@ -256,7 +257,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
self.extension
|
self.extension
|
||||||
.manifest()
|
.manifest()
|
||||||
.language_servers
|
.language_servers
|
||||||
.get(&self.language_server_id)
|
.get(&self.language_server_name)
|
||||||
.map(|server| server.language_ids.clone())
|
.map(|server| server.language_ids.clone())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
@ -270,7 +271,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
let json_options = self
|
let json_options = self
|
||||||
.extension
|
.extension
|
||||||
.language_server_initialization_options(
|
.language_server_initialization_options(
|
||||||
self.language_server_id.clone(),
|
self.language_server_name.clone(),
|
||||||
self.language_name.clone(),
|
self.language_name.clone(),
|
||||||
delegate,
|
delegate,
|
||||||
)
|
)
|
||||||
|
@ -294,7 +295,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
let delegate = Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _;
|
let delegate = Arc::new(WorktreeDelegateAdapter(delegate.clone())) as _;
|
||||||
let json_options: Option<String> = self
|
let json_options: Option<String> = self
|
||||||
.extension
|
.extension
|
||||||
.language_server_workspace_configuration(self.language_server_id.clone(), delegate)
|
.language_server_workspace_configuration(self.language_server_name.clone(), delegate)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(if let Some(json_options) = json_options {
|
Ok(if let Some(json_options) = json_options {
|
||||||
serde_json::from_str(&json_options).with_context(|| {
|
serde_json::from_str(&json_options).with_context(|| {
|
||||||
|
@ -315,7 +316,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
let json_options: Option<String> = self
|
let json_options: Option<String> = self
|
||||||
.extension
|
.extension
|
||||||
.language_server_additional_initialization_options(
|
.language_server_additional_initialization_options(
|
||||||
self.language_server_id.clone(),
|
self.language_server_name.clone(),
|
||||||
target_language_server_id.clone(),
|
target_language_server_id.clone(),
|
||||||
delegate,
|
delegate,
|
||||||
)
|
)
|
||||||
|
@ -343,7 +344,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
let json_options: Option<String> = self
|
let json_options: Option<String> = self
|
||||||
.extension
|
.extension
|
||||||
.language_server_additional_workspace_configuration(
|
.language_server_additional_workspace_configuration(
|
||||||
self.language_server_id.clone(),
|
self.language_server_name.clone(),
|
||||||
target_language_server_id.clone(),
|
target_language_server_id.clone(),
|
||||||
delegate,
|
delegate,
|
||||||
)
|
)
|
||||||
|
@ -370,7 +371,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
|
|
||||||
let labels = self
|
let labels = self
|
||||||
.extension
|
.extension
|
||||||
.labels_for_completions(self.language_server_id.clone(), completions)
|
.labels_for_completions(self.language_server_name.clone(), completions)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(labels_from_extension(labels, language))
|
Ok(labels_from_extension(labels, language))
|
||||||
|
@ -392,7 +393,7 @@ impl LspAdapter for ExtensionLspAdapter {
|
||||||
|
|
||||||
let labels = self
|
let labels = self
|
||||||
.extension
|
.extension
|
||||||
.labels_for_symbols(self.language_server_id.clone(), symbols)
|
.labels_for_symbols(self.language_server_name.clone(), symbols)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(labels_from_extension(labels, language))
|
Ok(labels_from_extension(labels, language))
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl std::fmt::Debug for ActiveEditor {
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
struct LanguageServers {
|
struct LanguageServers {
|
||||||
health_statuses: HashMap<LanguageServerId, LanguageServerHealthStatus>,
|
health_statuses: HashMap<LanguageServerId, LanguageServerHealthStatus>,
|
||||||
binary_statuses: HashMap<LanguageServerName, LanguageServerBinaryStatus>,
|
binary_statuses: HashMap<LanguageServerId, LanguageServerBinaryStatus>,
|
||||||
servers_per_buffer_abs_path: HashMap<PathBuf, ServersForPath>,
|
servers_per_buffer_abs_path: HashMap<PathBuf, ServersForPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ struct LanguageServerHealthStatus {
|
||||||
struct LanguageServerBinaryStatus {
|
struct LanguageServerBinaryStatus {
|
||||||
status: BinaryStatus,
|
status: BinaryStatus,
|
||||||
message: Option<SharedString>,
|
message: Option<SharedString>,
|
||||||
|
name: LanguageServerName,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -370,17 +371,19 @@ impl LanguageServers {
|
||||||
binary_status: BinaryStatus,
|
binary_status: BinaryStatus,
|
||||||
message: Option<&str>,
|
message: Option<&str>,
|
||||||
name: LanguageServerName,
|
name: LanguageServerName,
|
||||||
|
id: LanguageServerId,
|
||||||
) {
|
) {
|
||||||
let binary_status_message = message.map(SharedString::new);
|
let binary_status_message = message.map(SharedString::new);
|
||||||
if matches!(
|
if matches!(
|
||||||
binary_status,
|
binary_status,
|
||||||
BinaryStatus::Stopped | BinaryStatus::Failed { .. }
|
BinaryStatus::Stopped | BinaryStatus::Failed { .. }
|
||||||
) {
|
) {
|
||||||
self.health_statuses.retain(|_, server| server.name != name);
|
self.health_statuses.remove(&id);
|
||||||
}
|
}
|
||||||
self.binary_statuses.insert(
|
self.binary_statuses.insert(
|
||||||
name,
|
id,
|
||||||
LanguageServerBinaryStatus {
|
LanguageServerBinaryStatus {
|
||||||
|
name,
|
||||||
status: binary_status,
|
status: binary_status,
|
||||||
message: binary_status_message,
|
message: binary_status_message,
|
||||||
},
|
},
|
||||||
|
@ -583,18 +586,16 @@ impl LspTool {
|
||||||
proto::ServerBinaryStatus::Starting => BinaryStatus::Starting,
|
proto::ServerBinaryStatus::Starting => BinaryStatus::Starting,
|
||||||
proto::ServerBinaryStatus::Stopping => BinaryStatus::Stopping,
|
proto::ServerBinaryStatus::Stopping => BinaryStatus::Stopping,
|
||||||
proto::ServerBinaryStatus::Stopped => BinaryStatus::Stopped,
|
proto::ServerBinaryStatus::Stopped => BinaryStatus::Stopped,
|
||||||
proto::ServerBinaryStatus::Failed => {
|
proto::ServerBinaryStatus::Failed => BinaryStatus::Failed {
|
||||||
let Some(error) = status_update.message.clone() else {
|
error: status_update.message.clone().unwrap_or_default(),
|
||||||
return;
|
},
|
||||||
};
|
|
||||||
BinaryStatus::Failed { error }
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.server_state.update(cx, |state, _| {
|
self.server_state.update(cx, |state, _| {
|
||||||
state.language_servers.update_binary_status(
|
state.language_servers.update_binary_status(
|
||||||
binary_status,
|
binary_status,
|
||||||
status_update.message.as_deref(),
|
status_update.message.as_deref(),
|
||||||
name.clone(),
|
name.clone(),
|
||||||
|
*language_server_id,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
updated = true;
|
updated = true;
|
||||||
|
@ -684,27 +685,16 @@ impl LspTool {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
let mut server_ids_to_worktrees =
|
let mut server_ids_to_worktrees =
|
||||||
HashMap::<LanguageServerId, Entity<Worktree>>::default();
|
HashMap::<LanguageServerId, Entity<Worktree>>::default();
|
||||||
let mut server_names_to_worktrees = HashMap::<
|
|
||||||
LanguageServerName,
|
|
||||||
HashSet<(Entity<Worktree>, LanguageServerId)>,
|
|
||||||
>::default();
|
|
||||||
for servers_for_path in state.language_servers.servers_per_buffer_abs_path.values() {
|
for servers_for_path in state.language_servers.servers_per_buffer_abs_path.values() {
|
||||||
if let Some(worktree) = servers_for_path
|
if let Some(worktree) = servers_for_path
|
||||||
.worktree
|
.worktree
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|worktree| worktree.upgrade())
|
.and_then(|worktree| worktree.upgrade())
|
||||||
{
|
{
|
||||||
for (server_id, server_name) in &servers_for_path.servers {
|
for (server_id, _) in &servers_for_path.servers {
|
||||||
server_ids_to_worktrees.insert(*server_id, worktree.clone());
|
server_ids_to_worktrees.insert(*server_id, worktree.clone());
|
||||||
if let Some(server_name) = server_name {
|
|
||||||
server_names_to_worktrees
|
|
||||||
.entry(server_name.clone())
|
|
||||||
.or_default()
|
|
||||||
.insert((worktree.clone(), *server_id));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -714,19 +704,12 @@ impl LspTool {
|
||||||
let mut servers_with_health_checks = HashSet::default();
|
let mut servers_with_health_checks = HashSet::default();
|
||||||
|
|
||||||
for (server_id, health) in &state.language_servers.health_statuses {
|
for (server_id, health) in &state.language_servers.health_statuses {
|
||||||
let worktree = server_ids_to_worktrees.get(server_id).or_else(|| {
|
let worktree = server_ids_to_worktrees.get(server_id);
|
||||||
let worktrees = server_names_to_worktrees.get(&health.name)?;
|
servers_with_health_checks.insert(*server_id);
|
||||||
worktrees
|
|
||||||
.iter()
|
|
||||||
.find(|(worktree, _)| active_worktrees.contains(worktree))
|
|
||||||
.or_else(|| worktrees.iter().next())
|
|
||||||
.map(|(worktree, _)| worktree)
|
|
||||||
});
|
|
||||||
servers_with_health_checks.insert(&health.name);
|
|
||||||
let worktree_name =
|
let worktree_name =
|
||||||
worktree.map(|worktree| SharedString::new(worktree.read(cx).root_name()));
|
worktree.map(|worktree| SharedString::new(worktree.read(cx).root_name()));
|
||||||
|
|
||||||
let binary_status = state.language_servers.binary_statuses.get(&health.name);
|
let binary_status = state.language_servers.binary_statuses.get(server_id);
|
||||||
let server_data = ServerData::WithHealthCheck {
|
let server_data = ServerData::WithHealthCheck {
|
||||||
server_id: *server_id,
|
server_id: *server_id,
|
||||||
health,
|
health,
|
||||||
|
@ -743,11 +726,11 @@ impl LspTool {
|
||||||
|
|
||||||
let mut can_stop_all = !state.language_servers.health_statuses.is_empty();
|
let mut can_stop_all = !state.language_servers.health_statuses.is_empty();
|
||||||
let mut can_restart_all = state.language_servers.health_statuses.is_empty();
|
let mut can_restart_all = state.language_servers.health_statuses.is_empty();
|
||||||
for (server_name, binary_status) in state
|
for (server_id, binary_status) in state
|
||||||
.language_servers
|
.language_servers
|
||||||
.binary_statuses
|
.binary_statuses
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(name, _)| !servers_with_health_checks.contains(name))
|
.filter(|&(id, _)| !servers_with_health_checks.contains(id))
|
||||||
{
|
{
|
||||||
match binary_status.status {
|
match binary_status.status {
|
||||||
BinaryStatus::None => {
|
BinaryStatus::None => {
|
||||||
|
@ -774,40 +757,25 @@ impl LspTool {
|
||||||
BinaryStatus::Failed { .. } => {}
|
BinaryStatus::Failed { .. } => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match server_names_to_worktrees.get(server_name) {
|
let server_name = &binary_status.name;
|
||||||
Some(worktrees_for_name) => {
|
match server_ids_to_worktrees.get(server_id) {
|
||||||
match worktrees_for_name
|
Some(worktree) if active_worktrees.contains(worktree) => {
|
||||||
.iter()
|
let worktree_name = SharedString::new(worktree.read(cx).root_name());
|
||||||
.find(|(worktree, _)| active_worktrees.contains(worktree))
|
servers_per_worktree.entry(worktree_name).or_default().push(
|
||||||
.or_else(|| worktrees_for_name.iter().next())
|
ServerData::WithBinaryStatus {
|
||||||
{
|
|
||||||
Some((worktree, server_id)) => {
|
|
||||||
let worktree_name =
|
|
||||||
SharedString::new(worktree.read(cx).root_name());
|
|
||||||
servers_per_worktree
|
|
||||||
.entry(worktree_name.clone())
|
|
||||||
.or_default()
|
|
||||||
.push(ServerData::WithBinaryStatus {
|
|
||||||
server_name,
|
server_name,
|
||||||
binary_status,
|
binary_status,
|
||||||
server_id: Some(*server_id),
|
server_id: Some(*server_id),
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
None => servers_without_worktree.push(ServerData::WithBinaryStatus {
|
_ => servers_without_worktree.push(ServerData::WithBinaryStatus {
|
||||||
server_name,
|
server_name,
|
||||||
binary_status,
|
binary_status,
|
||||||
server_id: None,
|
server_id: Some(*server_id),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => servers_without_worktree.push(ServerData::WithBinaryStatus {
|
|
||||||
server_name,
|
|
||||||
binary_status,
|
|
||||||
server_id: None,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut new_lsp_items =
|
let mut new_lsp_items =
|
||||||
Vec::with_capacity(servers_per_worktree.len() + servers_without_worktree.len() + 2);
|
Vec::with_capacity(servers_per_worktree.len() + servers_without_worktree.len() + 2);
|
||||||
for (worktree_name, worktree_servers) in servers_per_worktree {
|
for (worktree_name, worktree_servers) in servers_per_worktree {
|
||||||
|
|
|
@ -308,6 +308,7 @@ impl LocalLspStore {
|
||||||
toolchain.clone(),
|
toolchain.clone(),
|
||||||
delegate.clone(),
|
delegate.clone(),
|
||||||
true,
|
true,
|
||||||
|
server_id,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
let pending_workspace_folders: Arc<Mutex<BTreeSet<Url>>> = Default::default();
|
let pending_workspace_folders: Arc<Mutex<BTreeSet<Url>>> = Default::default();
|
||||||
|
@ -351,11 +352,11 @@ impl LocalLspStore {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let server_name = adapter.name.clone();
|
||||||
let startup = {
|
let startup = {
|
||||||
let server_name = adapter.name.0.clone();
|
let server_name = server_name.clone();
|
||||||
let delegate = delegate as Arc<dyn LspAdapterDelegate>;
|
let delegate = delegate as Arc<dyn LspAdapterDelegate>;
|
||||||
let key = key.clone();
|
let key = key.clone();
|
||||||
let adapter = adapter.clone();
|
|
||||||
let lsp_store = self.weak.clone();
|
let lsp_store = self.weak.clone();
|
||||||
let pending_workspace_folders = pending_workspace_folders.clone();
|
let pending_workspace_folders = pending_workspace_folders.clone();
|
||||||
let fs = self.fs.clone();
|
let fs = self.fs.clone();
|
||||||
|
@ -460,8 +461,10 @@ impl LocalLspStore {
|
||||||
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let log = stderr_capture.lock().take().unwrap_or_default();
|
let log = stderr_capture.lock().take().unwrap_or_default();
|
||||||
|
log::error!("Failed to start language server {server_name:?}: {err:?}");
|
||||||
delegate.update_status(
|
delegate.update_status(
|
||||||
adapter.name(),
|
server_id,
|
||||||
|
server_name,
|
||||||
BinaryStatus::Failed {
|
BinaryStatus::Failed {
|
||||||
error: if log.is_empty() {
|
error: if log.is_empty() {
|
||||||
format!("{err:#}")
|
format!("{err:#}")
|
||||||
|
@ -470,7 +473,6 @@ impl LocalLspStore {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
log::error!("Failed to start language server {server_name:?}: {err:?}");
|
|
||||||
if !log.is_empty() {
|
if !log.is_empty() {
|
||||||
log::error!("server stderr: {log}");
|
log::error!("server stderr: {log}");
|
||||||
}
|
}
|
||||||
|
@ -485,7 +487,7 @@ impl LocalLspStore {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.languages
|
self.languages
|
||||||
.update_lsp_binary_status(adapter.name(), BinaryStatus::Starting);
|
.update_lsp_binary_status(server_id, server_name, BinaryStatus::Starting);
|
||||||
|
|
||||||
self.language_servers.insert(server_id, state);
|
self.language_servers.insert(server_id, state);
|
||||||
self.language_server_ids
|
self.language_server_ids
|
||||||
|
@ -504,6 +506,7 @@ impl LocalLspStore {
|
||||||
toolchain: Option<Toolchain>,
|
toolchain: Option<Toolchain>,
|
||||||
delegate: Arc<dyn LspAdapterDelegate>,
|
delegate: Arc<dyn LspAdapterDelegate>,
|
||||||
allow_binary_download: bool,
|
allow_binary_download: bool,
|
||||||
|
server_id: LanguageServerId,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Task<Result<LanguageServerBinary>> {
|
) -> Task<Result<LanguageServerBinary>> {
|
||||||
if let Some(settings) = settings.binary.as_ref()
|
if let Some(settings) = settings.binary.as_ref()
|
||||||
|
@ -539,10 +542,16 @@ impl LocalLspStore {
|
||||||
cx.spawn(async move |cx| {
|
cx.spawn(async move |cx| {
|
||||||
let binary_result = adapter
|
let binary_result = adapter
|
||||||
.clone()
|
.clone()
|
||||||
.get_language_server_command(delegate.clone(), toolchain, lsp_binary_options, cx)
|
.get_language_server_command(
|
||||||
|
delegate.clone(),
|
||||||
|
toolchain,
|
||||||
|
lsp_binary_options,
|
||||||
|
server_id,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
delegate.update_status(adapter.name.clone(), BinaryStatus::None);
|
delegate.update_status(server_id, adapter.name(), BinaryStatus::None);
|
||||||
|
|
||||||
let mut binary = binary_result?;
|
let mut binary = binary_result?;
|
||||||
let mut shell_env = delegate.shell_env().await;
|
let mut shell_env = delegate.shell_env().await;
|
||||||
|
@ -10409,17 +10418,22 @@ impl LspStore {
|
||||||
|
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
log::info!("stopping language server {name}");
|
log::info!("stopping language server {name}");
|
||||||
self.languages
|
self.languages.update_lsp_binary_status(
|
||||||
.update_lsp_binary_status(name.clone(), BinaryStatus::Stopping);
|
server_id,
|
||||||
|
name.clone(),
|
||||||
|
BinaryStatus::Stopping,
|
||||||
|
);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
||||||
return cx.spawn(async move |lsp_store, cx| {
|
return cx.spawn(async move |lsp_store, cx| {
|
||||||
Self::shutdown_language_server(server_state, name.clone(), cx).await;
|
Self::shutdown_language_server(server_state, name.clone(), cx).await;
|
||||||
lsp_store
|
lsp_store
|
||||||
.update(cx, |lsp_store, cx| {
|
.update(cx, |lsp_store, cx| {
|
||||||
lsp_store
|
lsp_store.languages.update_lsp_binary_status(
|
||||||
.languages
|
server_id,
|
||||||
.update_lsp_binary_status(name, BinaryStatus::Stopped);
|
name.clone(),
|
||||||
|
BinaryStatus::Stopped,
|
||||||
|
);
|
||||||
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
|
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id));
|
||||||
cx.notify();
|
cx.notify();
|
||||||
})
|
})
|
||||||
|
@ -10882,7 +10896,7 @@ impl LspStore {
|
||||||
);
|
);
|
||||||
local
|
local
|
||||||
.languages
|
.languages
|
||||||
.update_lsp_binary_status(adapter.name(), BinaryStatus::None);
|
.update_lsp_binary_status(server_id, adapter.name(), BinaryStatus::None);
|
||||||
if let Some(file_ops_caps) = language_server
|
if let Some(file_ops_caps) = language_server
|
||||||
.capabilities()
|
.capabilities()
|
||||||
.workspace
|
.workspace
|
||||||
|
@ -12197,7 +12211,7 @@ fn subscribe_to_binary_statuses(
|
||||||
) -> Task<()> {
|
) -> Task<()> {
|
||||||
let mut server_statuses = languages.language_server_binary_statuses();
|
let mut server_statuses = languages.language_server_binary_statuses();
|
||||||
cx.spawn(async move |lsp_store, cx| {
|
cx.spawn(async move |lsp_store, cx| {
|
||||||
while let Some((server_name, binary_status)) = server_statuses.next().await {
|
while let Some((server_id, server_name, binary_status)) = server_statuses.next().await {
|
||||||
if lsp_store
|
if lsp_store
|
||||||
.update(cx, |_, cx| {
|
.update(cx, |_, cx| {
|
||||||
let mut message = None;
|
let mut message = None;
|
||||||
|
@ -12216,9 +12230,7 @@ fn subscribe_to_binary_statuses(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cx.emit(LspStoreEvent::LanguageServerUpdate {
|
cx.emit(LspStoreEvent::LanguageServerUpdate {
|
||||||
// Binary updates are about the binary that might not have any language server id at that point.
|
language_server_id: server_id,
|
||||||
// Reuse `LanguageServerUpdate` for them and provide a fake id that won't be used on the receiver side.
|
|
||||||
language_server_id: LanguageServerId(0),
|
|
||||||
name: Some(server_name),
|
name: Some(server_name),
|
||||||
message: proto::update_language_server::Variant::StatusUpdate(
|
message: proto::update_language_server::Variant::StatusUpdate(
|
||||||
proto::StatusUpdate {
|
proto::StatusUpdate {
|
||||||
|
@ -13154,9 +13166,14 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_status(&self, server_name: LanguageServerName, status: language::BinaryStatus) {
|
fn update_status(
|
||||||
|
&self,
|
||||||
|
server_id: LanguageServerId,
|
||||||
|
server_name: LanguageServerName,
|
||||||
|
status: language::BinaryStatus,
|
||||||
|
) {
|
||||||
self.language_registry
|
self.language_registry
|
||||||
.update_lsp_binary_status(server_name, status);
|
.update_lsp_binary_status(server_id, server_name, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn registered_lsp_adapters(&self) -> Vec<Arc<dyn LspAdapter>> {
|
fn registered_lsp_adapters(&self) -> Vec<Arc<dyn LspAdapter>> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue