Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show DAP status in activity bar #54

Merged
merged 5 commits into from
Oct 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions crates/activity_indicator/src/activity_indicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ actions!(activity_indicator, [ShowErrorMessage]);

pub enum Event {
ShowError {
lsp_name: LanguageServerName,
server_name: LanguageServerName,
error: String,
},
}

pub struct ActivityIndicator {
statuses: Vec<LspStatus>,
statuses: Vec<ServerStatus>,
project: Model<Project>,
auto_updater: Option<Model<AutoUpdater>>,
context_menu_handle: PopoverMenuHandle<ContextMenu>,
}

struct LspStatus {
struct ServerStatus {
name: LanguageServerName,
status: LanguageServerBinaryStatus,
}
Expand Down Expand Up @@ -63,13 +63,27 @@ impl ActivityIndicator {
while let Some((name, status)) = status_events.next().await {
this.update(&mut cx, |this, cx| {
this.statuses.retain(|s| s.name != name);
this.statuses.push(LspStatus { name, status });
this.statuses.push(ServerStatus { name, status });
cx.notify();
})?;
}
anyhow::Ok(())
})
.detach();

let mut status_events = languages.dap_server_binary_statuses();
cx.spawn(|this, mut cx| async move {
while let Some((name, status)) = status_events.next().await {
this.update(&mut cx, |this, cx| {
this.statuses.retain(|s| s.name != name);
this.statuses.push(ServerStatus { name, status });
cx.notify();
})?;
}
anyhow::Ok(())
})
.detach();

cx.observe(&project, |_, _, cx| cx.notify()).detach();

if let Some(auto_updater) = auto_updater.as_ref() {
Expand All @@ -85,7 +99,10 @@ impl ActivityIndicator {
});

cx.subscribe(&this, move |_, _, event, cx| match event {
Event::ShowError { lsp_name, error } => {
Event::ShowError {
server_name: lsp_name,
error,
} => {
let create_buffer = project.update(cx, |project, cx| project.create_buffer(cx));
let project = project.clone();
let error = error.clone();
Expand Down Expand Up @@ -127,7 +144,7 @@ impl ActivityIndicator {
self.statuses.retain(|status| {
if let LanguageServerBinaryStatus::Failed { error } = &status.status {
cx.emit(Event::ShowError {
lsp_name: status.name.clone(),
server_name: status.name.clone(),
error: error.clone(),
});
false
Expand Down
11 changes: 11 additions & 0 deletions crates/dap/src/adapters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@ use std::{
};
use task::DebugAdapterConfig;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DapStatus {
None,
CheckingForUpdate,
Downloading,
Failed { error: String },
}

pub trait DapDelegate {
fn http_client(&self) -> Option<Arc<dyn HttpClient>>;
fn node_runtime(&self) -> Option<NodeRuntime>;
fn fs(&self) -> Arc<dyn Fs>;
fn cached_binaries(&self) -> Arc<Mutex<HashMap<DebugAdapterName, DebugAdapterBinary>>>;
fn update_status(&self, dap_name: DebugAdapterName, status: DapStatus);
}

#[derive(PartialEq, Eq, Hash, Debug)]
Expand Down Expand Up @@ -189,6 +198,7 @@ pub trait DebugAdapter: 'static + Send + Sync {
}

log::info!("Getting latest version of debug adapter {}", self.name());
delegate.update_status(self.name(), DapStatus::CheckingForUpdate);
let version = self.fetch_latest_adapter_version(delegate).await.ok();

let mut binary = self.get_installed_binary(delegate, config).await;
Expand All @@ -209,6 +219,7 @@ pub trait DebugAdapter: 'static + Send + Sync {
return Ok(binary);
}

delegate.update_status(self.name(), DapStatus::Downloading);
self.install_binary(version, delegate).await?;
binary = self.get_installed_binary(delegate, config).await;
}
Expand Down
36 changes: 36 additions & 0 deletions crates/language/src/language_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ pub struct LanguageRegistry {
language_server_download_dir: Option<Arc<Path>>,
executor: BackgroundExecutor,
lsp_binary_status_tx: LspBinaryStatusSender,
dap_binary_status_tx: DapBinaryStatusSender,
}

struct LanguageRegistryState {
Expand Down Expand Up @@ -222,6 +223,7 @@ impl LanguageRegistry {
}),
language_server_download_dir: None,
lsp_binary_status_tx: Default::default(),
dap_binary_status_tx: Default::default(),
executor,
};
this.add(PLAIN_TEXT.clone());
Expand Down Expand Up @@ -875,6 +877,14 @@ impl LanguageRegistry {
self.lsp_binary_status_tx.send(server_name, status);
}

pub fn update_dap_status(
&self,
server_name: LanguageServerName,
status: LanguageServerBinaryStatus,
) {
self.dap_binary_status_tx.send(server_name, status);
}

pub fn next_language_server_id(&self) -> LanguageServerId {
self.state.write().next_language_server_id()
}
Expand Down Expand Up @@ -930,6 +940,12 @@ impl LanguageRegistry {
self.lsp_binary_status_tx.subscribe()
}

pub fn dap_server_binary_statuses(
&self,
) -> mpsc::UnboundedReceiver<(LanguageServerName, LanguageServerBinaryStatus)> {
self.dap_binary_status_tx.subscribe()
}

pub async fn delete_server_container(&self, name: LanguageServerName) {
log::info!("deleting server container");
let Some(dir) = self.language_server_download_dir(&name) else {
Expand Down Expand Up @@ -1039,6 +1055,26 @@ impl LanguageRegistryState {
}
}

#[derive(Clone, Default)]
struct DapBinaryStatusSender {
txs: Arc<Mutex<Vec<mpsc::UnboundedSender<(LanguageServerName, LanguageServerBinaryStatus)>>>>,
}

impl DapBinaryStatusSender {
fn subscribe(
&self,
) -> mpsc::UnboundedReceiver<(LanguageServerName, LanguageServerBinaryStatus)> {
let (tx, rx) = mpsc::unbounded();
self.txs.lock().push(tx);
rx
}

fn send(&self, name: LanguageServerName, status: LanguageServerBinaryStatus) {
let mut txs = self.txs.lock();
txs.retain(|tx| tx.unbounded_send((name.clone(), status.clone())).is_ok());
}
}

impl LspBinaryStatusSender {
fn subscribe(
&self,
Expand Down
28 changes: 25 additions & 3 deletions crates/project/src/dap_store.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::ProjectPath;
use anyhow::{anyhow, Context as _, Result};
use collections::HashSet;
use dap::adapters::{DebugAdapterBinary, DebugAdapterName};
use dap::adapters::{DapStatus, DebugAdapterBinary, DebugAdapterName};
use dap::client::{DebugAdapterClient, DebugAdapterClientId};
use dap::messages::{Message, Response};
use dap::requests::{
Expand All @@ -23,9 +23,11 @@ use dap::{
};
use dap_adapters::build_adapter;
use fs::Fs;
use gpui::{EventEmitter, Model, ModelContext, Task};
use gpui::{EventEmitter, Model, ModelContext, SharedString, Task};
use http_client::HttpClient;
use language::{Buffer, BufferSnapshot};
use language::{
Buffer, BufferSnapshot, LanguageRegistry, LanguageServerBinaryStatus, LanguageServerName,
};
use node_runtime::NodeRuntime;
use serde_json::{json, Value};
use settings::WorktreeId;
Expand Down Expand Up @@ -73,6 +75,7 @@ pub struct DapStore {
active_debug_line: Option<(ProjectPath, DebugPosition)>,
http_client: Option<Arc<dyn HttpClient>>,
node_runtime: Option<NodeRuntime>,
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
}

Expand All @@ -83,6 +86,7 @@ impl DapStore {
http_client: Option<Arc<dyn HttpClient>>,
node_runtime: Option<NodeRuntime>,
fs: Arc<dyn Fs>,
_languages: Arc<LanguageRegistry>,
cx: &mut ModelContext<Self>,
) -> Self {
cx.on_app_quit(Self::shutdown_clients).detach();
Expand All @@ -96,6 +100,7 @@ impl DapStore {
next_client_id: Default::default(),
http_client,
node_runtime,
languages: _languages,
fs,
}
}
Expand Down Expand Up @@ -248,6 +253,7 @@ impl DapStore {
self.node_runtime.clone(),
self.fs.clone(),
self.cached_binaries.clone(),
self.languages.clone(),
);
let start_client_task = cx.spawn(|this, mut cx| async move {
let dap_store = this.clone();
Expand Down Expand Up @@ -1234,6 +1240,7 @@ pub struct DapAdapterDelegate {
http_client: Option<Arc<dyn HttpClient>>,
node_runtime: Option<NodeRuntime>,
cached_binaries: Arc<Mutex<HashMap<DebugAdapterName, DebugAdapterBinary>>>,
languages: Arc<LanguageRegistry>,
}

impl DapAdapterDelegate {
Expand All @@ -1242,12 +1249,14 @@ impl DapAdapterDelegate {
node_runtime: Option<NodeRuntime>,
fs: Arc<dyn Fs>,
cached_binaries: Arc<Mutex<HashMap<DebugAdapterName, DebugAdapterBinary>>>,
languages: Arc<LanguageRegistry>,
) -> Self {
Self {
fs,
http_client,
node_runtime,
cached_binaries,
languages,
}
}
}
Expand All @@ -1268,4 +1277,17 @@ impl dap::adapters::DapDelegate for DapAdapterDelegate {
fn cached_binaries(&self) -> Arc<Mutex<HashMap<DebugAdapterName, DebugAdapterBinary>>> {
self.cached_binaries.clone()
}

fn update_status(&self, dap_name: DebugAdapterName, status: dap::adapters::DapStatus) {
let name = SharedString::from(dap_name.to_string());
let status = match status {
DapStatus::None => LanguageServerBinaryStatus::None,
DapStatus::Downloading => LanguageServerBinaryStatus::Downloading,
DapStatus::Failed { error } => LanguageServerBinaryStatus::Failed { error },
DapStatus::CheckingForUpdate => LanguageServerBinaryStatus::CheckingForUpdate,
};

self.languages
.update_dap_status(LanguageServerName(name), status);
}
}
13 changes: 11 additions & 2 deletions crates/project/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ impl Project {
Some(client.http_client()),
Some(node.clone()),
fs.clone(),
languages.clone(),
cx,
)
});
Expand Down Expand Up @@ -786,6 +787,7 @@ impl Project {
Some(client.http_client()),
Some(node.clone()),
fs.clone(),
languages.clone(),
cx,
)
});
Expand Down Expand Up @@ -944,8 +946,15 @@ impl Project {
BufferStore::remote(worktree_store.clone(), client.clone().into(), remote_id, cx)
})?;

let dap_store =
cx.new_model(|cx| DapStore::new(Some(client.http_client()), None, fs.clone(), cx))?;
let dap_store = cx.new_model(|cx| {
DapStore::new(
Some(client.http_client()),
None,
fs.clone(),
languages.clone(),
cx,
)
})?;

let lsp_store = cx.new_model(|cx| {
let mut lsp_store = LspStore::new_remote(
Expand Down
3 changes: 2 additions & 1 deletion crates/remote_server/src/headless_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ impl HeadlessProject {
store
});

let dap_store = cx.new_model(|cx| DapStore::new(None, None, fs.clone(), cx));
let dap_store =
cx.new_model(|cx| DapStore::new(None, None, fs.clone(), languages.clone(), cx));
let buffer_store = cx.new_model(|cx| {
let mut buffer_store =
BufferStore::local(worktree_store.clone(), dap_store.clone(), cx);
Expand Down
Loading