Detailed changes
@@ -33,6 +33,7 @@ use std::sync::Arc;
use task::DebugTaskDefinition;
use terminal_view::terminal_panel::TerminalPanel;
use ui::{ContextMenu, Divider, DropdownMenu, Tooltip, prelude::*};
+use util::debug_panic;
use workspace::{
Workspace,
dock::{DockPosition, Panel, PanelEvent},
@@ -316,8 +317,20 @@ impl DebugPanel {
.any(|item| item.read(cx).session_id(cx) == session_id)
{
// We already have an item for this session.
+ debug_panic!("We should never reuse session ids");
return;
}
+
+ this.sessions.retain(|session| {
+ session
+ .read(cx)
+ .mode()
+ .as_running()
+ .map_or(false, |running_state| {
+ !running_state.read(cx).session().read(cx).is_terminated()
+ })
+ });
+
let session_item = DebugSession::running(
project,
this.workspace.clone(),
@@ -769,9 +782,6 @@ impl DebugPanel {
this.restart_session(cx);
},
))
- .disabled(
- !capabilities.supports_restart_request.unwrap_or_default(),
- )
.tooltip(move |window, cx| {
Tooltip::text("Restart")(window, cx)
}),
@@ -792,10 +792,48 @@ fn create_new_session(
this.update(cx, |_, cx| {
cx.subscribe(
&session,
- move |this: &mut DapStore, _, event: &SessionStateEvent, cx| match event {
+ 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 Some((config, binary)) = session.read_with(cx, |session, _| {
+ session
+ .configuration()
+ .map(|config| (config, session.binary().clone()))
+ }) else {
+ log::error!("Failed to get debug config from session");
+ return;
+ };
+
+ 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 session_id = curr_session.read(cx).session_id();
+
+ let task = curr_session.update(cx, |session, cx| session.shutdown(cx));
+
+ cx.spawn(async move |this, cx| {
+ task.await;
+
+ this.update(cx, |this, cx| {
+ this.sessions.remove(&session_id);
+ this.new_session(binary, config, None, cx)
+ })?
+ .1
+ .await?;
+
+ anyhow::Ok(())
+ })
+ .detach_and_log_err(cx);
+ }
},
)
.detach();
@@ -397,6 +397,7 @@ impl LocalMode {
self.definition.initialize_args.clone().unwrap_or(json!({})),
&mut raw.configuration,
);
+
// Of relevance: https://github.com/microsoft/vscode/issues/4902#issuecomment-368583522
let launch = match raw.request {
dap::StartDebuggingRequestArgumentsRequest::Launch => self.request(
@@ -684,8 +685,9 @@ pub enum SessionEvent {
Threads,
}
-pub(crate) enum SessionStateEvent {
+pub(super) enum SessionStateEvent {
Shutdown,
+ Restart,
}
impl EventEmitter<SessionEvent> for Session {}
@@ -1362,6 +1364,18 @@ impl Session {
&self.loaded_sources
}
+ fn fallback_to_manual_restart(
+ &mut self,
+ res: Result<()>,
+ cx: &mut Context<Self>,
+ ) -> Option<()> {
+ if res.log_err().is_none() {
+ cx.emit(SessionStateEvent::Restart);
+ return None;
+ }
+ Some(())
+ }
+
fn empty_response(&mut self, res: Result<()>, _cx: &mut Context<Self>) -> Option<()> {
res.log_err()?;
Some(())
@@ -1421,26 +1435,17 @@ impl Session {
}
pub fn restart(&mut self, args: Option<Value>, cx: &mut Context<Self>) {
- if self.capabilities.supports_restart_request.unwrap_or(false) {
+ if self.capabilities.supports_restart_request.unwrap_or(false) && !self.is_terminated() {
self.request(
RestartCommand {
raw: args.unwrap_or(Value::Null),
},
- Self::empty_response,
+ Self::fallback_to_manual_restart,
cx,
)
.detach();
} else {
- self.request(
- DisconnectCommand {
- restart: Some(false),
- terminate_debuggee: Some(true),
- suspend_debuggee: Some(false),
- },
- Self::empty_response,
- cx,
- )
- .detach();
+ cx.emit(SessionStateEvent::Restart);
}
}
@@ -1475,8 +1480,14 @@ impl Session {
cx.emit(SessionStateEvent::Shutdown);
+ let debug_client = self.adapter_client();
+
cx.background_spawn(async move {
let _ = task.await;
+
+ if let Some(client) = debug_client {
+ client.shutdown().await.log_err();
+ }
})
}