Finish merge

This commit is contained in:
Anthony
2025-04-21 22:22:53 -04:00
parent 351adc23f1
commit 0cb2ff84ed
4 changed files with 49 additions and 308 deletions

View File

@@ -108,11 +108,7 @@ impl NewSessionModal {
return;
};
let config = self.debug_config(cx, debugger);
let _ = self.debug_panel.update(cx, |panel, cx| {
panel.past_debug_definition = Some(config.clone());
panel.start_session(config, window, cx)
});
let workspace = self.workspace.clone();
let task_contexts = workspace
.update(cx, |workspace, cx| {
@@ -120,7 +116,7 @@ impl NewSessionModal {
})
.ok();
cx.spawn(async move |this, cx| {
cx.spawn_in(window, async move |this, cx| {
let task_context = if let Some(task) = task_contexts {
task.await
.active_worktree_context
@@ -128,9 +124,8 @@ impl NewSessionModal {
} else {
task::TaskContext::default()
};
let project = workspace.update(cx, |workspace, _| workspace.project().clone())?;
let task = project.update(cx, |this, cx| {
workspace.update_in(cx, |this, window, cx| {
let template = DebugTaskTemplate {
locator: None,
definition: config.clone(),
@@ -140,23 +135,18 @@ impl NewSessionModal {
.resolve_task("debug_task", &task_context)
.and_then(|resolved_task| resolved_task.resolved_debug_adapter_config())
{
this.start_debug_session(debug_config.definition, cx)
this.start_debug_session(debug_config.definition, window, cx)
} else {
this.start_debug_session(config, cx)
this.start_debug_session(config, window, cx)
}
})?;
let spawn_result = task.await;
if spawn_result.is_ok() {
this.update(cx, |_, cx| {
cx.emit(DismissEvent);
})
.ok();
}
spawn_result?;
this.update(cx, |_, cx| {
cx.emit(DismissEvent);
})
.ok();
anyhow::Result::<_, anyhow::Error>::Ok(())
})
.detach_and_log_err(cx);
Ok(())
}
fn update_attach_picker(

View File

@@ -9,7 +9,7 @@ use crate::{
terminals::{SshCommand, wrap_for_ssh},
worktree_store::WorktreeStore,
};
use anyhow::{Result, anyhow};
use anyhow::{Result, anyhow, bail};
use async_trait::async_trait;
use collections::HashMap;
use dap::{
@@ -95,14 +95,12 @@ pub struct LocalDapStore {
pub struct SshDapStore {
upstream_client: AnyProtoClient,
ssh_client: Entity<SshRemoteClient>,
upstream_project_id: u64,
}
pub struct DapStore {
mode: DapStoreMode,
downstream_client: Option<(AnyProtoClient, u64)>,
worktree_store: Entity<WorktreeStore>,
breakpoint_store: Entity<BreakpointStore>,
sessions: BTreeMap<SessionId, Entity<Session>>,
next_session_id: u32,
@@ -208,7 +206,6 @@ impl DapStore {
start_debugging_tx,
next_session_id: 0,
downstream_client: None,
worktree_store,
breakpoint_store,
sessions: Default::default(),
}
@@ -324,70 +321,23 @@ impl DapStore {
}
}
pub fn add_remote_client(
&mut self,
definition: DebugTaskDefinition,
cx: &mut Context<Self>,
) {
if let DapStoreMode::Ssh(remote) = &self.mode {
self.sessions.insert(
session_id,
cx.new(|_| {
debugger::session::Session::remote(
session_id,
remote.upstream_client.clone(),
remote.upstream_project_id,
ignore.unwrap_or(false),
)
}),
);
} else {
debug_assert!(false);
}
}
pub fn run_debug_locator(
&mut self,
template: DebugTaskTemplate,
cx: &mut Context<Self>,
) -> Task<Result<DebugTaskDefinition>> {
let Some(locator_name) = template.locator else {
return Task::ready(Ok(template.definition));
};
match &self.mode {
DapStoreMode::Local(local) => {
if let Some(locator) = local.locators.get(&locator_name).cloned() {
cx.background_spawn(
async move { locator.run_locator(template.definition).await },
)
} else {
Task::ready(Err(anyhow!("Couldn't find locator {}", locator_name)))
}
}
DapStoreMode::Ssh(ssh) => {
let request = ssh.upstream_client.request(proto::RunDebugLocator {
project_id: ssh.upstream_project_id,
locator: locator_name,
task: Some(template.definition.to_proto()),
});
cx.background_spawn(async move {
let response = request.await?;
DebugTaskDefinition::from_proto(response)
})
}
DapStoreMode::Collab => {
Task::ready(Err(anyhow!("Debugging is not yet supported via collab")))
}
}
}
fn as_local(&self) -> Option<&LocalDapStore> {
match &self.mode {
DapStoreMode::Local(local_dap_store) => Some(local_dap_store),
_ => None,
}
}
// pub fn add_remote_client(&mut self, definition: DebugTaskDefinition, cx: &mut Context<Self>) {
// if let DapStoreMode::Ssh(remote) = &self.mode {
// self.sessions.insert(
// session_id,
// cx.new(|_| {
// debugger::session::Session::remote(
// session_id,
// remote.upstream_client.clone(),
// remote.upstream_project_id,
// ignore.unwrap_or(false),
// )
// }),
// );
// } else {
// debug_assert!(false);
// }
// }
pub fn start_session(
&mut self,
@@ -395,7 +345,11 @@ impl DapStore {
parent_session: Option<Entity<Session>>,
cx: &mut Context<Self>,
) -> Result<Entity<Session>> {
let Some(worktree) = self.worktree_store.read(cx).visible_worktrees(cx).next() else {
let Some(local) = self.as_local() else {
bail!("Can't start a session from non local dap store");
};
let Some(worktree) = local.worktree_store.read(cx).visible_worktrees(cx).next() else {
return Err(anyhow!("Failed to find a worktree"));
};
let session_id = SessionId(util::post_inc(&mut self.next_session_id));
@@ -939,142 +893,6 @@ impl DapStore {
}
}
async fn handle_run_debug_locator(
this: Entity<Self>,
envelope: TypedEnvelope<proto::RunDebugLocator>,
mut cx: AsyncApp,
) -> Result<proto::DebugTaskDefinition> {
let template = DebugTaskTemplate {
locator: Some(envelope.payload.locator),
definition: DebugTaskDefinition::from_proto(
envelope
.payload
.task
.ok_or_else(|| anyhow!("missing definition"))?,
)?,
};
let definition = this
.update(&mut cx, |this, cx| this.run_debug_locator(template, cx))?
.await?;
Ok(definition.to_proto())
}
<<<<<<< HEAD
async fn handle_get_debug_adapter_binary(
this: Entity<Self>,
envelope: TypedEnvelope<proto::GetDebugAdapterBinary>,
mut cx: AsyncApp,
) -> Result<proto::DebugAdapterBinary> {
let definition = DebugTaskDefinition::from_proto(
envelope
.payload
.task
.ok_or_else(|| anyhow!("missing definition"))?,
)?;
let binary = this
.update(&mut cx, |this, cx| {
this.get_debug_adapter_binary(definition, cx)
})?
.await?;
Ok(binary.to_proto())
}
=======
// we have to insert the session early, so we can handle reverse requests
// that need the session to be available
this.update(cx, |store, cx| {
store.sessions.insert(session_id, session.clone());
cx.emit(DapStoreEvent::DebugClientStarted(session_id));
cx.notify();
})?;
let seq_result = async || {
session
.update(cx, |session, cx| session.request_initialize(cx))?
.await?;
session
.update(cx, |session, cx| {
session.initialize_sequence(initialized_rx, this.clone(), cx)
})?
.await
};
match seq_result().await {
Ok(_) => {}
Err(error) => {
this.update(cx, |this, cx| {
cx.emit(DapStoreEvent::Notification(error.to_string()));
this.shutdown_session(session_id, cx)
})?
.await
.log_err();
return Err(error);
}
}
this.update(cx, |_, cx| {
cx.subscribe(
&session,
move |this: &mut DapStore, session, event: &SessionStateEvent, cx| match event {
SessionStateEvent::Shutdown => {
this.shutdown_session(session_id, cx).detach_and_log_err(cx);
}
SessionStateEvent::Restart => {
let mut curr_session = session;
while let Some(parent_id) = curr_session.read(cx).parent_id() {
if let Some(parent_session) = this.sessions.get(&parent_id).cloned() {
curr_session = parent_session;
} else {
log::error!("Failed to get parent session from parent session id");
break;
}
}
let Some((config, binary)) = curr_session.read_with(cx, |session, _| {
session
.configuration()
.map(|config| (config, session.root_binary().clone()))
}) else {
log::error!("Failed to get debug config from session");
return;
};
let session_id = curr_session.read(cx).session_id();
let task = curr_session.update(cx, |session, cx| session.shutdown(cx));
let worktree = worktree.clone();
cx.spawn(async move |this, cx| {
task.await;
this.update(cx, |this, cx| {
this.sessions.remove(&session_id);
this.new_session(
binary.as_ref().clone(),
config,
worktree,
None,
cx,
)
})?
.1
.await?;
anyhow::Ok(())
})
.detach_and_log_err(cx);
}
},
)
.detach();
cx.emit(DapStoreEvent::DebugSessionInitialized(session_id));
})?;
Ok(session)
});
task
>>>>>>> origin/main
}
#[derive(Clone)]
pub struct DapAdapterDelegate {
fs: Arc<dyn Fs>,

View File

@@ -153,12 +153,17 @@ impl LocalMode {
binary: DebugAdapterBinary,
messages_tx: futures::channel::mpsc::UnboundedSender<Message>,
cx: AsyncApp,
<<<<<<< HEAD
) -> Result<Self> {
let message_handler = Box::new(move |message| {
messages_tx.unbounded_send(message).ok();
});
let root_binary = if let Some(parent_session) = parent_session.as_ref() {
Some(parent_session.read_with(&cx, |session, _| session.root_binary().clone())?)
} else {
None
};
let client = Arc::new(
if let Some(client) = parent_session
.and_then(|session| cx.update(|cx| session.read(cx).adapter_client()).ok())
@@ -169,58 +174,18 @@ impl LocalMode {
.await?
} else {
DebugAdapterClient::start(session_id, binary.clone(), message_handler, cx.clone())
=======
) -> Task<Result<Self>> {
cx.spawn(async move |cx| {
let message_handler = Box::new(move |message| {
messages_tx.unbounded_send(message).ok();
});
let root_binary = if let Some(parent_session) = parent_session.as_ref() {
Some(parent_session.read_with(cx, |session, _| session.root_binary().clone())?)
} else {
None
};
let client = Arc::new(
if let Some(client) = parent_session
.and_then(|session| cx.update(|cx| session.read(cx).adapter_client()).ok())
.flatten()
{
client
.reconnect(session_id, binary.clone(), message_handler, cx.clone())
.await?
} else {
DebugAdapterClient::start(
session_id,
binary.clone(),
message_handler,
cx.clone(),
)
>>>>>>> origin/main
.await
.with_context(|| "Failed to start communication with debug adapter")?
},
);
<<<<<<< HEAD
Ok(Self {
client,
breakpoint_store,
worktree,
tmp_breakpoint: None,
root_binary,
binary,
=======
Ok(Self {
client,
breakpoint_store,
worktree,
tmp_breakpoint: None,
definition: config,
root_binary,
binary,
})
>>>>>>> origin/main
})
}
@@ -857,13 +822,16 @@ impl Session {
}
pub(crate) fn root_binary(&self) -> Arc<DebugAdapterBinary> {
let Mode::Local(local_mode) = &self.mode else {
panic!("Session is not local");
};
local_mode
.root_binary
.clone()
.unwrap_or_else(|| Arc::new(local_mode.binary.clone()))
match &self.mode {
Mode::Building => {
// todo(debugger): Implement root_binary for building mode
unimplemented!()
}
Mode::Running(running) => running
.root_binary
.clone()
.unwrap_or_else(|| Arc::new(running.binary.clone())),
}
}
pub fn binary(&self) -> &DebugAdapterBinary {

View File

@@ -39,41 +39,6 @@ pub fn intercept_debug_sessions<T: Fn(&Arc<DebugAdapterClient>) + 'static>(
})
}
pub fn start_debug_session_with<T: Fn(&Arc<DebugAdapterClient>) + 'static>(
project: &Entity<Project>,
cx: &mut gpui::TestAppContext,
config: DebugTaskDefinition,
configure: T,
) -> Task<Result<Entity<Session>>> {
let subscription = intercept_debug_sessions(cx, configure);
let task = project.update(cx, |project, cx| project.start_debug_session(config, cx));
cx.spawn(async move |_| {
let result = task.await;
drop(subscription);
result
})
}
pub fn start_debug_session<T: Fn(&Arc<DebugAdapterClient>) + 'static>(
project: &Entity<Project>,
cx: &mut gpui::TestAppContext,
configure: T,
) -> Task<Result<Entity<Session>>> {
start_debug_session_with(
project,
cx,
DebugTaskDefinition {
adapter: "fake-adapter".to_string(),
request: DebugRequest::Launch(Default::default()),
label: "test".to_string(),
initialize_args: None,
tcp_connection: None,
stop_on_entry: None,
},
configure,
)
}
fn register_default_handlers(session: &Session, client: &Arc<DebugAdapterClient>, cx: &mut App) {
client.on_request::<dap::requests::Initialize, _>(move |_, _| Ok(Default::default()));
let paths = session