Add initial support for defining language server adapters in WebAssembly-based extensions (#8645)
This PR adds **internal** ability to run arbitrary language servers via WebAssembly extensions. The functionality isn't exposed yet - we're just landing this in this early state because there have been a lot of changes to the `LspAdapter` trait, and other language server logic. ## Next steps * Currently, wasm extensions can only define how to *install* and run a language server, they can't yet implement the other LSP adapter methods, such as formatting completion labels and workspace symbols. * We don't have an automatic way to install or develop these types of extensions * We don't have a way to package these types of extensions in our extensions repo, to make them available via our extensions API. * The Rust extension API crate, `zed-extension-api` has not yet been published to crates.io, because we still consider the API a work in progress. Release Notes: - N/A --------- Co-authored-by: Marshall <marshall@zed.dev> Co-authored-by: Nathan <nathan@zed.dev> Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
f3f2225a8e
commit
268fa1cbaf
84 changed files with 3714 additions and 1973 deletions
|
@ -6,7 +6,7 @@ use gpui::{
|
|||
ParentElement as _, Render, SharedString, StatefulInteractiveElement, Styled, View,
|
||||
ViewContext, VisualContext as _,
|
||||
};
|
||||
use language::{LanguageRegistry, LanguageServerBinaryStatus};
|
||||
use language::{LanguageRegistry, LanguageServerBinaryStatus, LanguageServerName};
|
||||
use project::{LanguageServerProgress, Project};
|
||||
use smallvec::SmallVec;
|
||||
use std::{cmp::Reverse, fmt::Write, sync::Arc};
|
||||
|
@ -30,7 +30,7 @@ pub struct ActivityIndicator {
|
|||
}
|
||||
|
||||
struct LspStatus {
|
||||
name: Arc<str>,
|
||||
name: LanguageServerName,
|
||||
status: LanguageServerBinaryStatus,
|
||||
}
|
||||
|
||||
|
@ -58,13 +58,10 @@ impl ActivityIndicator {
|
|||
let this = cx.new_view(|cx: &mut ViewContext<Self>| {
|
||||
let mut status_events = languages.language_server_binary_statuses();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
while let Some((language, event)) = status_events.next().await {
|
||||
while let Some((name, status)) = status_events.next().await {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.statuses.retain(|s| s.name != language.name());
|
||||
this.statuses.push(LspStatus {
|
||||
name: language.name(),
|
||||
status: event,
|
||||
});
|
||||
this.statuses.retain(|s| s.name != name);
|
||||
this.statuses.push(LspStatus { name, status });
|
||||
cx.notify();
|
||||
})?;
|
||||
}
|
||||
|
@ -114,7 +111,7 @@ impl ActivityIndicator {
|
|||
self.statuses.retain(|status| {
|
||||
if let LanguageServerBinaryStatus::Failed { error } = &status.status {
|
||||
cx.emit(Event::ShowError {
|
||||
lsp_name: status.name.clone(),
|
||||
lsp_name: status.name.0.clone(),
|
||||
error: error.clone(),
|
||||
});
|
||||
false
|
||||
|
@ -202,11 +199,12 @@ impl ActivityIndicator {
|
|||
let mut checking_for_update = SmallVec::<[_; 3]>::new();
|
||||
let mut failed = SmallVec::<[_; 3]>::new();
|
||||
for status in &self.statuses {
|
||||
let name = status.name.clone();
|
||||
match status.status {
|
||||
LanguageServerBinaryStatus::CheckingForUpdate => checking_for_update.push(name),
|
||||
LanguageServerBinaryStatus::Downloading => downloading.push(name),
|
||||
LanguageServerBinaryStatus::Failed { .. } => failed.push(name),
|
||||
LanguageServerBinaryStatus::CheckingForUpdate => {
|
||||
checking_for_update.push(status.name.0.as_ref())
|
||||
}
|
||||
LanguageServerBinaryStatus::Downloading => downloading.push(status.name.0.as_ref()),
|
||||
LanguageServerBinaryStatus::Failed { .. } => failed.push(status.name.0.as_ref()),
|
||||
LanguageServerBinaryStatus::Downloaded | LanguageServerBinaryStatus::Cached => {}
|
||||
}
|
||||
}
|
||||
|
@ -214,34 +212,28 @@ impl ActivityIndicator {
|
|||
if !downloading.is_empty() {
|
||||
return Content {
|
||||
icon: Some(DOWNLOAD_ICON),
|
||||
message: format!(
|
||||
"Downloading {} language server{}...",
|
||||
downloading.join(", "),
|
||||
if downloading.len() > 1 { "s" } else { "" }
|
||||
),
|
||||
message: format!("Downloading {}...", downloading.join(", "),),
|
||||
on_click: None,
|
||||
};
|
||||
} else if !checking_for_update.is_empty() {
|
||||
}
|
||||
|
||||
if !checking_for_update.is_empty() {
|
||||
return Content {
|
||||
icon: Some(DOWNLOAD_ICON),
|
||||
message: format!(
|
||||
"Checking for updates to {} language server{}...",
|
||||
"Checking for updates to {}...",
|
||||
checking_for_update.join(", "),
|
||||
if checking_for_update.len() > 1 {
|
||||
"s"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
),
|
||||
on_click: None,
|
||||
};
|
||||
} else if !failed.is_empty() {
|
||||
}
|
||||
|
||||
if !failed.is_empty() {
|
||||
return Content {
|
||||
icon: Some(WARNING_ICON),
|
||||
message: format!(
|
||||
"Failed to download {} language server{}. Click to show error.",
|
||||
"Failed to download {}. Click to show error.",
|
||||
failed.join(", "),
|
||||
if failed.len() > 1 { "s" } else { "" }
|
||||
),
|
||||
on_click: Some(Arc::new(|this, cx| {
|
||||
this.show_error_message(&Default::default(), cx)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue