From 45db28a5cee1835e82ff30002eef1ccb969274a1 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 17 Feb 2025 12:50:55 +0100 Subject: [PATCH] Project compiles, yay --- crates/debugger_tools/src/dap_log.rs | 68 ++-- crates/project/src/debugger/client.rs | 10 +- crates/project/src/debugger/dap_store.rs | 436 +++++++++++------------ crates/project/src/project.rs | 2 +- crates/task/src/debug_format.rs | 3 + 5 files changed, 253 insertions(+), 266 deletions(-) diff --git a/crates/debugger_tools/src/dap_log.rs b/crates/debugger_tools/src/dap_log.rs index 5b9067d498..17475fae09 100644 --- a/crates/debugger_tools/src/dap_log.rs +++ b/crates/debugger_tools/src/dap_log.rs @@ -12,7 +12,7 @@ use gpui::{ actions, div, App, AppContext, Context, Empty, Entity, EventEmitter, FocusHandle, Focusable, IntoElement, ParentElement, Render, SharedString, Styled, Subscription, WeakEntity, Window, }; -use project::{search::SearchQuery, Project}; +use project::{debugger::client::Client, search::SearchQuery, Project}; use settings::Settings as _; use std::{ borrow::Cow, @@ -166,19 +166,17 @@ impl LogStore { this.projects.remove(&weak_project); }), cx.subscribe(project, |this, project, event, cx| match event { - project::Event::DebugClientStarted((_, client_id)) => { - this.add_debug_client( - *client_id, - project.update(cx, |project, cx| { - project.dap_store().update(cx, |store, cx| { - store.client_by_id(client_id, cx).and_then( - |(session, client)| { - Some((session, client.read(cx).adapter_client()?)) - }, - ) - }) - }), - ); + project::Event::DebugClientStarted(client_id) => { + let client = project.update(cx, |project, cx| { + project.dap_store().update(cx, |store, cx| { + store + .client_by_id(client_id) + .and_then(|client| Some(client)) + }) + }); + if let Some(client) = client { + this.add_debug_client(*client_id, client, cx); + } } project::Event::DebugClientShutdown(client_id) => { this.remove_debug_client(*client_id, cx); @@ -292,35 +290,35 @@ impl LogStore { fn add_debug_client( &mut self, client_id: DebugAdapterClientId, - session_and_client: Option<(Entity, Arc)>, + client: Entity, + cx: &App, ) -> Option<&mut DebugAdapterState> { let client_state = self .debug_clients .entry(client_id) .or_insert_with(DebugAdapterState::new); - if let Some((_, client)) = session_and_client { - let io_tx = self.rpc_tx.clone(); + let io_tx = self.rpc_tx.clone(); - client.add_log_handler( - move |io_kind, message| { - io_tx - .unbounded_send((client_id, io_kind, message.to_string())) - .ok(); - }, - LogKind::Rpc, - ); + let client = client.read(cx).adapter_client()?; + client.add_log_handler( + move |io_kind, message| { + io_tx + .unbounded_send((client_id, io_kind, message.to_string())) + .ok(); + }, + LogKind::Rpc, + ); - let log_io_tx = self.adapter_log_tx.clone(); - client.add_log_handler( - move |io_kind, message| { - log_io_tx - .unbounded_send((client_id, io_kind, message.to_string())) - .ok(); - }, - LogKind::Adapter, - ); - } + let log_io_tx = self.adapter_log_tx.clone(); + client.add_log_handler( + move |io_kind, message| { + log_io_tx + .unbounded_send((client_id, io_kind, message.to_string())) + .ok(); + }, + LogKind::Adapter, + ); Some(client_state) } diff --git a/crates/project/src/debugger/client.rs b/crates/project/src/debugger/client.rs index 25a668bd6f..76136df4ac 100644 --- a/crates/project/src/debugger/client.rs +++ b/crates/project/src/debugger/client.rs @@ -207,7 +207,7 @@ impl Mode { /// Represents a current state of a single debug adapter and provides ways to mutate it. pub struct Client { mode: Mode, - + config: DebugAdapterConfig, pub(super) capabilities: Capabilities, client_id: DebugAdapterClientId, ignore_breakpoints: bool, @@ -293,13 +293,14 @@ impl CompletionsQuery { } impl Client { - pub(crate) fn local(adapter: Arc, capabilities: Capabilities) -> Self { + pub(crate) fn local(adapter: Arc, config: DebugAdapterConfig) -> Self { let client_id = adapter.id(); Self { mode: Mode::Local(adapter), client_id, - capabilities, + config, + capabilities: unimplemented!(), ignore_breakpoints: false, requests: HashMap::default(), modules: Vec::default(), @@ -326,6 +327,7 @@ impl Client { modules: Vec::default(), loaded_sources: Vec::default(), threads: IndexMap::default(), + config: todo!(), } } @@ -333,7 +335,7 @@ impl Client { &self.capabilities } pub fn configuration(&self) -> DebugAdapterConfig { - DebugAdapterConfig::default() + self.config.clone() } pub(crate) fn _wait_for_request( diff --git a/crates/project/src/debugger/dap_store.rs b/crates/project/src/debugger/dap_store.rs index 1427fd0e24..0db48d2ed5 100644 --- a/crates/project/src/debugger/dap_store.rs +++ b/crates/project/src/debugger/dap_store.rs @@ -93,6 +93,109 @@ impl LocalDapStore { fn next_client_id(&self) -> DebugAdapterClientId { DebugAdapterClientId(self.next_client_id.fetch_add(1, SeqCst)) } + pub fn respond_to_start_debugging( + &mut self, + client: &Entity, + seq: u64, + args: Option, + cx: &mut Context, + ) -> Task> { + let config = client.read(cx).configuration(); + + let request_args = args.unwrap_or_else(|| StartDebuggingRequestArguments { + configuration: config.initialize_args.clone().unwrap_or_default(), + request: match config.request { + DebugRequestType::Launch => StartDebuggingRequestArgumentsRequest::Launch, + DebugRequestType::Attach(_) => StartDebuggingRequestArgumentsRequest::Attach, + }, + }); + + // Merge the new configuration over the existing configuration + let mut initialize_args = config.initialize_args.clone().unwrap_or_default(); + merge_json_value_into(request_args.configuration, &mut initialize_args); + + let new_config = DebugAdapterConfig { + label: config.label.clone(), + kind: config.kind.clone(), + request: match &request_args.request { + StartDebuggingRequestArgumentsRequest::Launch => DebugRequestType::Launch, + StartDebuggingRequestArgumentsRequest::Attach => DebugRequestType::Attach( + if let DebugRequestType::Attach(attach_config) = &config.request { + attach_config.clone() + } else { + AttachConfig::default() + }, + ), + }, + program: config.program.clone(), + cwd: config.cwd.clone(), + initialize_args: Some(initialize_args), + supports_attach: true, + }; + + cx.spawn(|this, mut cx| async move { + let (success, body) = { + let reconnect_task = this.update(&mut cx, |store, cx| { + if !unimplemented!("client.adapter().supports_attach()") + && matches!(new_config.request, DebugRequestType::Attach(_)) + { + Task::>::ready(Err(anyhow!( + "Debug adapter does not support `attach` request" + ))) + } else { + unimplemented!( + "store.reconnect_client(client.binary().clone(), new_config, cx)" + ); + } + }); + + match reconnect_task { + Ok(task) => match task.await { + Ok(_) => (true, None), + Err(error) => ( + false, + Some(serde_json::to_value(ErrorResponse { + error: Some(dap::Message { + id: seq, + format: error.to_string(), + variables: None, + send_telemetry: None, + show_user: None, + url: None, + url_label: None, + }), + })?), + ), + }, + Err(error) => ( + false, + Some(serde_json::to_value(ErrorResponse { + error: Some(dap::Message { + id: seq, + format: error.to_string(), + variables: None, + send_telemetry: None, + show_user: None, + url: None, + url_label: None, + }), + })?), + ), + } + }; + unimplemented!(); + Ok(()) + /*client + .send_message(Message::Response(Response { + seq, + body, + success, + request_seq: seq, + command: StartDebugging::COMMAND.to_string(), + })) + .await*/ + }) + } } pub struct RemoteDapStore { @@ -407,58 +510,58 @@ impl DapStore { } } - fn reconnect_client( - &mut self, - adapter: Arc, - binary: DebugAdapterBinary, - config: DebugAdapterConfig, - cx: &mut Context, - ) -> Task> { - if !adapter.supports_attach() && matches!(config.request, DebugRequestType::Attach(_)) { - return Task::ready(Err(anyhow!( - "Debug adapter does not support `attach` request" - ))); - } + // fn reconnect_client( + // &mut self, + // adapter: Arc, + // binary: DebugAdapterBinary, + // config: DebugAdapterConfig, + // cx: &mut Context, + // ) -> Task> { + // if !config.supports_attach && matches!(config.request, DebugRequestType::Attach(_)) { + // return Task::ready(Err(anyhow!( + // "Debug adapter does not support `attach` request" + // ))); + // } - let client_id = self.as_local().unwrap().next_client_id(); + // let client_id = self.as_local().unwrap().next_client_id(); - cx.spawn(|dap_store, mut cx| async move { - let mut client = DebugAdapterClient::new(client_id, adapter, binary, &cx); + // cx.spawn(|dap_store, mut cx| async move { + // let mut client = DebugAdapterClient::new(client_id, adapter, binary, &cx); - client - .reconnect( - { - let dap_store = dap_store.clone(); - move |message, cx| { - dap_store - .update(cx, |_, cx| { - cx.emit(DapStoreEvent::DebugClientEvent { client_id, message }) - }) - .log_err(); - } - }, - &mut cx, - ) - .await?; + // client + // .reconnect( + // { + // let dap_store = dap_store.clone(); + // move |message, cx| { + // dap_store + // .update(cx, |_, cx| { + // cx.emit(DapStoreEvent::DebugClientEvent { client_id, message }) + // }) + // .log_err(); + // } + // }, + // &mut cx, + // ) + // .await?; - dap_store.update(&mut cx, |store, cx| { - cx.new(|cx| { - let client_state = - debugger::client::Client::local(Arc::new(client), capabilities); - }); + // dap_store.update(&mut cx, |store, cx| { + // cx.new(|cx| { + // let client_state = + // debugger::client::Client::local(Arc::new(client), capabilities); + // }); - store.clients.insert(Arc::new(client), client_id); + // store.clients.insert(Arc::new(client), client_id); - // don't emit this event ourself in tests, so we can add request, - // response and event handlers for this client - if !cfg!(any(test, feature = "test-support")) { - cx.emit(DapStoreEvent::DebugClientStarted(client_id)); - } + // // don't emit this event ourself in tests, so we can add request, + // // response and event handlers for this client + // if !cfg!(any(test, feature = "test-support")) { + // cx.emit(DapStoreEvent::DebugClientStarted(client_id)); + // } - cx.notify(); - }) - }) - } + // cx.notify(); + // }) + // }) + // } fn start_client_internal( &mut self, @@ -475,7 +578,9 @@ impl DapStore { cx.spawn(|this, mut cx| async move { let adapter = build_adapter(&config.kind).await?; - if !adapter.supports_attach() && matches!(config.request, DebugRequestType::Attach(_)) { + if !unimplemented!("adapter.supports_attach()") + && matches!(config.request, DebugRequestType::Attach(_)) + { bail!("Debug adapter does not support `attach` request"); } @@ -577,7 +682,7 @@ impl DapStore { this.update(&mut cx, |store, cx| { let client_id = client.id(); - store.clients.insert(client_id, client); + unimplemented!("store.clients.insert(client_id, client);"); cx.emit(DapStoreEvent::DebugClientStarted(client_id)); cx.notify(); @@ -640,44 +745,38 @@ impl DapStore { } } - pub fn launch( + pub fn new_session( &mut self, - client_id: DebugAdapterClientId, + config: DebugAdapterConfig, cx: &mut Context, ) -> Task> { - let Some(client) = self - .client_by_id(client_id) - .and_then(|client| Some(client.read(cx).adapter_client()?)) - else { - return Task::ready(Err(anyhow!("Could not find debug client: {:?}", client_id))); - }; + // let config = session.read(cx).as_local().unwrap().configuration(); + // let mut adapter_args = client.adapter().request_args(&config); + // if let Some(args) = config.initialize_args.clone() { + // merge_json_value_into(args, &mut adapter_args); + // } - let config = session.read(cx).as_local().unwrap().configuration(); - let mut adapter_args = client.adapter().request_args(&config); - if let Some(args) = config.initialize_args.clone() { - merge_json_value_into(args, &mut adapter_args); - } + // // TODO(debugger): GDB starts the debuggee program on launch instead of configurationDone + // // causing our sent breakpoints to not be valid. This delay should eventually be taken out + // let delay = if &client.adapter_id() == "gdb" { + // Some( + // cx.background_executor() + // .timer(std::time::Duration::from_millis(20u64)), + // ) + // } else { + // None + // }; - // TODO(debugger): GDB starts the debuggee program on launch instead of configurationDone - // causing our sent breakpoints to not be valid. This delay should eventually be taken out - let delay = if &client.adapter_id() == "gdb" { - Some( - cx.background_executor() - .timer(std::time::Duration::from_millis(20u64)), - ) - } else { - None - }; + // cx.background_executor().spawn(async move { + // if let Some(delay) = delay { + // delay.await; + // } - cx.background_executor().spawn(async move { - if let Some(delay) = delay { - delay.await; - } - - client - .request::(LaunchRequestArguments { raw: adapter_args }) - .await - }) + // client + // .request::(LaunchRequestArguments { raw: adapter_args }) + // .await + // }) + Task::ready(Ok(())) } pub fn attach( @@ -686,157 +785,42 @@ impl DapStore { process_id: u32, cx: &mut Context, ) -> Task> { - let Some(client) = self - .client_by_id(client_id) - .and_then(|client| Some(client.read(cx).adapter_client()?)) - else { - return Task::ready(Err( - anyhow!("Could not find debug client: {:?}", client_id,), - )); - }; + unimplemented!(); + // let Some(client) = self + // .client_by_id(client_id) + // .and_then(|client| Some(client.read(cx).adapter_client()?)) + // else { + // return Task::ready(Err( + // anyhow!("Could not find debug client: {:?}", client_id,), + // )); + // }; - // update the process id on the config, so when the `startDebugging` reverse request - // comes in we send another `attach` request with the already selected PID - // If we don't do this the user has to select the process twice if the adapter sends a `startDebugging` request - session.update(cx, |session, cx| { - session.as_local_mut().unwrap().update_configuration( - |config| { - config.request = DebugRequestType::Attach(task::AttachConfig { - process_id: Some(process_id), - }); - }, - cx, - ); - }); + // // update the process id on the config, so when the `startDebugging` reverse request + // // comes in we send another `attach` request with the already selected PID + // // If we don't do this the user has to select the process twice if the adapter sends a `startDebugging` request + // session.update(cx, |session, cx| { + // session.as_local_mut().unwrap().update_configuration( + // |config| { + // config.request = DebugRequestType::Attach(task::AttachConfig { + // process_id: Some(process_id), + // }); + // }, + // cx, + // ); + // }); - let config = session.read(cx).as_local().unwrap().configuration(); - let mut adapter_args = client.adapter().request_args(&config); + // let config = session.read(cx).as_local().unwrap().configuration(); + // let mut adapter_args = client.adapter().request_args(&config); - if let Some(args) = config.initialize_args.clone() { - merge_json_value_into(args, &mut adapter_args); - } + // if let Some(args) = config.initialize_args.clone() { + // merge_json_value_into(args, &mut adapter_args); + // } - cx.background_executor().spawn(async move { - client - .request::(AttachRequestArguments { raw: adapter_args }) - .await - }) - } - - pub fn respond_to_start_debugging( - &mut self, - client_id: DebugAdapterClientId, - seq: u64, - args: Option, - cx: &mut Context, - ) -> Task> { - let Some((client, adapter)) = self - .client_by_id(client_id) - .and_then(|client| Some((client, client.read(cx).adapter_client()?))) - else { - return Task::ready(Err( - anyhow!("Could not find debug client: {:?}", client_id,), - )); - }; - - let config = client.read(cx).configuration(); - - let request_args = args.unwrap_or_else(|| StartDebuggingRequestArguments { - configuration: config.initialize_args.clone().unwrap_or_default(), - request: match config.request { - DebugRequestType::Launch => StartDebuggingRequestArgumentsRequest::Launch, - DebugRequestType::Attach(_) => StartDebuggingRequestArgumentsRequest::Attach, - }, - }); - - // Merge the new configuration over the existing configuration - let mut initialize_args = config.initialize_args.clone().unwrap_or_default(); - merge_json_value_into(request_args.configuration, &mut initialize_args); - - let new_config = DebugAdapterConfig { - label: config.label.clone(), - kind: config.kind.clone(), - request: match &request_args.request { - StartDebuggingRequestArgumentsRequest::Launch => DebugRequestType::Launch, - StartDebuggingRequestArgumentsRequest::Attach => DebugRequestType::Attach( - if let DebugRequestType::Attach(attach_config) = &config.request { - attach_config.clone() - } else { - AttachConfig::default() - }, - ), - }, - program: config.program.clone(), - cwd: config.cwd.clone(), - initialize_args: Some(initialize_args), - }; - - cx.spawn(|this, mut cx| async move { - let (success, body) = { - let reconnect_task = this.update(&mut cx, |store, cx| { - if !client.adapter().supports_attach() - && matches!(new_config.request, DebugRequestType::Attach(_)) - { - Task::ready(Err(anyhow!( - "Debug adapter does not support `attach` request" - ))) - } else { - store.reconnect_client(client.binary().clone(), new_config, cx) - } - }); - - match reconnect_task { - Ok(task) => match task.await { - Ok(_) => (true, None), - Err(error) => { - this.update(&mut cx, |_, cx| { - cx.emit(DapStoreEvent::Notification(error.to_string())); - }) - .log_err(); - - ( - false, - Some(serde_json::to_value(ErrorResponse { - error: Some(dap::Message { - id: seq, - format: error.to_string(), - variables: None, - send_telemetry: None, - show_user: None, - url: None, - url_label: None, - }), - })?), - ) - } - }, - Err(error) => ( - false, - Some(serde_json::to_value(ErrorResponse { - error: Some(dap::Message { - id: seq, - format: error.to_string(), - variables: None, - send_telemetry: None, - show_user: None, - url: None, - url_label: None, - }), - })?), - ), - } - }; - - client - .send_message(Message::Response(Response { - seq, - body, - success, - request_seq: seq, - command: StartDebugging::COMMAND.to_string(), - })) - .await - }) + // cx.background_executor().spawn(async move { + // client + // .request::(AttachRequestArguments { raw: adapter_args }) + // .await + // }) } pub fn respond_to_run_in_terminal( diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index c7b3f6b27f..e94aa6a084 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -1102,7 +1102,7 @@ impl Project { let mut dap_store = DapStore::new_remote(remote_id, client.clone().into(), breakpoint_store.clone()); - dap_store.request_active_debug_sessions(cx); + unimplemented!("dap_store.request_active_debug_sessions(cx)"); dap_store })?; diff --git a/crates/task/src/debug_format.rs b/crates/task/src/debug_format.rs index 1cd8492c54..f89728aa5e 100644 --- a/crates/task/src/debug_format.rs +++ b/crates/task/src/debug_format.rs @@ -131,6 +131,8 @@ pub struct DebugAdapterConfig { pub cwd: Option, /// Additional initialization arguments to be sent on DAP initialization pub initialize_args: Option, + /// Whether the debug adapter supports attaching to a running process. + pub supports_attach: bool, } /// Represents the type of the debugger adapter connection @@ -176,6 +178,7 @@ impl DebugTaskDefinition { program: self.program, cwd: cwd.clone(), initialize_args: self.initialize_args, + supports_attach: true, }); let args: Vec = Vec::new();