To make DAP work over SSH we want to create the binary at the project level (so we can wrap it in an `ssh` invocation transparently). This means not pushing the adapter down into the session, and resolving more information ahead-of-time. Co-authored-by: Anthony Eid <hello@anthonyeid.me> Co-authored-by: Piotr <piotr@zed.dev> Release Notes: - N/A ---------
Unified · Split
| @@ -3,13 +3,13 @@ use anyhow::{Context as _, Ok, Result, anyhow}; · 2 unmodified lines | ||
| 3 | 3 | use async_compression::futures::bufread::GzipDecoder; |
| 4 | 4 | use async_tar::Archive; |
| 5 | 5 | use async_trait::async_trait; |
| 6 | +use dap_types::StartDebuggingRequestArguments; | |
| 6 | 7 | use futures::io::BufReader; |
| 7 | 8 | use gpui::{AsyncApp, SharedString}; |
| 8 | 9 | pub use http_client::{HttpClient, github::latest_github_release}; |
| 9 | 10 | use language::LanguageToolchainStore; |
| 10 | 11 | use node_runtime::NodeRuntime; |
| 11 | 12 | use serde::{Deserialize, Serialize}; |
| 12 | −use serde_json::Value; | |
| 13 | 13 | use settings::WorktreeId; |
| 14 | 14 | use smol::{self, fs::File, lock::Mutex}; |
| 15 | 15 | use std::{ |
| @@ -22,7 +22,7 @@ use std::{ · 6 unmodified lines | ||
| 22 | 22 | path::PathBuf, |
| 23 | 23 | sync::Arc, |
| 24 | 24 | }; |
| 25 | −use task::{DebugAdapterConfig, DebugTaskDefinition}; | |
| 25 | +use task::DebugTaskDefinition; | |
| 26 | 26 | use util::ResultExt; |
| 27 | 27 | |
| 28 | 28 | #[derive(Clone, Debug, PartialEq, Eq)] |
| @@ -93,13 +93,15 @@ pub struct TcpArguments { · 64 unmodified lines | ||
| 93 | 93 | pub port: u16, |
| 94 | 94 | pub timeout: Option<u64>, |
| 95 | 95 | } |
| 96 | −#[derive(Default, Debug, Clone)] | |
| 96 | +#[derive(Debug, Clone)] | |
| 97 | 97 | pub struct DebugAdapterBinary { |
| 98 | + pub adapter_name: DebugAdapterName, | |
| 98 | 99 | pub command: String, |
| 99 | 100 | pub arguments: Option<Vec<OsString>>, |
| 100 | 101 | pub envs: Option<HashMap<String, String>>, |
| 101 | 102 | pub cwd: Option<PathBuf>, |
| 102 | 103 | pub connection: Option<TcpArguments>, |
| 104 | + pub request_args: StartDebuggingRequestArguments, | |
| 103 | 105 | } |
| 104 | 106 | |
| 105 | 107 | #[derive(Debug)] |
| @@ -220,7 +222,7 @@ pub trait DebugAdapter: 'static + Send + Sync { · 114 unmodified lines | ||
| 220 | 222 | async fn get_binary( |
| 221 | 223 | &self, |
| 222 | 224 | delegate: &dyn DapDelegate, |
| 223 | − config: &DebugAdapterConfig, | |
| 225 | + config: &DebugTaskDefinition, | |
| 224 | 226 | user_installed_path: Option<PathBuf>, |
| 225 | 227 | cx: &mut AsyncApp, |
| 226 | 228 | ) -> Result<DebugAdapterBinary> { |
| @@ -284,13 +286,10 @@ pub trait DebugAdapter: 'static + Send + Sync { · 57 unmodified lines | ||
| 284 | 286 | async fn get_installed_binary( |
| 285 | 287 | &self, |
| 286 | 288 | delegate: &dyn DapDelegate, |
| 287 | − config: &DebugAdapterConfig, | |
| 289 | + config: &DebugTaskDefinition, | |
| 288 | 290 | user_installed_path: Option<PathBuf>, |
| 289 | 291 | cx: &mut AsyncApp, |
| 290 | 292 | ) -> Result<DebugAdapterBinary>; |
| 291 | − | |
| 292 | − /// Should return base configuration to make the debug adapter work | |
| 293 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value; | |
| 294 | 293 | } |
| 295 | 294 | #[cfg(any(test, feature = "test-support"))] |
| 296 | 295 | pub struct FakeAdapter {} |
| @@ -302,6 +301,31 @@ impl FakeAdapter { · 5 unmodified lines | ||
| 302 | 301 | pub fn new() -> Self { |
| 303 | 302 | Self {} |
| 304 | 303 | } |
| 304 | + | |
| 305 | + fn request_args(&self, config: &DebugTaskDefinition) -> StartDebuggingRequestArguments { | |
| 306 | + use serde_json::json; | |
| 307 | + use task::DebugRequestType; | |
| 308 | + | |
| 309 | + let value = json!({ | |
| 310 | + "request": match config.request { | |
| 311 | + DebugRequestType::Launch(_) => "launch", | |
| 312 | + DebugRequestType::Attach(_) => "attach", | |
| 313 | + }, | |
| 314 | + "process_id": if let DebugRequestType::Attach(attach_config) = &config.request { | |
| 315 | + attach_config.process_id | |
| 316 | + } else { | |
| 317 | + None | |
| 318 | + }, | |
| 319 | + }); | |
| 320 | + let request = match config.request { | |
| 321 | + DebugRequestType::Launch(_) => dap_types::StartDebuggingRequestArgumentsRequest::Launch, | |
| 322 | + DebugRequestType::Attach(_) => dap_types::StartDebuggingRequestArgumentsRequest::Attach, | |
| 323 | + }; | |
| 324 | + StartDebuggingRequestArguments { | |
| 325 | + configuration: value, | |
| 326 | + request, | |
| 327 | + } | |
| 328 | + } | |
| 305 | 329 | } |
| 306 | 330 | |
| 307 | 331 | #[cfg(any(test, feature = "test-support"))] |
| @@ -314,16 +338,18 @@ impl DebugAdapter for FakeAdapter { · 6 unmodified lines | ||
| 314 | 338 | async fn get_binary( |
| 315 | 339 | &self, |
| 316 | 340 | _: &dyn DapDelegate, |
| 317 | − _: &DebugAdapterConfig, | |
| 341 | + config: &DebugTaskDefinition, | |
| 318 | 342 | _: Option<PathBuf>, |
| 319 | 343 | _: &mut AsyncApp, |
| 320 | 344 | ) -> Result<DebugAdapterBinary> { |
| 321 | 345 | Ok(DebugAdapterBinary { |
| 346 | + adapter_name: Self::ADAPTER_NAME.into(), | |
| 322 | 347 | command: "command".into(), |
| 323 | 348 | arguments: None, |
| 324 | 349 | connection: None, |
| 325 | 350 | envs: None, |
| 326 | 351 | cwd: None, |
| 352 | + request_args: self.request_args(config), | |
| 327 | 353 | }) |
| 328 | 354 | } |
| 329 | 355 | |
| @@ -345,27 +371,10 @@ impl DebugAdapter for FakeAdapter { · 15 unmodified lines | ||
| 345 | 371 | async fn get_installed_binary( |
| 346 | 372 | &self, |
| 347 | 373 | _: &dyn DapDelegate, |
| 348 | − _: &DebugAdapterConfig, | |
| 374 | + _: &DebugTaskDefinition, | |
| 349 | 375 | _: Option<PathBuf>, |
| 350 | 376 | _: &mut AsyncApp, |
| 351 | 377 | ) -> Result<DebugAdapterBinary> { |
| 352 | 378 | unimplemented!("get installed binary"); |
| 353 | 379 | } |
| 354 | − | |
| 355 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 356 | − use serde_json::json; | |
| 357 | − use task::DebugRequestType; | |
| 358 | − | |
| 359 | − json!({ | |
| 360 | − "request": match config.request { | |
| 361 | − DebugRequestType::Launch(_) => "launch", | |
| 362 | − DebugRequestType::Attach(_) => "attach", | |
| 363 | − }, | |
| 364 | − "process_id": if let DebugRequestType::Attach(attach_config) = &config.request { | |
| 365 | − attach_config.process_id | |
| 366 | − } else { | |
| 367 | − None | |
| 368 | − }, | |
| 369 | − }) | |
| 370 | − } | |
| 371 | 380 | } |
| @@ -39,7 +39,6 @@ impl SessionId { · 38 unmodified lines | ||
| 39 | 39 | /// Represents a connection to the debug adapter process, either via stdout/stdin or a socket. |
| 40 | 40 | pub struct DebugAdapterClient { |
| 41 | 41 | id: SessionId, |
| 42 | − name: DebugAdapterName, | |
| 43 | 42 | sequence_count: AtomicU64, |
| 44 | 43 | binary: DebugAdapterBinary, |
| 45 | 44 | executor: BackgroundExecutor, |
| @@ -51,7 +50,6 @@ pub type DapMessageHandler = Box<dyn FnMut(Message) + 'static + Send + Sync>; · 5 unmodified lines | ||
| 51 | 50 | impl DebugAdapterClient { |
| 52 | 51 | pub async fn start( |
| 53 | 52 | id: SessionId, |
| 54 | − name: DebugAdapterName, | |
| 55 | 53 | binary: DebugAdapterBinary, |
| 56 | 54 | message_handler: DapMessageHandler, |
| 57 | 55 | cx: AsyncApp, |
| @@ -60,7 +58,6 @@ impl DebugAdapterClient { · 2 unmodified lines | ||
| 60 | 58 | TransportDelegate::start(&binary, cx.clone()).await?; |
| 61 | 59 | let this = Self { |
| 62 | 60 | id, |
| 63 | − name, | |
| 64 | 61 | binary, |
| 65 | 62 | transport_delegate, |
| 66 | 63 | sequence_count: AtomicU64::new(1), |
| @@ -91,6 +88,7 @@ impl DebugAdapterClient { · 24 unmodified lines | ||
| 91 | 88 | ) -> Result<Self> { |
| 92 | 89 | let binary = match self.transport_delegate.transport() { |
| 93 | 90 | crate::transport::Transport::Tcp(tcp_transport) => DebugAdapterBinary { |
| 91 | + adapter_name: binary.adapter_name, | |
| 94 | 92 | command: binary.command, |
| 95 | 93 | arguments: binary.arguments, |
| 96 | 94 | envs: binary.envs, |
| @@ -100,11 +98,12 @@ impl DebugAdapterClient { · 3 unmodified lines | ||
| 100 | 98 | port: tcp_transport.port, |
| 101 | 99 | timeout: Some(tcp_transport.timeout), |
| 102 | 100 | }), |
| 101 | + request_args: binary.request_args, | |
| 103 | 102 | }, |
| 104 | 103 | _ => self.binary.clone(), |
| 105 | 104 | }; |
| 106 | 105 | |
| 107 | − Self::start(session_id, self.name(), binary, message_handler, cx).await | |
| 106 | + Self::start(session_id, binary, message_handler, cx).await | |
| 108 | 107 | } |
| 109 | 108 | |
| 110 | 109 | async fn handle_receive_messages( |
| @@ -189,7 +188,17 @@ impl DebugAdapterClient { · 78 unmodified lines | ||
| 189 | 188 | |
| 190 | 189 | let response = response??; |
| 191 | 190 | match response.success { |
| 192 | − true => Ok(serde_json::from_value(response.body.unwrap_or_default())?), | |
| 191 | + true => { | |
| 192 | + if let Some(json) = response.body { | |
| 193 | + Ok(serde_json::from_value(json)?) | |
| 194 | + // Note: dap types configure themselves to return `None` when an empty object is received, | |
| 195 | + // which then fails here... | |
| 196 | + } else if let Ok(result) = serde_json::from_value(serde_json::Value::Object(Default::default())) { | |
| 197 | + Ok(result) | |
| 198 | + } else { | |
| 199 | + Ok(serde_json::from_value(Default::default())?) | |
| 200 | + } | |
| 201 | + } | |
| 193 | 202 | false => Err(anyhow!("Request failed: {}", response.message.unwrap_or_default())), |
| 194 | 203 | } |
| 195 | 204 | } |
| @@ -211,7 +220,7 @@ impl DebugAdapterClient { · 15 unmodified lines | ||
| 211 | 220 | } |
| 212 | 221 | |
| 213 | 222 | pub fn name(&self) -> DebugAdapterName { |
| 214 | − self.name.clone() | |
| 223 | + self.binary.adapter_name.clone() | |
| 215 | 224 | } |
| 216 | 225 | pub fn binary(&self) -> &DebugAdapterBinary { |
| 217 | 226 | &self.binary |
| @@ -238,14 +247,14 @@ impl DebugAdapterClient { · 20 unmodified lines | ||
| 238 | 247 | } |
| 239 | 248 | |
| 240 | 249 | #[cfg(any(test, feature = "test-support"))] |
| 241 | − pub async fn on_request<R: dap_types::requests::Request, F>(&self, handler: F) | |
| 250 | + pub fn on_request<R: dap_types::requests::Request, F>(&self, handler: F) | |
| 242 | 251 | where |
| 243 | 252 | F: 'static |
| 244 | 253 | + Send |
| 245 | 254 | + FnMut(u64, R::Arguments) -> Result<R::Response, dap_types::ErrorResponse>, |
| 246 | 255 | { |
| 247 | 256 | let transport = self.transport_delegate.transport().as_fake(); |
| 248 | − transport.on_request::<R, F>(handler).await; | |
| 257 | + transport.on_request::<R, F>(handler); | |
| 249 | 258 | } |
| 250 | 259 | |
| 251 | 260 | #[cfg(any(test, feature = "test-support"))] |
| @@ -282,7 +291,7 @@ mod tests { · 30 unmodified lines | ||
| 282 | 291 | use crate::{client::DebugAdapterClient, debugger_settings::DebuggerSettings}; |
| 283 | 292 | use dap_types::{ |
| 284 | 293 | Capabilities, InitializeRequestArguments, InitializeRequestArgumentsPathFormat, |
| 285 | − RunInTerminalRequestArguments, | |
| 294 | + RunInTerminalRequestArguments, StartDebuggingRequestArguments, | |
| 286 | 295 | messages::Events, |
| 287 | 296 | requests::{Initialize, Request, RunInTerminal}, |
| 288 | 297 | }; |
| @@ -312,13 +321,17 @@ mod tests { · 23 unmodified lines | ||
| 312 | 321 | |
| 313 | 322 | let client = DebugAdapterClient::start( |
| 314 | 323 | crate::client::SessionId(1), |
| 315 | − DebugAdapterName("adapter".into()), | |
| 316 | 324 | DebugAdapterBinary { |
| 325 | + adapter_name: "adapter".into(), | |
| 317 | 326 | command: "command".into(), |
| 318 | 327 | arguments: Default::default(), |
| 319 | 328 | envs: Default::default(), |
| 320 | 329 | connection: None, |
| 321 | 330 | cwd: None, |
| 331 | + request_args: StartDebuggingRequestArguments { | |
| 332 | + configuration: serde_json::Value::Null, | |
| 333 | + request: dap_types::StartDebuggingRequestArgumentsRequest::Launch, | |
| 334 | + }, | |
| 322 | 335 | }, |
| 323 | 336 | Box::new(|_| panic!("Did not expect to hit this code path")), |
| 324 | 337 | cx.to_async(), |
| @@ -326,14 +339,12 @@ mod tests { · 1 unmodified line | ||
| 326 | 339 | .await |
| 327 | 340 | .unwrap(); |
| 328 | 341 | |
| 329 | − client | |
| 330 | − .on_request::<Initialize, _>(move |_, _| { | |
| 331 | − Ok(dap_types::Capabilities { | |
| 332 | − supports_configuration_done_request: Some(true), | |
| 333 | − ..Default::default() | |
| 334 | − }) | |
| 342 | + client.on_request::<Initialize, _>(move |_, _| { | |
| 343 | + Ok(dap_types::Capabilities { | |
| 344 | + supports_configuration_done_request: Some(true), | |
| 345 | + ..Default::default() | |
| 335 | 346 | }) |
| 336 | − .await; | |
| 347 | + }); | |
| 337 | 348 | |
| 338 | 349 | cx.run_until_parked(); |
| 339 | 350 | |
| @@ -381,13 +392,17 @@ mod tests { · 41 unmodified lines | ||
| 381 | 392 | |
| 382 | 393 | let client = DebugAdapterClient::start( |
| 383 | 394 | crate::client::SessionId(1), |
| 384 | − DebugAdapterName("adapter".into()), | |
| 385 | 395 | DebugAdapterBinary { |
| 396 | + adapter_name: "adapter".into(), | |
| 386 | 397 | command: "command".into(), |
| 387 | 398 | arguments: Default::default(), |
| 388 | 399 | envs: Default::default(), |
| 389 | 400 | connection: None, |
| 390 | 401 | cwd: None, |
| 402 | + request_args: StartDebuggingRequestArguments { | |
| 403 | + configuration: serde_json::Value::Null, | |
| 404 | + request: dap_types::StartDebuggingRequestArgumentsRequest::Launch, | |
| 405 | + }, | |
| 391 | 406 | }, |
| 392 | 407 | Box::new({ |
| 393 | 408 | let called_event_handler = called_event_handler.clone(); |
| @@ -431,13 +446,17 @@ mod tests { · 37 unmodified lines | ||
| 431 | 446 | |
| 432 | 447 | let client = DebugAdapterClient::start( |
| 433 | 448 | crate::client::SessionId(1), |
| 434 | − DebugAdapterName("test-adapter".into()), | |
| 435 | 449 | DebugAdapterBinary { |
| 450 | + adapter_name: "test-adapter".into(), | |
| 436 | 451 | command: "command".into(), |
| 437 | 452 | arguments: Default::default(), |
| 438 | 453 | envs: Default::default(), |
| 439 | 454 | connection: None, |
| 440 | 455 | cwd: None, |
| 456 | + request_args: dap_types::StartDebuggingRequestArguments { | |
| 457 | + configuration: serde_json::Value::Null, | |
| 458 | + request: dap_types::StartDebuggingRequestArgumentsRequest::Launch, | |
| 459 | + }, | |
| 441 | 460 | }, |
| 442 | 461 | Box::new({ |
| 443 | 462 | let called_event_handler = called_event_handler.clone(); |
| @@ -699,14 +699,8 @@ impl StdioTransport { · 698 unmodified lines | ||
| 699 | 699 | } |
| 700 | 700 | |
| 701 | 701 | #[cfg(any(test, feature = "test-support"))] |
| 702 | −type RequestHandler = Box< | |
| 703 | − dyn Send | |
| 704 | − + FnMut( | |
| 705 | − u64, | |
| 706 | − serde_json::Value, | |
| 707 | − Arc<Mutex<async_pipe::PipeWriter>>, | |
| 708 | − ) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>>, | |
| 709 | −>; | |
| 702 | +type RequestHandler = | |
| 703 | + Box<dyn Send + FnMut(u64, serde_json::Value) -> dap_types::messages::Response>; | |
| 710 | 704 | |
| 711 | 705 | #[cfg(any(test, feature = "test-support"))] |
| 712 | 706 | type ResponseHandler = Box<dyn Send + Fn(Response)>; |
| @@ -714,45 +708,41 @@ type ResponseHandler = Box<dyn Send + Fn(Response)>; · 1 unmodified line | ||
| 714 | 708 | #[cfg(any(test, feature = "test-support"))] |
| 715 | 709 | pub struct FakeTransport { |
| 716 | 710 | // for sending fake response back from adapter side |
| 717 | − request_handlers: Arc<Mutex<HashMap<&'static str, RequestHandler>>>, | |
| 711 | + request_handlers: Arc<parking_lot::Mutex<HashMap<&'static str, RequestHandler>>>, | |
| 718 | 712 | // for reverse request responses |
| 719 | − response_handlers: Arc<Mutex<HashMap<&'static str, ResponseHandler>>>, | |
| 713 | + response_handlers: Arc<parking_lot::Mutex<HashMap<&'static str, ResponseHandler>>>, | |
| 720 | 714 | } |
| 721 | 715 | |
| 722 | 716 | #[cfg(any(test, feature = "test-support"))] |
| 723 | 717 | impl FakeTransport { |
| 724 | − pub async fn on_request<R: dap_types::requests::Request, F>(&self, mut handler: F) | |
| 718 | + pub fn on_request<R: dap_types::requests::Request, F>(&self, mut handler: F) | |
| 725 | 719 | where |
| 726 | 720 | F: 'static + Send + FnMut(u64, R::Arguments) -> Result<R::Response, ErrorResponse>, |
| 727 | 721 | { |
| 728 | − self.request_handlers.lock().await.insert( | |
| 722 | + self.request_handlers.lock().insert( | |
| 729 | 723 | R::COMMAND, |
| 730 | − Box::new( | |
| 731 | − move |seq, args, writer: Arc<Mutex<async_pipe::PipeWriter>>| { | |
| 732 | − let response = handler(seq, serde_json::from_value(args).unwrap()); | |
| 733 | − | |
| 734 | − let message = serde_json::to_string(&Message::Response(Response { | |
| 724 | + Box::new(move |seq, args| { | |
| 725 | + let result = handler(seq, serde_json::from_value(args).unwrap()); | |
| 726 | + let response = match result { | |
| 727 | + Ok(response) => Response { | |
| 735 | 728 | seq: seq + 1, |
| 736 | 729 | request_seq: seq, |
| 737 | − success: response.as_ref().is_ok(), | |
| 730 | + success: true, | |
| 738 | 731 | command: R::COMMAND.into(), |
| 739 | − body: util::maybe!({ serde_json::to_value(response.ok()?).ok() }), | |
| 732 | + body: Some(serde_json::to_value(response).unwrap()), | |
| 740 | 733 | message: None, |
| 741 | − })) | |
| 742 | − .unwrap(); | |
| 743 | − | |
| 744 | − let writer = writer.clone(); | |
| 745 | − | |
| 746 | − Box::pin(async move { | |
| 747 | − let mut writer = writer.lock().await; | |
| 748 | − writer | |
| 749 | − .write_all(TransportDelegate::build_rpc_message(message).as_bytes()) | |
| 750 | − .await | |
| 751 | − .unwrap(); | |
| 752 | − writer.flush().await.unwrap(); | |
| 753 | − }) | |
| 754 | − }, | |
| 755 | − ), | |
| 734 | + }, | |
| 735 | + Err(response) => Response { | |
| 736 | + seq: seq + 1, | |
| 737 | + request_seq: seq, | |
| 738 | + success: false, | |
| 739 | + command: R::COMMAND.into(), | |
| 740 | + body: Some(serde_json::to_value(response).unwrap()), | |
| 741 | + message: None, | |
| 742 | + }, | |
| 743 | + }; | |
| 744 | + response | |
| 745 | + }), | |
| 756 | 746 | ); |
| 757 | 747 | } |
| 758 | 748 | |
| @@ -762,14 +752,13 @@ impl FakeTransport { · 3 unmodified lines | ||
| 762 | 752 | { |
| 763 | 753 | self.response_handlers |
| 764 | 754 | .lock() |
| 765 | − .await | |
| 766 | 755 | .insert(R::COMMAND, Box::new(handler)); |
| 767 | 756 | } |
| 768 | 757 | |
| 769 | 758 | async fn start(cx: AsyncApp) -> Result<(TransportPipe, Self)> { |
| 770 | 759 | let this = Self { |
| 771 | − request_handlers: Arc::new(Mutex::new(HashMap::default())), | |
| 772 | − response_handlers: Arc::new(Mutex::new(HashMap::default())), | |
| 760 | + request_handlers: Arc::new(parking_lot::Mutex::new(HashMap::default())), | |
| 761 | + response_handlers: Arc::new(parking_lot::Mutex::new(HashMap::default())), | |
| 773 | 762 | }; |
| 774 | 763 | use dap_types::requests::{Request, RunInTerminal, StartDebugging}; |
| 775 | 764 | use serde_json::json; |
| @@ -816,23 +805,31 @@ impl FakeTransport { · 40 unmodified lines | ||
| 816 | 805 | .unwrap(); |
| 817 | 806 | writer.flush().await.unwrap(); |
| 818 | 807 | } else { |
| 819 | − if let Some(handle) = request_handlers | |
| 808 | + let response = if let Some(handle) = request_handlers | |
| 820 | 809 | .lock() |
| 821 | − .await | |
| 822 | 810 | .get_mut(request.command.as_str()) |
| 823 | 811 | { |
| 824 | 812 | handle( |
| 825 | 813 | request.seq, |
| 826 | 814 | request.arguments.unwrap_or(json!({})), |
| 827 | − stdout_writer.clone(), | |
| 828 | 815 | ) |
| 829 | − .await; | |
| 830 | 816 | } else { |
| 831 | − log::error!( | |
| 832 | − "No request handler for {}", | |
| 833 | − request.command | |
| 834 | − ); | |
| 835 | − } | |
| 817 | + panic!("No request handler for {}", request.command); | |
| 818 | + }; | |
| 819 | + let message = | |
| 820 | + serde_json::to_string(&Message::Response(response)) | |
| 821 | + .unwrap(); | |
| 822 | + | |
| 823 | + let mut writer = stdout_writer.lock().await; | |
| 824 | + | |
| 825 | + writer | |
| 826 | + .write_all( | |
| 827 | + TransportDelegate::build_rpc_message(message) | |
| 828 | + .as_bytes(), | |
| 829 | + ) | |
| 830 | + .await | |
| 831 | + .unwrap(); | |
| 832 | + writer.flush().await.unwrap(); | |
| 836 | 833 | } |
| 837 | 834 | } |
| 838 | 835 | Message::Event(event) => { |
| @@ -850,10 +847,8 @@ impl FakeTransport { · 11 unmodified lines | ||
| 850 | 847 | writer.flush().await.unwrap(); |
| 851 | 848 | } |
| 852 | 849 | Message::Response(response) => { |
| 853 | − if let Some(handle) = response_handlers | |
| 854 | − .lock() | |
| 855 | − .await | |
| 856 | − .get(response.command.as_str()) | |
| 850 | + if let Some(handle) = | |
| 851 | + response_handlers.lock().get(response.command.as_str()) | |
| 857 | 852 | { |
| 858 | 853 | handle(response); |
| 859 | 854 | } else { |
| @@ -4,7 +4,7 @@ use anyhow::{Result, bail}; · 3 unmodified lines | ||
| 4 | 4 | use async_trait::async_trait; |
| 5 | 5 | use dap::adapters::latest_github_release; |
| 6 | 6 | use gpui::AsyncApp; |
| 7 | −use task::{DebugAdapterConfig, DebugRequestType, DebugTaskDefinition}; | |
| 7 | +use task::{DebugRequestType, DebugTaskDefinition}; | |
| 8 | 8 | |
| 9 | 9 | use crate::*; |
| 10 | 10 | |
| @@ -15,6 +15,42 @@ pub(crate) struct CodeLldbDebugAdapter { · 4 unmodified lines | ||
| 15 | 15 | |
| 16 | 16 | impl CodeLldbDebugAdapter { |
| 17 | 17 | const ADAPTER_NAME: &'static str = "CodeLLDB"; |
| 18 | + | |
| 19 | + fn request_args(&self, config: &DebugTaskDefinition) -> dap::StartDebuggingRequestArguments { | |
| 20 | + let mut configuration = json!({ | |
| 21 | + "request": match config.request { | |
| 22 | + DebugRequestType::Launch(_) => "launch", | |
| 23 | + DebugRequestType::Attach(_) => "attach", | |
| 24 | + }, | |
| 25 | + }); | |
| 26 | + let map = configuration.as_object_mut().unwrap(); | |
| 27 | + // CodeLLDB uses `name` for a terminal label. | |
| 28 | + map.insert("name".into(), Value::String(config.label.clone())); | |
| 29 | + let request = config.request.to_dap(); | |
| 30 | + match &config.request { | |
| 31 | + DebugRequestType::Attach(attach) => { | |
| 32 | + map.insert("pid".into(), attach.process_id.into()); | |
| 33 | + } | |
| 34 | + DebugRequestType::Launch(launch) => { | |
| 35 | + map.insert("program".into(), launch.program.clone().into()); | |
| 36 | + | |
| 37 | + if !launch.args.is_empty() { | |
| 38 | + map.insert("args".into(), launch.args.clone().into()); | |
| 39 | + } | |
| 40 | + | |
| 41 | + if let Some(stop_on_entry) = config.stop_on_entry { | |
| 42 | + map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 43 | + } | |
| 44 | + if let Some(cwd) = launch.cwd.as_ref() { | |
| 45 | + map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 46 | + } | |
| 47 | + } | |
| 48 | + } | |
| 49 | + dap::StartDebuggingRequestArguments { | |
| 50 | + request, | |
| 51 | + configuration, | |
| 52 | + } | |
| 53 | + } | |
| 18 | 54 | } |
| 19 | 55 | |
| 20 | 56 | #[async_trait(?Send)] |
| @@ -86,7 +122,7 @@ impl DebugAdapter for CodeLldbDebugAdapter { · 65 unmodified lines | ||
| 86 | 122 | async fn get_installed_binary( |
| 87 | 123 | &self, |
| 88 | 124 | _: &dyn DapDelegate, |
| 89 | − _: &DebugAdapterConfig, | |
| 125 | + config: &DebugTaskDefinition, | |
| 90 | 126 | _: Option<PathBuf>, |
| 91 | 127 | _: &mut AsyncApp, |
| 92 | 128 | ) -> Result<DebugAdapterBinary> { |
| @@ -111,39 +147,10 @@ impl DebugAdapter for CodeLldbDebugAdapter { · 18 unmodified lines | ||
| 111 | 147 | .to_string() |
| 112 | 148 | .into(), |
| 113 | 149 | ]), |
| 114 | − ..Default::default() | |
| 150 | + request_args: self.request_args(config), | |
| 151 | + adapter_name: "test".into(), | |
| 152 | + envs: None, | |
| 153 | + connection: None, | |
| 115 | 154 | }) |
| 116 | 155 | } |
| 117 | − | |
| 118 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 119 | − let mut args = json!({ | |
| 120 | − "request": match config.request { | |
| 121 | − DebugRequestType::Launch(_) => "launch", | |
| 122 | − DebugRequestType::Attach(_) => "attach", | |
| 123 | − }, | |
| 124 | − }); | |
| 125 | − let map = args.as_object_mut().unwrap(); | |
| 126 | − // CodeLLDB uses `name` for a terminal label. | |
| 127 | − map.insert("name".into(), Value::String(config.label.clone())); | |
| 128 | − match &config.request { | |
| 129 | − DebugRequestType::Attach(attach) => { | |
| 130 | − map.insert("pid".into(), attach.process_id.into()); | |
| 131 | − } | |
| 132 | − DebugRequestType::Launch(launch) => { | |
| 133 | − map.insert("program".into(), launch.program.clone().into()); | |
| 134 | − | |
| 135 | − if !launch.args.is_empty() { | |
| 136 | − map.insert("args".into(), launch.args.clone().into()); | |
| 137 | − } | |
| 138 | − | |
| 139 | − if let Some(stop_on_entry) = config.stop_on_entry { | |
| 140 | − map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 141 | − } | |
| 142 | − if let Some(cwd) = launch.cwd.as_ref() { | |
| 143 | − map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 144 | − } | |
| 145 | − } | |
| 146 | − } | |
| 147 | − args | |
| 148 | − } | |
| 149 | 156 | } |
| @@ -12,7 +12,7 @@ use anyhow::{Result, anyhow}; · 11 unmodified lines | ||
| 12 | 12 | use async_trait::async_trait; |
| 13 | 13 | use codelldb::CodeLldbDebugAdapter; |
| 14 | 14 | use dap::{ |
| 15 | − DapRegistry, | |
| 15 | + DapRegistry, DebugRequestType, | |
| 16 | 16 | adapters::{ |
| 17 | 17 | self, AdapterVersion, DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName, |
| 18 | 18 | GithubRepo, |
| @@ -25,7 +25,7 @@ use lldb::LldbDebugAdapter; · 6 unmodified lines | ||
| 25 | 25 | use php::PhpDebugAdapter; |
| 26 | 26 | use python::PythonDebugAdapter; |
| 27 | 27 | use serde_json::{Value, json}; |
| 28 | −use task::{DebugAdapterConfig, TCPHost}; | |
| 28 | +use task::TCPHost; | |
| 29 | 29 | |
| 30 | 30 | pub fn init(registry: Arc<DapRegistry>) { |
| 31 | 31 | registry.add_adapter(Arc::from(CodeLldbDebugAdapter::default())); |
| @@ -51,3 +51,16 @@ pub(crate) async fn configure_tcp_connection( · 19 unmodified lines | ||
| 51 | 51 | |
| 52 | 52 | Ok((host, port, timeout)) |
| 53 | 53 | } |
| 54 | + | |
| 55 | +trait ToDap { | |
| 56 | + fn to_dap(&self) -> dap::StartDebuggingRequestArgumentsRequest; | |
| 57 | +} | |
| 58 | + | |
| 59 | +impl ToDap for DebugRequestType { | |
| 60 | + fn to_dap(&self) -> dap::StartDebuggingRequestArgumentsRequest { | |
| 61 | + match self { | |
| 62 | + Self::Launch(_) => dap::StartDebuggingRequestArgumentsRequest::Launch, | |
| 63 | + Self::Attach(_) => dap::StartDebuggingRequestArgumentsRequest::Attach, | |
| 64 | + } | |
| 65 | + } | |
| 66 | +} | |
| @@ -2,8 +2,9 @@ use std::ffi::OsStr; · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | use anyhow::{Result, bail}; |
| 4 | 4 | use async_trait::async_trait; |
| 5 | +use dap::StartDebuggingRequestArguments; | |
| 5 | 6 | use gpui::AsyncApp; |
| 6 | −use task::{DebugAdapterConfig, DebugRequestType, DebugTaskDefinition}; | |
| 7 | +use task::{DebugRequestType, DebugTaskDefinition}; | |
| 7 | 8 | |
| 8 | 9 | use crate::*; |
| 9 | 10 | |
| @@ -12,6 +13,44 @@ pub(crate) struct GdbDebugAdapter; · 2 unmodified lines | ||
| 12 | 13 | |
| 13 | 14 | impl GdbDebugAdapter { |
| 14 | 15 | const ADAPTER_NAME: &'static str = "GDB"; |
| 16 | + | |
| 17 | + fn request_args(&self, config: &DebugTaskDefinition) -> StartDebuggingRequestArguments { | |
| 18 | + let mut args = json!({ | |
| 19 | + "request": match config.request { | |
| 20 | + DebugRequestType::Launch(_) => "launch", | |
| 21 | + DebugRequestType::Attach(_) => "attach", | |
| 22 | + }, | |
| 23 | + }); | |
| 24 | + | |
| 25 | + let map = args.as_object_mut().unwrap(); | |
| 26 | + match &config.request { | |
| 27 | + DebugRequestType::Attach(attach) => { | |
| 28 | + map.insert("pid".into(), attach.process_id.into()); | |
| 29 | + } | |
| 30 | + | |
| 31 | + DebugRequestType::Launch(launch) => { | |
| 32 | + map.insert("program".into(), launch.program.clone().into()); | |
| 33 | + | |
| 34 | + if !launch.args.is_empty() { | |
| 35 | + map.insert("args".into(), launch.args.clone().into()); | |
| 36 | + } | |
| 37 | + | |
| 38 | + if let Some(stop_on_entry) = config.stop_on_entry { | |
| 39 | + map.insert( | |
| 40 | + "stopAtBeginningOfMainSubprogram".into(), | |
| 41 | + stop_on_entry.into(), | |
| 42 | + ); | |
| 43 | + } | |
| 44 | + if let Some(cwd) = launch.cwd.as_ref() { | |
| 45 | + map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 46 | + } | |
| 47 | + } | |
| 48 | + } | |
| 49 | + StartDebuggingRequestArguments { | |
| 50 | + configuration: args, | |
| 51 | + request: config.request.to_dap(), | |
| 52 | + } | |
| 53 | + } | |
| 15 | 54 | } |
| 16 | 55 | |
| 17 | 56 | #[async_trait(?Send)] |
| @@ -23,7 +62,7 @@ impl DebugAdapter for GdbDebugAdapter { · 5 unmodified lines | ||
| 23 | 62 | async fn get_binary( |
| 24 | 63 | &self, |
| 25 | 64 | delegate: &dyn DapDelegate, |
| 26 | − _: &DebugAdapterConfig, | |
| 65 | + config: &DebugTaskDefinition, | |
| 27 | 66 | user_installed_path: Option<std::path::PathBuf>, |
| 28 | 67 | _: &mut AsyncApp, |
| 29 | 68 | ) -> Result<DebugAdapterBinary> { |
| @@ -43,11 +82,13 @@ impl DebugAdapter for GdbDebugAdapter { · 13 unmodified lines | ||
| 43 | 82 | let gdb_path = user_setting_path.unwrap_or(gdb_path?); |
| 44 | 83 | |
| 45 | 84 | Ok(DebugAdapterBinary { |
| 85 | + adapter_name: Self::ADAPTER_NAME.into(), | |
| 46 | 86 | command: gdb_path, |
| 47 | 87 | arguments: Some(vec!["-i=dap".into()]), |
| 48 | 88 | envs: None, |
| 49 | 89 | cwd: None, |
| 50 | 90 | connection: None, |
| 91 | + request_args: self.request_args(config), | |
| 51 | 92 | }) |
| 52 | 93 | } |
| 53 | 94 | |
| @@ -66,45 +107,10 @@ impl DebugAdapter for GdbDebugAdapter { · 12 unmodified lines | ||
| 66 | 107 | async fn get_installed_binary( |
| 67 | 108 | &self, |
| 68 | 109 | _: &dyn DapDelegate, |
| 69 | − _: &DebugAdapterConfig, | |
| 110 | + _: &DebugTaskDefinition, | |
| 70 | 111 | _: Option<std::path::PathBuf>, |
| 71 | 112 | _: &mut AsyncApp, |
| 72 | 113 | ) -> Result<DebugAdapterBinary> { |
| 73 | 114 | unimplemented!("GDB cannot be installed by Zed (yet)") |
| 74 | 115 | } |
| 75 | − | |
| 76 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 77 | − let mut args = json!({ | |
| 78 | − "request": match config.request { | |
| 79 | − DebugRequestType::Launch(_) => "launch", | |
| 80 | − DebugRequestType::Attach(_) => "attach", | |
| 81 | − }, | |
| 82 | − }); | |
| 83 | − | |
| 84 | − let map = args.as_object_mut().unwrap(); | |
| 85 | − match &config.request { | |
| 86 | − DebugRequestType::Attach(attach) => { | |
| 87 | − map.insert("pid".into(), attach.process_id.into()); | |
| 88 | − } | |
| 89 | − | |
| 90 | − DebugRequestType::Launch(launch) => { | |
| 91 | − map.insert("program".into(), launch.program.clone().into()); | |
| 92 | − | |
| 93 | − if !launch.args.is_empty() { | |
| 94 | − map.insert("args".into(), launch.args.clone().into()); | |
| 95 | − } | |
| 96 | − | |
| 97 | − if let Some(stop_on_entry) = config.stop_on_entry { | |
| 98 | − map.insert( | |
| 99 | − "stopAtBeginningOfMainSubprogram".into(), | |
| 100 | − stop_on_entry.into(), | |
| 101 | − ); | |
| 102 | − } | |
| 103 | − if let Some(cwd) = launch.cwd.as_ref() { | |
| 104 | − map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 105 | − } | |
| 106 | − } | |
| 107 | − } | |
| 108 | − args | |
| 109 | − } | |
| 110 | 116 | } |
| @@ -1,3 +1,4 @@ | ||
| 1 | +use dap::StartDebuggingRequestArguments; | |
| 1 | 2 | use gpui::AsyncApp; |
| 2 | 3 | use std::{ffi::OsStr, path::PathBuf}; |
| 3 | 4 | use task::DebugTaskDefinition; |
| @@ -9,6 +10,31 @@ pub(crate) struct GoDebugAdapter; · 5 unmodified lines | ||
| 9 | 10 | |
| 10 | 11 | impl GoDebugAdapter { |
| 11 | 12 | const ADAPTER_NAME: &'static str = "Delve"; |
| 13 | + fn request_args(&self, config: &DebugTaskDefinition) -> StartDebuggingRequestArguments { | |
| 14 | + let mut args = match &config.request { | |
| 15 | + dap::DebugRequestType::Attach(attach_config) => { | |
| 16 | + json!({ | |
| 17 | + "processId": attach_config.process_id, | |
| 18 | + }) | |
| 19 | + } | |
| 20 | + dap::DebugRequestType::Launch(launch_config) => json!({ | |
| 21 | + "program": launch_config.program, | |
| 22 | + "cwd": launch_config.cwd, | |
| 23 | + "args": launch_config.args | |
| 24 | + }), | |
| 25 | + }; | |
| 26 | + | |
| 27 | + let map = args.as_object_mut().unwrap(); | |
| 28 | + | |
| 29 | + if let Some(stop_on_entry) = config.stop_on_entry { | |
| 30 | + map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 31 | + } | |
| 32 | + | |
| 33 | + StartDebuggingRequestArguments { | |
| 34 | + configuration: args, | |
| 35 | + request: config.request.to_dap(), | |
| 36 | + } | |
| 37 | + } | |
| 12 | 38 | } |
| 13 | 39 | |
| 14 | 40 | #[async_trait(?Send)] |
| @@ -20,7 +46,7 @@ impl DebugAdapter for GoDebugAdapter { · 5 unmodified lines | ||
| 20 | 46 | async fn get_binary( |
| 21 | 47 | &self, |
| 22 | 48 | delegate: &dyn DapDelegate, |
| 23 | − config: &DebugAdapterConfig, | |
| 49 | + config: &DebugTaskDefinition, | |
| 24 | 50 | user_installed_path: Option<PathBuf>, |
| 25 | 51 | cx: &mut AsyncApp, |
| 26 | 52 | ) -> Result<DebugAdapterBinary> { |
| @@ -53,7 +79,7 @@ impl DebugAdapter for GoDebugAdapter { · 26 unmodified lines | ||
| 53 | 79 | async fn get_installed_binary( |
| 54 | 80 | &self, |
| 55 | 81 | delegate: &dyn DapDelegate, |
| 56 | − config: &DebugAdapterConfig, | |
| 82 | + config: &DebugTaskDefinition, | |
| 57 | 83 | _: Option<PathBuf>, |
| 58 | 84 | _: &mut AsyncApp, |
| 59 | 85 | ) -> Result<DebugAdapterBinary> { |
| @@ -66,6 +92,7 @@ impl DebugAdapter for GoDebugAdapter { · 6 unmodified lines | ||
| 66 | 92 | let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?; |
| 67 | 93 | |
| 68 | 94 | Ok(DebugAdapterBinary { |
| 95 | + adapter_name: self.name(), | |
| 69 | 96 | command: delve_path, |
| 70 | 97 | arguments: Some(vec![ |
| 71 | 98 | "dap".into(), |
| @@ -79,29 +106,7 @@ impl DebugAdapter for GoDebugAdapter { · 7 unmodified lines | ||
| 79 | 106 | port, |
| 80 | 107 | timeout, |
| 81 | 108 | }), |
| 109 | + request_args: self.request_args(config), | |
| 82 | 110 | }) |
| 83 | 111 | } |
| 84 | − | |
| 85 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 86 | − let mut args = match &config.request { | |
| 87 | − dap::DebugRequestType::Attach(attach_config) => { | |
| 88 | − json!({ | |
| 89 | − "processId": attach_config.process_id, | |
| 90 | − }) | |
| 91 | − } | |
| 92 | − dap::DebugRequestType::Launch(launch_config) => json!({ | |
| 93 | − "program": launch_config.program, | |
| 94 | − "cwd": launch_config.cwd, | |
| 95 | − "args": launch_config.args | |
| 96 | − }), | |
| 97 | − }; | |
| 98 | − | |
| 99 | − let map = args.as_object_mut().unwrap(); | |
| 100 | − | |
| 101 | − if let Some(stop_on_entry) = config.stop_on_entry { | |
| 102 | − map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 103 | − } | |
| 104 | − | |
| 105 | − args | |
| 106 | − } | |
| 107 | 112 | } |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | use adapters::latest_github_release; |
| 2 | +use dap::StartDebuggingRequestArguments; | |
| 2 | 3 | use gpui::AsyncApp; |
| 3 | 4 | use std::path::PathBuf; |
| 4 | 5 | use task::{DebugRequestType, DebugTaskDefinition}; |
| @@ -12,6 +13,40 @@ impl JsDebugAdapter { · 7 unmodified lines | ||
| 12 | 13 | const ADAPTER_NAME: &'static str = "JavaScript"; |
| 13 | 14 | const ADAPTER_NPM_NAME: &'static str = "vscode-js-debug"; |
| 14 | 15 | const ADAPTER_PATH: &'static str = "js-debug/src/dapDebugServer.js"; |
| 16 | + | |
| 17 | + fn request_args(&self, config: &DebugTaskDefinition) -> StartDebuggingRequestArguments { | |
| 18 | + let mut args = json!({ | |
| 19 | + "type": "pwa-node", | |
| 20 | + "request": match config.request { | |
| 21 | + DebugRequestType::Launch(_) => "launch", | |
| 22 | + DebugRequestType::Attach(_) => "attach", | |
| 23 | + }, | |
| 24 | + }); | |
| 25 | + let map = args.as_object_mut().unwrap(); | |
| 26 | + match &config.request { | |
| 27 | + DebugRequestType::Attach(attach) => { | |
| 28 | + map.insert("processId".into(), attach.process_id.into()); | |
| 29 | + } | |
| 30 | + DebugRequestType::Launch(launch) => { | |
| 31 | + map.insert("program".into(), launch.program.clone().into()); | |
| 32 | + | |
| 33 | + if !launch.args.is_empty() { | |
| 34 | + map.insert("args".into(), launch.args.clone().into()); | |
| 35 | + } | |
| 36 | + | |
| 37 | + if let Some(stop_on_entry) = config.stop_on_entry { | |
| 38 | + map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 39 | + } | |
| 40 | + if let Some(cwd) = launch.cwd.as_ref() { | |
| 41 | + map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 42 | + } | |
| 43 | + } | |
| 44 | + } | |
| 45 | + StartDebuggingRequestArguments { | |
| 46 | + configuration: args, | |
| 47 | + request: config.request.to_dap(), | |
| 48 | + } | |
| 49 | + } | |
| 15 | 50 | } |
| 16 | 51 | |
| 17 | 52 | #[async_trait(?Send)] |
| @@ -49,7 +84,7 @@ impl DebugAdapter for JsDebugAdapter { · 31 unmodified lines | ||
| 49 | 84 | async fn get_installed_binary( |
| 50 | 85 | &self, |
| 51 | 86 | delegate: &dyn DapDelegate, |
| 52 | − config: &DebugAdapterConfig, | |
| 87 | + config: &DebugTaskDefinition, | |
| 53 | 88 | user_installed_path: Option<PathBuf>, |
| 54 | 89 | _: &mut AsyncApp, |
| 55 | 90 | ) -> Result<DebugAdapterBinary> { |
| @@ -71,6 +106,7 @@ impl DebugAdapter for JsDebugAdapter { · 15 unmodified lines | ||
| 71 | 106 | let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?; |
| 72 | 107 | |
| 73 | 108 | Ok(DebugAdapterBinary { |
| 109 | + adapter_name: self.name(), | |
| 74 | 110 | command: delegate |
| 75 | 111 | .node_runtime() |
| 76 | 112 | .binary_path() |
| @@ -89,6 +125,7 @@ impl DebugAdapter for JsDebugAdapter { · 12 unmodified lines | ||
| 89 | 125 | port, |
| 90 | 126 | timeout, |
| 91 | 127 | }), |
| 128 | + request_args: self.request_args(config), | |
| 92 | 129 | }) |
| 93 | 130 | } |
| 94 | 131 | |
| @@ -107,35 +144,4 @@ impl DebugAdapter for JsDebugAdapter { · 12 unmodified lines | ||
| 107 | 144 | |
| 108 | 145 | return Ok(()); |
| 109 | 146 | } |
| 110 | − | |
| 111 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 112 | − let mut args = json!({ | |
| 113 | − "type": "pwa-node", | |
| 114 | − "request": match config.request { | |
| 115 | − DebugRequestType::Launch(_) => "launch", | |
| 116 | − DebugRequestType::Attach(_) => "attach", | |
| 117 | − }, | |
| 118 | − }); | |
| 119 | − let map = args.as_object_mut().unwrap(); | |
| 120 | − match &config.request { | |
| 121 | − DebugRequestType::Attach(attach) => { | |
| 122 | − map.insert("processId".into(), attach.process_id.into()); | |
| 123 | − } | |
| 124 | − DebugRequestType::Launch(launch) => { | |
| 125 | − map.insert("program".into(), launch.program.clone().into()); | |
| 126 | − | |
| 127 | − if !launch.args.is_empty() { | |
| 128 | − map.insert("args".into(), launch.args.clone().into()); | |
| 129 | − } | |
| 130 | − | |
| 131 | − if let Some(stop_on_entry) = config.stop_on_entry { | |
| 132 | − map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 133 | − } | |
| 134 | − if let Some(cwd) = launch.cwd.as_ref() { | |
| 135 | − map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 136 | − } | |
| 137 | − } | |
| 138 | − } | |
| 139 | − args | |
| 140 | − } | |
| 141 | 147 | } |
| @@ -3,7 +3,7 @@ use std::{ffi::OsStr, path::PathBuf}; · 2 unmodified lines | ||
| 3 | 3 | use anyhow::Result; |
| 4 | 4 | use async_trait::async_trait; |
| 5 | 5 | use gpui::AsyncApp; |
| 6 | −use task::{DebugAdapterConfig, DebugRequestType, DebugTaskDefinition}; | |
| 6 | +use task::{DebugRequestType, DebugTaskDefinition}; | |
| 7 | 7 | |
| 8 | 8 | use crate::*; |
| 9 | 9 | |
| @@ -12,6 +12,40 @@ pub(crate) struct LldbDebugAdapter; · 2 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | impl LldbDebugAdapter { |
| 14 | 14 | const ADAPTER_NAME: &'static str = "LLDB"; |
| 15 | + | |
| 16 | + fn request_args(&self, config: &DebugTaskDefinition) -> dap::StartDebuggingRequestArguments { | |
| 17 | + let request = config.request.to_dap(); | |
| 18 | + let mut args = json!({ | |
| 19 | + "request": match config.request { | |
| 20 | + DebugRequestType::Launch(_) => "launch", | |
| 21 | + DebugRequestType::Attach(_) => "attach", | |
| 22 | + }, | |
| 23 | + }); | |
| 24 | + let map = args.as_object_mut().unwrap(); | |
| 25 | + match &config.request { | |
| 26 | + DebugRequestType::Attach(attach) => { | |
| 27 | + map.insert("pid".into(), attach.process_id.into()); | |
| 28 | + } | |
| 29 | + DebugRequestType::Launch(launch) => { | |
| 30 | + map.insert("program".into(), launch.program.clone().into()); | |
| 31 | + | |
| 32 | + if !launch.args.is_empty() { | |
| 33 | + map.insert("args".into(), launch.args.clone().into()); | |
| 34 | + } | |
| 35 | + | |
| 36 | + if let Some(stop_on_entry) = config.stop_on_entry { | |
| 37 | + map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 38 | + } | |
| 39 | + if let Some(cwd) = launch.cwd.as_ref() { | |
| 40 | + map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 41 | + } | |
| 42 | + } | |
| 43 | + } | |
| 44 | + dap::StartDebuggingRequestArguments { | |
| 45 | + request, | |
| 46 | + configuration: args, | |
| 47 | + } | |
| 48 | + } | |
| 15 | 49 | } |
| 16 | 50 | |
| 17 | 51 | #[async_trait(?Send)] |
| @@ -23,7 +57,7 @@ impl DebugAdapter for LldbDebugAdapter { · 5 unmodified lines | ||
| 23 | 57 | async fn get_binary( |
| 24 | 58 | &self, |
| 25 | 59 | delegate: &dyn DapDelegate, |
| 26 | − _: &DebugAdapterConfig, | |
| 60 | + config: &DebugTaskDefinition, | |
| 27 | 61 | user_installed_path: Option<PathBuf>, |
| 28 | 62 | _: &mut AsyncApp, |
| 29 | 63 | ) -> Result<DebugAdapterBinary> { |
| @@ -37,11 +71,13 @@ impl DebugAdapter for LldbDebugAdapter { · 7 unmodified lines | ||
| 37 | 71 | }; |
| 38 | 72 | |
| 39 | 73 | Ok(DebugAdapterBinary { |
| 74 | + adapter_name: Self::ADAPTER_NAME.into(), | |
| 40 | 75 | command: lldb_dap_path, |
| 41 | 76 | arguments: None, |
| 42 | 77 | envs: None, |
| 43 | 78 | cwd: None, |
| 44 | 79 | connection: None, |
| 80 | + request_args: self.request_args(config), | |
| 45 | 81 | }) |
| 46 | 82 | } |
| 47 | 83 | |
| @@ -60,40 +96,10 @@ impl DebugAdapter for LldbDebugAdapter { · 12 unmodified lines | ||
| 60 | 96 | async fn get_installed_binary( |
| 61 | 97 | &self, |
| 62 | 98 | _: &dyn DapDelegate, |
| 63 | − _: &DebugAdapterConfig, | |
| 99 | + _: &DebugTaskDefinition, | |
| 64 | 100 | _: Option<PathBuf>, |
| 65 | 101 | _: &mut AsyncApp, |
| 66 | 102 | ) -> Result<DebugAdapterBinary> { |
| 67 | 103 | unimplemented!("LLDB debug adapter cannot be installed by Zed (yet)") |
| 68 | 104 | } |
| 69 | − | |
| 70 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 71 | − let mut args = json!({ | |
| 72 | − "request": match config.request { | |
| 73 | − DebugRequestType::Launch(_) => "launch", | |
| 74 | − DebugRequestType::Attach(_) => "attach", | |
| 75 | − }, | |
| 76 | − }); | |
| 77 | − let map = args.as_object_mut().unwrap(); | |
| 78 | − match &config.request { | |
| 79 | − DebugRequestType::Attach(attach) => { | |
| 80 | − map.insert("pid".into(), attach.process_id.into()); | |
| 81 | − } | |
| 82 | − DebugRequestType::Launch(launch) => { | |
| 83 | − map.insert("program".into(), launch.program.clone().into()); | |
| 84 | − | |
| 85 | − if !launch.args.is_empty() { | |
| 86 | − map.insert("args".into(), launch.args.clone().into()); | |
| 87 | − } | |
| 88 | − | |
| 89 | − if let Some(stop_on_entry) = config.stop_on_entry { | |
| 90 | − map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 91 | − } | |
| 92 | − if let Some(cwd) = launch.cwd.as_ref() { | |
| 93 | − map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 94 | − } | |
| 95 | − } | |
| 96 | − } | |
| 97 | − args | |
| 98 | − } | |
| 99 | 105 | } |
| @@ -13,6 +13,28 @@ impl PhpDebugAdapter { · 12 unmodified lines | ||
| 13 | 13 | const ADAPTER_NAME: &'static str = "PHP"; |
| 14 | 14 | const ADAPTER_PACKAGE_NAME: &'static str = "vscode-php-debug"; |
| 15 | 15 | const ADAPTER_PATH: &'static str = "extension/out/phpDebug.js"; |
| 16 | + | |
| 17 | + fn request_args( | |
| 18 | + &self, | |
| 19 | + config: &DebugTaskDefinition, | |
| 20 | + ) -> Result<dap::StartDebuggingRequestArguments> { | |
| 21 | + match &config.request { | |
| 22 | + dap::DebugRequestType::Attach(_) => { | |
| 23 | + anyhow::bail!("php adapter does not support attaching") | |
| 24 | + } | |
| 25 | + dap::DebugRequestType::Launch(launch_config) => { | |
| 26 | + Ok(dap::StartDebuggingRequestArguments { | |
| 27 | + configuration: json!({ | |
| 28 | + "program": launch_config.program, | |
| 29 | + "cwd": launch_config.cwd, | |
| 30 | + "args": launch_config.args, | |
| 31 | + "stopOnEntry": config.stop_on_entry.unwrap_or_default(), | |
| 32 | + }), | |
| 33 | + request: config.request.to_dap(), | |
| 34 | + }) | |
| 35 | + } | |
| 36 | + } | |
| 37 | + } | |
| 16 | 38 | } |
| 17 | 39 | |
| 18 | 40 | #[async_trait(?Send)] |
| @@ -50,7 +72,7 @@ impl DebugAdapter for PhpDebugAdapter { · 31 unmodified lines | ||
| 50 | 72 | async fn get_installed_binary( |
| 51 | 73 | &self, |
| 52 | 74 | delegate: &dyn DapDelegate, |
| 53 | − config: &DebugAdapterConfig, | |
| 75 | + config: &DebugTaskDefinition, | |
| 54 | 76 | user_installed_path: Option<PathBuf>, |
| 55 | 77 | _: &mut AsyncApp, |
| 56 | 78 | ) -> Result<DebugAdapterBinary> { |
| @@ -72,6 +94,7 @@ impl DebugAdapter for PhpDebugAdapter { · 15 unmodified lines | ||
| 72 | 94 | let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?; |
| 73 | 95 | |
| 74 | 96 | Ok(DebugAdapterBinary { |
| 97 | + adapter_name: self.name(), | |
| 75 | 98 | command: delegate |
| 76 | 99 | .node_runtime() |
| 77 | 100 | .binary_path() |
| @@ -89,6 +112,7 @@ impl DebugAdapter for PhpDebugAdapter { · 11 unmodified lines | ||
| 89 | 112 | }), |
| 90 | 113 | cwd: None, |
| 91 | 114 | envs: None, |
| 115 | + request_args: self.request_args(config)?, | |
| 92 | 116 | }) |
| 93 | 117 | } |
| 94 | 118 | |
| @@ -107,21 +131,4 @@ impl DebugAdapter for PhpDebugAdapter { · 12 unmodified lines | ||
| 107 | 131 | |
| 108 | 132 | Ok(()) |
| 109 | 133 | } |
| 110 | − | |
| 111 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 112 | − match &config.request { | |
| 113 | − dap::DebugRequestType::Attach(_) => { | |
| 114 | − // php adapter does not support attaching | |
| 115 | − json!({}) | |
| 116 | − } | |
| 117 | − dap::DebugRequestType::Launch(launch_config) => { | |
| 118 | − json!({ | |
| 119 | − "program": launch_config.program, | |
| 120 | − "cwd": launch_config.cwd, | |
| 121 | − "args": launch_config.args, | |
| 122 | − "stopOnEntry": config.stop_on_entry.unwrap_or_default(), | |
| 123 | − }) | |
| 124 | − } | |
| 125 | − } | |
| 126 | − } | |
| 127 | 134 | } |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | use crate::*; |
| 2 | −use dap::DebugRequestType; | |
| 2 | +use dap::{DebugRequestType, StartDebuggingRequestArguments}; | |
| 3 | 3 | use gpui::AsyncApp; |
| 4 | 4 | use std::{ffi::OsStr, path::PathBuf}; |
| 5 | 5 | use task::DebugTaskDefinition; |
| @@ -12,6 +12,38 @@ impl PythonDebugAdapter { · 6 unmodified lines | ||
| 12 | 12 | const ADAPTER_PACKAGE_NAME: &'static str = "debugpy"; |
| 13 | 13 | const ADAPTER_PATH: &'static str = "src/debugpy/adapter"; |
| 14 | 14 | const LANGUAGE_NAME: &'static str = "Python"; |
| 15 | + | |
| 16 | + fn request_args(&self, config: &DebugTaskDefinition) -> StartDebuggingRequestArguments { | |
| 17 | + let mut args = json!({ | |
| 18 | + "request": match config.request { | |
| 19 | + DebugRequestType::Launch(_) => "launch", | |
| 20 | + DebugRequestType::Attach(_) => "attach", | |
| 21 | + }, | |
| 22 | + "subProcess": true, | |
| 23 | + "redirectOutput": true, | |
| 24 | + }); | |
| 25 | + let map = args.as_object_mut().unwrap(); | |
| 26 | + match &config.request { | |
| 27 | + DebugRequestType::Attach(attach) => { | |
| 28 | + map.insert("processId".into(), attach.process_id.into()); | |
| 29 | + } | |
| 30 | + DebugRequestType::Launch(launch) => { | |
| 31 | + map.insert("program".into(), launch.program.clone().into()); | |
| 32 | + map.insert("args".into(), launch.args.clone().into()); | |
| 33 | + | |
| 34 | + if let Some(stop_on_entry) = config.stop_on_entry { | |
| 35 | + map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 36 | + } | |
| 37 | + if let Some(cwd) = launch.cwd.as_ref() { | |
| 38 | + map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 39 | + } | |
| 40 | + } | |
| 41 | + } | |
| 42 | + StartDebuggingRequestArguments { | |
| 43 | + configuration: args, | |
| 44 | + request: config.request.to_dap(), | |
| 45 | + } | |
| 46 | + } | |
| 15 | 47 | } |
| 16 | 48 | |
| 17 | 49 | #[async_trait(?Send)] |
| @@ -64,7 +96,7 @@ impl DebugAdapter for PythonDebugAdapter { · 46 unmodified lines | ||
| 64 | 96 | async fn get_installed_binary( |
| 65 | 97 | &self, |
| 66 | 98 | delegate: &dyn DapDelegate, |
| 67 | − config: &DebugAdapterConfig, | |
| 99 | + config: &DebugTaskDefinition, | |
| 68 | 100 | user_installed_path: Option<PathBuf>, |
| 69 | 101 | cx: &mut AsyncApp, |
| 70 | 102 | ) -> Result<DebugAdapterBinary> { |
| @@ -109,6 +141,7 @@ impl DebugAdapter for PythonDebugAdapter { · 38 unmodified lines | ||
| 109 | 141 | }; |
| 110 | 142 | |
| 111 | 143 | Ok(DebugAdapterBinary { |
| 144 | + adapter_name: self.name(), | |
| 112 | 145 | command: python_path.ok_or(anyhow!("failed to find binary path for python"))?, |
| 113 | 146 | arguments: Some(vec![ |
| 114 | 147 | debugpy_dir.join(Self::ADAPTER_PATH).into(), |
| @@ -122,35 +155,7 @@ impl DebugAdapter for PythonDebugAdapter { · 7 unmodified lines | ||
| 122 | 155 | }), |
| 123 | 156 | cwd: None, |
| 124 | 157 | envs: None, |
| 158 | + request_args: self.request_args(config), | |
| 125 | 159 | }) |
| 126 | 160 | } |
| 127 | − | |
| 128 | − fn request_args(&self, config: &DebugTaskDefinition) -> Value { | |
| 129 | − let mut args = json!({ | |
| 130 | − "request": match config.request { | |
| 131 | − DebugRequestType::Launch(_) => "launch", | |
| 132 | − DebugRequestType::Attach(_) => "attach", | |
| 133 | − }, | |
| 134 | − "subProcess": true, | |
| 135 | − "redirectOutput": true, | |
| 136 | − }); | |
| 137 | − let map = args.as_object_mut().unwrap(); | |
| 138 | − match &config.request { | |
| 139 | − DebugRequestType::Attach(attach) => { | |
| 140 | − map.insert("processId".into(), attach.process_id.into()); | |
| 141 | − } | |
| 142 | − DebugRequestType::Launch(launch) => { | |
| 143 | − map.insert("program".into(), launch.program.clone().into()); | |
| 144 | − map.insert("args".into(), launch.args.clone().into()); | |
| 145 | − | |
| 146 | − if let Some(stop_on_entry) = config.stop_on_entry { | |
| 147 | − map.insert("stopOnEntry".into(), stop_on_entry.into()); | |
| 148 | − } | |
| 149 | − if let Some(cwd) = launch.cwd.as_ref() { | |
| 150 | − map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into()); | |
| 151 | − } | |
| 152 | − } | |
| 153 | − } | |
| 154 | − args | |
| 155 | − } | |
| 156 | 161 | } |
| @@ -228,10 +228,7 @@ impl PickerDelegate for AttachModalDelegate { · 227 unmodified lines | ||
| 228 | 228 | let config = self.debug_config.clone(); |
| 229 | 229 | self.project |
| 230 | 230 | .update(cx, |project, cx| { |
| 231 | − #[cfg(any(test, feature = "test-support"))] | |
| 232 | − let ret = project.fake_debug_session(config.request, None, false, cx); | |
| 233 | − #[cfg(not(any(test, feature = "test-support")))] | |
| 234 | − let ret = project.start_debug_session(config.into(), cx); | |
| 231 | + let ret = project.start_debug_session(config, cx); | |
| 235 | 232 | ret |
| 236 | 233 | }) |
| 237 | 234 | .detach_and_log_err(cx); |
| @@ -146,7 +146,7 @@ impl NewSessionModal { · 145 unmodified lines | ||
| 146 | 146 | { |
| 147 | 147 | this.start_debug_session(debug_config, cx) |
| 148 | 148 | } else { |
| 149 | − this.start_debug_session(config.into(), cx) | |
| 149 | + this.start_debug_session(config, cx) | |
| 150 | 150 | } |
| 151 | 151 | })?; |
| 152 | 152 | let spawn_result = task.await; |
| @@ -26,18 +26,30 @@ async fn test_direct_attach_to_process(executor: BackgroundExecutor, cx: &mut Te · 25 unmodified lines | ||
| 26 | 26 | let workspace = init_test_workspace(&project, cx).await; |
| 27 | 27 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 28 | 28 | |
| 29 | − let task = project.update(cx, |project, cx| { | |
| 30 | − project.fake_debug_session( | |
| 31 | − dap::DebugRequestType::Attach(AttachConfig { | |
| 29 | + let session = debugger::test::start_debug_session_with( | |
| 30 | + &project, | |
| 31 | + cx, | |
| 32 | + DebugTaskDefinition { | |
| 33 | + adapter: "fake-adapter".to_string(), | |
| 34 | + request: dap::DebugRequestType::Attach(AttachConfig { | |
| 32 | 35 | process_id: Some(10), |
| 33 | 36 | }), |
| 34 | − None, | |
| 35 | − false, | |
| 36 | − cx, | |
| 37 | − ) | |
| 38 | − }); | |
| 39 | − | |
| 40 | − let session = task.await.unwrap(); | |
| 37 | + label: "label".to_string(), | |
| 38 | + initialize_args: None, | |
| 39 | + tcp_connection: None, | |
| 40 | + locator: None, | |
| 41 | + stop_on_entry: None, | |
| 42 | + }, | |
| 43 | + |client| { | |
| 44 | + client.on_request::<dap::requests::Attach, _>(move |_, args| { | |
| 45 | + assert_eq!(json!({"request": "attach", "process_id": 10}), args.raw); | |
| 46 | + | |
| 47 | + Ok(()) | |
| 48 | + }); | |
| 49 | + }, | |
| 50 | + ) | |
| 51 | + .await | |
| 52 | + .unwrap(); | |
| 41 | 53 | |
| 42 | 54 | cx.run_until_parked(); |
| 43 | 55 | |
| @@ -77,7 +89,15 @@ async fn test_show_attach_modal_and_select_process( · 33 unmodified lines | ||
| 77 | 89 | let project = Project::test(fs, ["/project".as_ref()], cx).await; |
| 78 | 90 | let workspace = init_test_workspace(&project, cx).await; |
| 79 | 91 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 92 | + // Set up handlers for sessions spawned via modal. | |
| 93 | + let _initialize_subscription = | |
| 94 | + project::debugger::test::intercept_debug_sessions(cx, |client| { | |
| 95 | + client.on_request::<dap::requests::Attach, _>(move |_, args| { | |
| 96 | + assert_eq!(json!({"request": "attach", "process_id": 1}), args.raw); | |
| 80 | 97 | |
| 98 | + Ok(()) | |
| 99 | + }); | |
| 100 | + }); | |
| 81 | 101 | let attach_modal = workspace |
| 82 | 102 | .update(cx, |workspace, window, cx| { |
| 83 | 103 | workspace.toggle_modal(window, cx, |window, cx| { |
| @@ -3,7 +3,6 @@ use dap::requests::StackTrace; · 2 unmodified lines | ||
| 3 | 3 | use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext}; |
| 4 | 4 | use project::{FakeFs, Project}; |
| 5 | 5 | use serde_json::json; |
| 6 | −use task::LaunchConfig; | |
| 7 | 6 | use tests::{init_test, init_test_workspace}; |
| 8 | 7 | |
| 9 | 8 | #[gpui::test] |
| @@ -29,26 +28,17 @@ async fn test_handle_output_event(executor: BackgroundExecutor, cx: &mut TestApp · 19 unmodified lines | ||
| 29 | 28 | }) |
| 30 | 29 | .unwrap(); |
| 31 | 30 | |
| 32 | − let task = project.update(cx, |project, cx| { | |
| 33 | − project.fake_debug_session( | |
| 34 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 35 | − None, | |
| 36 | − false, | |
| 37 | − cx, | |
| 38 | − ) | |
| 39 | − }); | |
| 40 | − | |
| 41 | − let session = task.await.unwrap(); | |
| 31 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 32 | + .await | |
| 33 | + .unwrap(); | |
| 42 | 34 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 43 | 35 | |
| 44 | − client | |
| 45 | − .on_request::<StackTrace, _>(move |_, _| { | |
| 46 | − Ok(dap::StackTraceResponse { | |
| 47 | − stack_frames: Vec::default(), | |
| 48 | − total_frames: None, | |
| 49 | − }) | |
| 36 | + client.on_request::<StackTrace, _>(move |_, _| { | |
| 37 | + Ok(dap::StackTraceResponse { | |
| 38 | + stack_frames: Vec::default(), | |
| 39 | + total_frames: None, | |
| 50 | 40 | }) |
| 51 | − .await; | |
| 41 | + }); | |
| 52 | 42 | |
| 53 | 43 | client |
| 54 | 44 | .fake_event(dap::messages::Events::Output(dap::OutputEvent { |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | use crate::*; |
| 2 | 2 | use dap::{ |
| 3 | − ErrorResponse, RunInTerminalRequestArguments, SourceBreakpoint, StartDebuggingRequestArguments, | |
| 4 | − StartDebuggingRequestArgumentsRequest, | |
| 3 | + ErrorResponse, Message, RunInTerminalRequestArguments, SourceBreakpoint, | |
| 4 | + StartDebuggingRequestArguments, StartDebuggingRequestArgumentsRequest, | |
| 5 | 5 | client::SessionId, |
| 6 | 6 | requests::{ |
| 7 | 7 | Continue, Disconnect, Launch, Next, RunInTerminal, SetBreakpoints, StackTrace, |
| @@ -25,7 +25,6 @@ use std::{ · 17 unmodified lines | ||
| 25 | 25 | atomic::{AtomicBool, Ordering}, |
| 26 | 26 | }, |
| 27 | 27 | }; |
| 28 | −use task::LaunchConfig; | |
| 29 | 28 | use terminal_view::{TerminalView, terminal_panel::TerminalPanel}; |
| 30 | 29 | use tests::{active_debug_session_panel, init_test, init_test_workspace}; |
| 31 | 30 | use util::path; |
| @@ -49,37 +48,26 @@ async fn test_basic_show_debug_panel(executor: BackgroundExecutor, cx: &mut Test · 17 unmodified lines | ||
| 49 | 48 | let workspace = init_test_workspace(&project, cx).await; |
| 50 | 49 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 51 | 50 | |
| 52 | − let task = project.update(cx, |project, cx| { | |
| 53 | − project.fake_debug_session( | |
| 54 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 55 | − None, | |
| 56 | − false, | |
| 57 | − cx, | |
| 58 | − ) | |
| 59 | − }); | |
| 60 | − | |
| 61 | − let session = task.await.unwrap(); | |
| 51 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 52 | + .await | |
| 53 | + .unwrap(); | |
| 62 | 54 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 63 | 55 | |
| 64 | − client | |
| 65 | − .on_request::<Threads, _>(move |_, _| { | |
| 66 | − Ok(dap::ThreadsResponse { | |
| 67 | − threads: vec![dap::Thread { | |
| 68 | − id: 1, | |
| 69 | − name: "Thread 1".into(), | |
| 70 | − }], | |
| 71 | − }) | |
| 56 | + client.on_request::<Threads, _>(move |_, _| { | |
| 57 | + Ok(dap::ThreadsResponse { | |
| 58 | + threads: vec![dap::Thread { | |
| 59 | + id: 1, | |
| 60 | + name: "Thread 1".into(), | |
| 61 | + }], | |
| 72 | 62 | }) |
| 73 | − .await; | |
| 63 | + }); | |
| 74 | 64 | |
| 75 | − client | |
| 76 | − .on_request::<StackTrace, _>(move |_, _| { | |
| 77 | − Ok(dap::StackTraceResponse { | |
| 78 | − stack_frames: Vec::default(), | |
| 79 | − total_frames: None, | |
| 80 | − }) | |
| 65 | + client.on_request::<StackTrace, _>(move |_, _| { | |
| 66 | + Ok(dap::StackTraceResponse { | |
| 67 | + stack_frames: Vec::default(), | |
| 68 | + total_frames: None, | |
| 81 | 69 | }) |
| 82 | − .await; | |
| 70 | + }); | |
| 83 | 71 | |
| 84 | 72 | cx.run_until_parked(); |
| 85 | 73 | |
| @@ -199,37 +187,26 @@ async fn test_we_can_only_have_one_panel_per_debug_session( · 113 unmodified lines | ||
| 199 | 187 | let workspace = init_test_workspace(&project, cx).await; |
| 200 | 188 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 201 | 189 | |
| 202 | − let task = project.update(cx, |project, cx| { | |
| 203 | − project.fake_debug_session( | |
| 204 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 205 | − None, | |
| 206 | − false, | |
| 207 | − cx, | |
| 208 | − ) | |
| 209 | − }); | |
| 210 | − | |
| 211 | − let session = task.await.unwrap(); | |
| 190 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 191 | + .await | |
| 192 | + .unwrap(); | |
| 212 | 193 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 213 | 194 | |
| 214 | − client | |
| 215 | − .on_request::<Threads, _>(move |_, _| { | |
| 216 | − Ok(dap::ThreadsResponse { | |
| 217 | − threads: vec![dap::Thread { | |
| 218 | − id: 1, | |
| 219 | − name: "Thread 1".into(), | |
| 220 | − }], | |
| 221 | − }) | |
| 195 | + client.on_request::<Threads, _>(move |_, _| { | |
| 196 | + Ok(dap::ThreadsResponse { | |
| 197 | + threads: vec![dap::Thread { | |
| 198 | + id: 1, | |
| 199 | + name: "Thread 1".into(), | |
| 200 | + }], | |
| 222 | 201 | }) |
| 223 | − .await; | |
| 202 | + }); | |
| 224 | 203 | |
| 225 | − client | |
| 226 | − .on_request::<StackTrace, _>(move |_, _| { | |
| 227 | − Ok(dap::StackTraceResponse { | |
| 228 | − stack_frames: Vec::default(), | |
| 229 | − total_frames: None, | |
| 230 | − }) | |
| 204 | + client.on_request::<StackTrace, _>(move |_, _| { | |
| 205 | + Ok(dap::StackTraceResponse { | |
| 206 | + stack_frames: Vec::default(), | |
| 207 | + total_frames: None, | |
| 231 | 208 | }) |
| 232 | − .await; | |
| 209 | + }); | |
| 233 | 210 | |
| 234 | 211 | cx.run_until_parked(); |
| 235 | 212 | |
| @@ -377,16 +354,9 @@ async fn test_handle_successful_run_in_terminal_reverse_request( · 141 unmodified lines | ||
| 377 | 354 | let workspace = init_test_workspace(&project, cx).await; |
| 378 | 355 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 379 | 356 | |
| 380 | − let task = project.update(cx, |project, cx| { | |
| 381 | − project.fake_debug_session( | |
| 382 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 383 | − None, | |
| 384 | − false, | |
| 385 | − cx, | |
| 386 | − ) | |
| 387 | − }); | |
| 388 | − | |
| 389 | − let session = task.await.unwrap(); | |
| 357 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 358 | + .await | |
| 359 | + .unwrap(); | |
| 390 | 360 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 391 | 361 | |
| 392 | 362 | client |
| @@ -474,16 +444,9 @@ async fn test_handle_error_run_in_terminal_reverse_request( · 81 unmodified lines | ||
| 474 | 444 | let workspace = init_test_workspace(&project, cx).await; |
| 475 | 445 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 476 | 446 | |
| 477 | − let task = project.update(cx, |project, cx| { | |
| 478 | − project.fake_debug_session( | |
| 479 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 480 | − None, | |
| 481 | − false, | |
| 482 | − cx, | |
| 483 | − ) | |
| 484 | − }); | |
| 485 | − | |
| 486 | − let session = task.await.unwrap(); | |
| 447 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 448 | + .await | |
| 449 | + .unwrap(); | |
| 487 | 450 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 488 | 451 | |
| 489 | 452 | client |
| @@ -559,28 +522,19 @@ async fn test_handle_start_debugging_reverse_request( · 69 unmodified lines | ||
| 559 | 522 | let workspace = init_test_workspace(&project, cx).await; |
| 560 | 523 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 561 | 524 | |
| 562 | − let task = project.update(cx, |project, cx| { | |
| 563 | − project.fake_debug_session( | |
| 564 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 565 | − None, | |
| 566 | − false, | |
| 567 | − cx, | |
| 568 | − ) | |
| 569 | − }); | |
| 570 | − | |
| 571 | − let session = task.await.unwrap(); | |
| 525 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 526 | + .await | |
| 527 | + .unwrap(); | |
| 572 | 528 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 573 | 529 | |
| 574 | − client | |
| 575 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 576 | − Ok(dap::ThreadsResponse { | |
| 577 | − threads: vec![dap::Thread { | |
| 578 | − id: 1, | |
| 579 | − name: "Thread 1".into(), | |
| 580 | − }], | |
| 581 | − }) | |
| 530 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 531 | + Ok(dap::ThreadsResponse { | |
| 532 | + threads: vec![dap::Thread { | |
| 533 | + id: 1, | |
| 534 | + name: "Thread 1".into(), | |
| 535 | + }], | |
| 582 | 536 | }) |
| 583 | − .await; | |
| 537 | + }); | |
| 584 | 538 | |
| 585 | 539 | client |
| 586 | 540 | .on_response::<StartDebugging, _>({ |
| @@ -593,7 +547,9 @@ async fn test_handle_start_debugging_reverse_request( · 6 unmodified lines | ||
| 593 | 547 | } |
| 594 | 548 | }) |
| 595 | 549 | .await; |
| 596 | − | |
| 550 | + // Set up handlers for sessions spawned with reverse request too. | |
| 551 | + let _reverse_request_subscription = | |
| 552 | + project::debugger::test::intercept_debug_sessions(cx, |_| {}); | |
| 597 | 553 | client |
| 598 | 554 | .fake_reverse_request::<StartDebugging>(StartDebuggingRequestArguments { |
| 599 | 555 | configuration: json!({}), |
| @@ -612,20 +568,16 @@ async fn test_handle_start_debugging_reverse_request( · 12 unmodified lines | ||
| 612 | 568 | }); |
| 613 | 569 | let child_client = child_session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 614 | 570 | |
| 615 | − child_client | |
| 616 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 617 | − Ok(dap::ThreadsResponse { | |
| 618 | − threads: vec![dap::Thread { | |
| 619 | − id: 1, | |
| 620 | − name: "Thread 1".into(), | |
| 621 | − }], | |
| 622 | − }) | |
| 571 | + child_client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 572 | + Ok(dap::ThreadsResponse { | |
| 573 | + threads: vec![dap::Thread { | |
| 574 | + id: 1, | |
| 575 | + name: "Thread 1".into(), | |
| 576 | + }], | |
| 623 | 577 | }) |
| 624 | − .await; | |
| 578 | + }); | |
| 625 | 579 | |
| 626 | − child_client | |
| 627 | − .on_request::<Disconnect, _>(move |_, _| Ok(())) | |
| 628 | − .await; | |
| 580 | + child_client.on_request::<Disconnect, _>(move |_, _| Ok(())); | |
| 629 | 581 | |
| 630 | 582 | child_client |
| 631 | 583 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -677,31 +629,24 @@ async fn test_shutdown_children_when_parent_session_shutdown( · 45 unmodified lines | ||
| 677 | 629 | let workspace = init_test_workspace(&project, cx).await; |
| 678 | 630 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 679 | 631 | |
| 680 | − let task = project.update(cx, |project, cx| { | |
| 681 | − project.fake_debug_session( | |
| 682 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 683 | − None, | |
| 684 | − false, | |
| 685 | − cx, | |
| 686 | − ) | |
| 687 | − }); | |
| 688 | − | |
| 689 | − let parent_session = task.await.unwrap(); | |
| 632 | + let parent_session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 633 | + .await | |
| 634 | + .unwrap(); | |
| 690 | 635 | let client = parent_session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 691 | 636 | |
| 692 | − client | |
| 693 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 694 | − Ok(dap::ThreadsResponse { | |
| 695 | − threads: vec![dap::Thread { | |
| 696 | − id: 1, | |
| 697 | − name: "Thread 1".into(), | |
| 698 | − }], | |
| 699 | − }) | |
| 637 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 638 | + Ok(dap::ThreadsResponse { | |
| 639 | + threads: vec![dap::Thread { | |
| 640 | + id: 1, | |
| 641 | + name: "Thread 1".into(), | |
| 642 | + }], | |
| 700 | 643 | }) |
| 701 | − .await; | |
| 644 | + }); | |
| 702 | 645 | |
| 703 | 646 | client.on_response::<StartDebugging, _>(move |_| {}).await; |
| 704 | − | |
| 647 | + // Set up handlers for sessions spawned with reverse request too. | |
| 648 | + let _reverse_request_subscription = | |
| 649 | + project::debugger::test::intercept_debug_sessions(cx, |_| {}); | |
| 705 | 650 | // start first child session |
| 706 | 651 | client |
| 707 | 652 | .fake_reverse_request::<StartDebugging>(StartDebuggingRequestArguments { |
| @@ -729,9 +674,7 @@ async fn test_shutdown_children_when_parent_session_shutdown( · 21 unmodified lines | ||
| 729 | 674 | let first_child_client = |
| 730 | 675 | first_child_session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 731 | 676 | |
| 732 | − first_child_client | |
| 733 | − .on_request::<Disconnect, _>(move |_, _| Ok(())) | |
| 734 | − .await; | |
| 677 | + first_child_client.on_request::<Disconnect, _>(move |_, _| Ok(())); | |
| 735 | 678 | |
| 736 | 679 | // configure second child session |
| 737 | 680 | let second_child_session = dap_store.read_with(cx, |dap_store, _| { |
| @@ -740,9 +683,7 @@ async fn test_shutdown_children_when_parent_session_shutdown( · 2 unmodified lines | ||
| 740 | 683 | let second_child_client = |
| 741 | 684 | second_child_session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 742 | 685 | |
| 743 | − second_child_client | |
| 744 | − .on_request::<Disconnect, _>(move |_, _| Ok(())) | |
| 745 | − .await; | |
| 686 | + second_child_client.on_request::<Disconnect, _>(move |_, _| Ok(())); | |
| 746 | 687 | |
| 747 | 688 | cx.run_until_parked(); |
| 748 | 689 | |
| @@ -796,20 +737,15 @@ async fn test_shutdown_parent_session_if_all_children_are_shutdown( · 47 unmodified lines | ||
| 796 | 737 | let workspace = init_test_workspace(&project, cx).await; |
| 797 | 738 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 798 | 739 | |
| 799 | − let task = project.update(cx, |project, cx| { | |
| 800 | − project.fake_debug_session( | |
| 801 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 802 | − None, | |
| 803 | − false, | |
| 804 | − cx, | |
| 805 | − ) | |
| 806 | − }); | |
| 807 | − | |
| 808 | − let parent_session = task.await.unwrap(); | |
| 740 | + let parent_session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 741 | + .await | |
| 742 | + .unwrap(); | |
| 809 | 743 | let client = parent_session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 810 | 744 | |
| 811 | 745 | client.on_response::<StartDebugging, _>(move |_| {}).await; |
| 812 | − | |
| 746 | + // Set up handlers for sessions spawned with reverse request too. | |
| 747 | + let _reverse_request_subscription = | |
| 748 | + project::debugger::test::intercept_debug_sessions(cx, |_| {}); | |
| 813 | 749 | // start first child session |
| 814 | 750 | client |
| 815 | 751 | .fake_reverse_request::<StartDebugging>(StartDebuggingRequestArguments { |
| @@ -837,9 +773,7 @@ async fn test_shutdown_parent_session_if_all_children_are_shutdown( · 21 unmodified lines | ||
| 837 | 773 | let first_child_client = |
| 838 | 774 | first_child_session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 839 | 775 | |
| 840 | − first_child_client | |
| 841 | − .on_request::<Disconnect, _>(move |_, _| Ok(())) | |
| 842 | − .await; | |
| 776 | + first_child_client.on_request::<Disconnect, _>(move |_, _| Ok(())); | |
| 843 | 777 | |
| 844 | 778 | // configure second child session |
| 845 | 779 | let second_child_session = dap_store.read_with(cx, |dap_store, _| { |
| @@ -848,9 +782,7 @@ async fn test_shutdown_parent_session_if_all_children_are_shutdown( · 2 unmodified lines | ||
| 848 | 782 | let second_child_client = |
| 849 | 783 | second_child_session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 850 | 784 | |
| 851 | − second_child_client | |
| 852 | − .on_request::<Disconnect, _>(move |_, _| Ok(())) | |
| 853 | − .await; | |
| 785 | + second_child_client.on_request::<Disconnect, _>(move |_, _| Ok(())); | |
| 854 | 786 | |
| 855 | 787 | cx.run_until_parked(); |
| 856 | 788 | |
| @@ -926,123 +858,107 @@ async fn test_debug_panel_item_thread_status_reset_on_failure( · 69 unmodified lines | ||
| 926 | 858 | let workspace = init_test_workspace(&project, cx).await; |
| 927 | 859 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 928 | 860 | |
| 929 | − let task = project.update(cx, |project, cx| { | |
| 930 | − project.fake_debug_session( | |
| 931 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 932 | − Some(dap::Capabilities { | |
| 861 | + let session = debugger::test::start_debug_session(&project, cx, |client| { | |
| 862 | + client.on_request::<dap::requests::Initialize, _>(move |_, _| { | |
| 863 | + Ok(dap::Capabilities { | |
| 933 | 864 | supports_step_back: Some(true), |
| 934 | 865 | ..Default::default() |
| 935 | − }), | |
| 936 | − false, | |
| 937 | − cx, | |
| 938 | − ) | |
| 939 | − }); | |
| 866 | + }) | |
| 867 | + }); | |
| 868 | + }) | |
| 869 | + .await | |
| 870 | + .unwrap(); | |
| 940 | 871 | |
| 941 | − let session = task.await.unwrap(); | |
| 942 | 872 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 943 | 873 | const THREAD_ID_NUM: u64 = 1; |
| 944 | 874 | |
| 945 | − client | |
| 946 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 947 | − Ok(dap::ThreadsResponse { | |
| 948 | − threads: vec![dap::Thread { | |
| 949 | − id: THREAD_ID_NUM, | |
| 950 | − name: "Thread 1".into(), | |
| 951 | − }], | |
| 952 | − }) | |
| 875 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 876 | + Ok(dap::ThreadsResponse { | |
| 877 | + threads: vec![dap::Thread { | |
| 878 | + id: THREAD_ID_NUM, | |
| 879 | + name: "Thread 1".into(), | |
| 880 | + }], | |
| 953 | 881 | }) |
| 954 | − .await; | |
| 882 | + }); | |
| 955 | 883 | |
| 956 | − client.on_request::<Launch, _>(move |_, _| Ok(())).await; | |
| 884 | + client.on_request::<Launch, _>(move |_, _| Ok(())); | |
| 957 | 885 | |
| 958 | − client | |
| 959 | − .on_request::<StackTrace, _>(move |_, _| { | |
| 960 | − Ok(dap::StackTraceResponse { | |
| 961 | − stack_frames: Vec::default(), | |
| 962 | − total_frames: None, | |
| 963 | − }) | |
| 886 | + client.on_request::<StackTrace, _>(move |_, _| { | |
| 887 | + Ok(dap::StackTraceResponse { | |
| 888 | + stack_frames: Vec::default(), | |
| 889 | + total_frames: None, | |
| 964 | 890 | }) |
| 965 | − .await; | |
| 891 | + }); | |
| 966 | 892 | |
| 967 | − client | |
| 968 | − .on_request::<Next, _>(move |_, _| { | |
| 969 | − Err(ErrorResponse { | |
| 970 | − error: Some(dap::Message { | |
| 971 | − id: 1, | |
| 972 | − format: "error".into(), | |
| 973 | − variables: None, | |
| 974 | − send_telemetry: None, | |
| 975 | − show_user: None, | |
| 976 | − url: None, | |
| 977 | − url_label: None, | |
| 978 | − }), | |
| 979 | − }) | |
| 893 | + client.on_request::<Next, _>(move |_, _| { | |
| 894 | + Err(ErrorResponse { | |
| 895 | + error: Some(dap::Message { | |
| 896 | + id: 1, | |
| 897 | + format: "error".into(), | |
| 898 | + variables: None, | |
| 899 | + send_telemetry: None, | |
| 900 | + show_user: None, | |
| 901 | + url: None, | |
| 902 | + url_label: None, | |
| 903 | + }), | |
| 980 | 904 | }) |
| 981 | − .await; | |
| 905 | + }); | |
| 982 | 906 | |
| 983 | − client | |
| 984 | − .on_request::<StepOut, _>(move |_, _| { | |
| 985 | − Err(ErrorResponse { | |
| 986 | − error: Some(dap::Message { | |
| 987 | − id: 1, | |
| 988 | − format: "error".into(), | |
| 989 | − variables: None, | |
| 990 | − send_telemetry: None, | |
| 991 | − show_user: None, | |
| 992 | − url: None, | |
| 993 | − url_label: None, | |
| 994 | − }), | |
| 995 | − }) | |
| 907 | + client.on_request::<StepOut, _>(move |_, _| { | |
| 908 | + Err(ErrorResponse { | |
| 909 | + error: Some(dap::Message { | |
| 910 | + id: 1, | |
| 911 | + format: "error".into(), | |
| 912 | + variables: None, | |
| 913 | + send_telemetry: None, | |
| 914 | + show_user: None, | |
| 915 | + url: None, | |
| 916 | + url_label: None, | |
| 917 | + }), | |
| 996 | 918 | }) |
| 997 | − .await; | |
| 919 | + }); | |
| 998 | 920 | |
| 999 | − client | |
| 1000 | − .on_request::<StepIn, _>(move |_, _| { | |
| 1001 | − Err(ErrorResponse { | |
| 1002 | − error: Some(dap::Message { | |
| 1003 | − id: 1, | |
| 1004 | − format: "error".into(), | |
| 1005 | − variables: None, | |
| 1006 | − send_telemetry: None, | |
| 1007 | − show_user: None, | |
| 1008 | − url: None, | |
| 1009 | − url_label: None, | |
| 1010 | − }), | |
| 1011 | − }) | |
| 921 | + client.on_request::<StepIn, _>(move |_, _| { | |
| 922 | + Err(ErrorResponse { | |
| 923 | + error: Some(dap::Message { | |
| 924 | + id: 1, | |
| 925 | + format: "error".into(), | |
| 926 | + variables: None, | |
| 927 | + send_telemetry: None, | |
| 928 | + show_user: None, | |
| 929 | + url: None, | |
| 930 | + url_label: None, | |
| 931 | + }), | |
| 1012 | 932 | }) |
| 1013 | − .await; | |
| 933 | + }); | |
| 1014 | 934 | |
| 1015 | − client | |
| 1016 | − .on_request::<StepBack, _>(move |_, _| { | |
| 1017 | − Err(ErrorResponse { | |
| 1018 | − error: Some(dap::Message { | |
| 1019 | − id: 1, | |
| 1020 | − format: "error".into(), | |
| 1021 | − variables: None, | |
| 1022 | − send_telemetry: None, | |
| 1023 | − show_user: None, | |
| 1024 | − url: None, | |
| 1025 | − url_label: None, | |
| 1026 | − }), | |
| 1027 | − }) | |
| 935 | + client.on_request::<StepBack, _>(move |_, _| { | |
| 936 | + Err(ErrorResponse { | |
| 937 | + error: Some(dap::Message { | |
| 938 | + id: 1, | |
| 939 | + format: "error".into(), | |
| 940 | + variables: None, | |
| 941 | + send_telemetry: None, | |
| 942 | + show_user: None, | |
| 943 | + url: None, | |
| 944 | + url_label: None, | |
| 945 | + }), | |
| 1028 | 946 | }) |
| 1029 | − .await; | |
| 947 | + }); | |
| 1030 | 948 | |
| 1031 | − client | |
| 1032 | − .on_request::<Continue, _>(move |_, _| { | |
| 1033 | − Err(ErrorResponse { | |
| 1034 | − error: Some(dap::Message { | |
| 1035 | − id: 1, | |
| 1036 | − format: "error".into(), | |
| 1037 | − variables: None, | |
| 1038 | − send_telemetry: None, | |
| 1039 | − show_user: None, | |
| 1040 | − url: None, | |
| 1041 | − url_label: None, | |
| 1042 | − }), | |
| 1043 | − }) | |
| 949 | + client.on_request::<Continue, _>(move |_, _| { | |
| 950 | + Err(ErrorResponse { | |
| 951 | + error: Some(dap::Message { | |
| 952 | + id: 1, | |
| 953 | + format: "error".into(), | |
| 954 | + variables: None, | |
| 955 | + send_telemetry: None, | |
| 956 | + show_user: None, | |
| 957 | + url: None, | |
| 958 | + url_label: None, | |
| 959 | + }), | |
| 1044 | 960 | }) |
| 1045 | − .await; | |
| 961 | + }); | |
| 1046 | 962 | |
| 1047 | 963 | client |
| 1048 | 964 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -1157,16 +1073,9 @@ async fn test_send_breakpoints_when_editor_has_been_saved( · 108 unmodified lines | ||
| 1157 | 1073 | .update(cx, |_, _, cx| worktree.read(cx).id()) |
| 1158 | 1074 | .unwrap(); |
| 1159 | 1075 | |
| 1160 | − let task = project.update(cx, |project, cx| { | |
| 1161 | − project.fake_debug_session( | |
| 1162 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 1163 | − None, | |
| 1164 | − false, | |
| 1165 | − cx, | |
| 1166 | − ) | |
| 1167 | − }); | |
| 1168 | − | |
| 1169 | − let session = task.await.unwrap(); | |
| 1076 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 1077 | + .await | |
| 1078 | + .unwrap(); | |
| 1170 | 1079 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 1171 | 1080 | |
| 1172 | 1081 | let buffer = project |
| @@ -1186,16 +1095,14 @@ async fn test_send_breakpoints_when_editor_has_been_saved( · 13 unmodified lines | ||
| 1186 | 1095 | ) |
| 1187 | 1096 | }); |
| 1188 | 1097 | |
| 1189 | − client.on_request::<Launch, _>(move |_, _| Ok(())).await; | |
| 1098 | + client.on_request::<Launch, _>(move |_, _| Ok(())); | |
| 1190 | 1099 | |
| 1191 | − client | |
| 1192 | − .on_request::<StackTrace, _>(move |_, _| { | |
| 1193 | − Ok(dap::StackTraceResponse { | |
| 1194 | − stack_frames: Vec::default(), | |
| 1195 | − total_frames: None, | |
| 1196 | − }) | |
| 1100 | + client.on_request::<StackTrace, _>(move |_, _| { | |
| 1101 | + Ok(dap::StackTraceResponse { | |
| 1102 | + stack_frames: Vec::default(), | |
| 1103 | + total_frames: None, | |
| 1197 | 1104 | }) |
| 1198 | − .await; | |
| 1105 | + }); | |
| 1199 | 1106 | |
| 1200 | 1107 | client |
| 1201 | 1108 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -1210,32 +1117,30 @@ async fn test_send_breakpoints_when_editor_has_been_saved( · 8 unmodified lines | ||
| 1210 | 1117 | .await; |
| 1211 | 1118 | |
| 1212 | 1119 | let called_set_breakpoints = Arc::new(AtomicBool::new(false)); |
| 1213 | − client | |
| 1214 | − .on_request::<SetBreakpoints, _>({ | |
| 1215 | − let called_set_breakpoints = called_set_breakpoints.clone(); | |
| 1216 | − move |_, args| { | |
| 1217 | − assert_eq!(path!("/project/main.rs"), args.source.path.unwrap()); | |
| 1218 | − assert_eq!( | |
| 1219 | − vec![SourceBreakpoint { | |
| 1220 | − line: 2, | |
| 1221 | − column: None, | |
| 1222 | − condition: None, | |
| 1223 | − hit_condition: None, | |
| 1224 | − log_message: None, | |
| 1225 | − mode: None | |
| 1226 | − }], | |
| 1227 | − args.breakpoints.unwrap() | |
| 1228 | − ); | |
| 1229 | − assert!(!args.source_modified.unwrap()); | |
| 1120 | + client.on_request::<SetBreakpoints, _>({ | |
| 1121 | + let called_set_breakpoints = called_set_breakpoints.clone(); | |
| 1122 | + move |_, args| { | |
| 1123 | + assert_eq!(path!("/project/main.rs"), args.source.path.unwrap()); | |
| 1124 | + assert_eq!( | |
| 1125 | + vec![SourceBreakpoint { | |
| 1126 | + line: 2, | |
| 1127 | + column: None, | |
| 1128 | + condition: None, | |
| 1129 | + hit_condition: None, | |
| 1130 | + log_message: None, | |
| 1131 | + mode: None | |
| 1132 | + }], | |
| 1133 | + args.breakpoints.unwrap() | |
| 1134 | + ); | |
| 1135 | + assert!(!args.source_modified.unwrap()); | |
| 1230 | 1136 | |
| 1231 | − called_set_breakpoints.store(true, Ordering::SeqCst); | |
| 1137 | + called_set_breakpoints.store(true, Ordering::SeqCst); | |
| 1232 | 1138 | |
| 1233 | − Ok(dap::SetBreakpointsResponse { | |
| 1234 | − breakpoints: Vec::default(), | |
| 1235 | − }) | |
| 1236 | − } | |
| 1237 | − }) | |
| 1238 | − .await; | |
| 1139 | + Ok(dap::SetBreakpointsResponse { | |
| 1140 | + breakpoints: Vec::default(), | |
| 1141 | + }) | |
| 1142 | + } | |
| 1143 | + }); | |
| 1239 | 1144 | |
| 1240 | 1145 | editor.update_in(cx, |editor, window, cx| { |
| 1241 | 1146 | editor.move_down(&actions::MoveDown, window, cx); |
| @@ -1250,32 +1155,30 @@ async fn test_send_breakpoints_when_editor_has_been_saved( · 8 unmodified lines | ||
| 1250 | 1155 | ); |
| 1251 | 1156 | |
| 1252 | 1157 | let called_set_breakpoints = Arc::new(AtomicBool::new(false)); |
| 1253 | − client | |
| 1254 | − .on_request::<SetBreakpoints, _>({ | |
| 1255 | − let called_set_breakpoints = called_set_breakpoints.clone(); | |
| 1256 | − move |_, args| { | |
| 1257 | − assert_eq!(path!("/project/main.rs"), args.source.path.unwrap()); | |
| 1258 | − assert_eq!( | |
| 1259 | − vec![SourceBreakpoint { | |
| 1260 | − line: 3, | |
| 1261 | − column: None, | |
| 1262 | − condition: None, | |
| 1263 | − hit_condition: None, | |
| 1264 | − log_message: None, | |
| 1265 | − mode: None | |
| 1266 | − }], | |
| 1267 | − args.breakpoints.unwrap() | |
| 1268 | − ); | |
| 1269 | − assert!(args.source_modified.unwrap()); | |
| 1158 | + client.on_request::<SetBreakpoints, _>({ | |
| 1159 | + let called_set_breakpoints = called_set_breakpoints.clone(); | |
| 1160 | + move |_, args| { | |
| 1161 | + assert_eq!(path!("/project/main.rs"), args.source.path.unwrap()); | |
| 1162 | + assert_eq!( | |
| 1163 | + vec![SourceBreakpoint { | |
| 1164 | + line: 3, | |
| 1165 | + column: None, | |
| 1166 | + condition: None, | |
| 1167 | + hit_condition: None, | |
| 1168 | + log_message: None, | |
| 1169 | + mode: None | |
| 1170 | + }], | |
| 1171 | + args.breakpoints.unwrap() | |
| 1172 | + ); | |
| 1173 | + assert!(args.source_modified.unwrap()); | |
| 1270 | 1174 | |
| 1271 | − called_set_breakpoints.store(true, Ordering::SeqCst); | |
| 1175 | + called_set_breakpoints.store(true, Ordering::SeqCst); | |
| 1272 | 1176 | |
| 1273 | − Ok(dap::SetBreakpointsResponse { | |
| 1274 | − breakpoints: Vec::default(), | |
| 1275 | − }) | |
| 1276 | − } | |
| 1277 | − }) | |
| 1278 | − .await; | |
| 1177 | + Ok(dap::SetBreakpointsResponse { | |
| 1178 | + breakpoints: Vec::default(), | |
| 1179 | + }) | |
| 1180 | + } | |
| 1181 | + }); | |
| 1279 | 1182 | |
| 1280 | 1183 | editor.update_in(cx, |editor, window, cx| { |
| 1281 | 1184 | editor.move_up(&actions::MoveUp, window, cx); |
| @@ -1387,49 +1290,40 @@ async fn test_unsetting_breakpoints_on_clear_breakpoint_action( · 105 unmodified lines | ||
| 1387 | 1290 | editor.toggle_breakpoint(&actions::ToggleBreakpoint, window, cx); |
| 1388 | 1291 | }); |
| 1389 | 1292 | |
| 1390 | − let task = project.update(cx, |project, cx| { | |
| 1391 | − project.fake_debug_session( | |
| 1392 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 1393 | − None, | |
| 1394 | − false, | |
| 1395 | − cx, | |
| 1396 | − ) | |
| 1397 | − }); | |
| 1398 | − | |
| 1399 | − let session = task.await.unwrap(); | |
| 1293 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 1294 | + .await | |
| 1295 | + .unwrap(); | |
| 1400 | 1296 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 1401 | 1297 | |
| 1402 | 1298 | let called_set_breakpoints = Arc::new(AtomicBool::new(false)); |
| 1403 | 1299 | |
| 1404 | − client | |
| 1405 | − .on_request::<SetBreakpoints, _>({ | |
| 1406 | − let called_set_breakpoints = called_set_breakpoints.clone(); | |
| 1407 | − move |_, args| { | |
| 1408 | − assert!( | |
| 1409 | − args.breakpoints.is_none_or(|bps| bps.is_empty()), | |
| 1410 | − "Send empty breakpoint sets to clear them from DAP servers" | |
| 1411 | − ); | |
| 1300 | + client.on_request::<SetBreakpoints, _>({ | |
| 1301 | + let called_set_breakpoints = called_set_breakpoints.clone(); | |
| 1302 | + move |_, args| { | |
| 1303 | + assert!( | |
| 1304 | + args.breakpoints.is_none_or(|bps| bps.is_empty()), | |
| 1305 | + "Send empty breakpoint sets to clear them from DAP servers" | |
| 1306 | + ); | |
| 1412 | 1307 | |
| 1413 | − match args | |
| 1414 | − .source | |
| 1415 | − .path | |
| 1416 | − .expect("We should always send a breakpoint's path") | |
| 1417 | − .as_str() | |
| 1418 | − { | |
| 1419 | − "/project/main.rs" | "/project/second.rs" => {} | |
| 1420 | − _ => { | |
| 1421 | − panic!("Unset breakpoints for path that doesn't have any") | |
| 1422 | − } | |
| 1308 | + match args | |
| 1309 | + .source | |
| 1310 | + .path | |
| 1311 | + .expect("We should always send a breakpoint's path") | |
| 1312 | + .as_str() | |
| 1313 | + { | |
| 1314 | + "/project/main.rs" | "/project/second.rs" => {} | |
| 1315 | + _ => { | |
| 1316 | + panic!("Unset breakpoints for path that doesn't have any") | |
| 1423 | 1317 | } |
| 1318 | + } | |
| 1424 | 1319 | |
| 1425 | − called_set_breakpoints.store(true, Ordering::SeqCst); | |
| 1320 | + called_set_breakpoints.store(true, Ordering::SeqCst); | |
| 1426 | 1321 | |
| 1427 | − Ok(dap::SetBreakpointsResponse { | |
| 1428 | − breakpoints: Vec::default(), | |
| 1429 | − }) | |
| 1430 | − } | |
| 1431 | − }) | |
| 1432 | − .await; | |
| 1322 | + Ok(dap::SetBreakpointsResponse { | |
| 1323 | + breakpoints: Vec::default(), | |
| 1324 | + }) | |
| 1325 | + } | |
| 1326 | + }); | |
| 1433 | 1327 | |
| 1434 | 1328 | cx.dispatch_action(crate::ClearAllBreakpoints); |
| 1435 | 1329 | cx.run_until_parked(); |
| @@ -1464,13 +1358,20 @@ async fn test_debug_session_is_shutdown_when_attach_and_launch_request_fails( · 28 unmodified lines | ||
| 1464 | 1358 | let workspace = init_test_workspace(&project, cx).await; |
| 1465 | 1359 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 1466 | 1360 | |
| 1467 | − let task = project.update(cx, |project, cx| { | |
| 1468 | − project.fake_debug_session( | |
| 1469 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 1470 | − None, | |
| 1471 | − true, | |
| 1472 | − cx, | |
| 1473 | − ) | |
| 1361 | + let task = project::debugger::test::start_debug_session(&project, cx, |client| { | |
| 1362 | + client.on_request::<dap::requests::Initialize, _>(|_, _| { | |
| 1363 | + Err(ErrorResponse { | |
| 1364 | + error: Some(Message { | |
| 1365 | + format: "failed to launch".to_string(), | |
| 1366 | + id: 1, | |
| 1367 | + variables: None, | |
| 1368 | + send_telemetry: None, | |
| 1369 | + show_user: None, | |
| 1370 | + url: None, | |
| 1371 | + url_label: None, | |
| 1372 | + }), | |
| 1373 | + }) | |
| 1374 | + }); | |
| 1474 | 1375 | }); |
| 1475 | 1376 | |
| 1476 | 1377 | assert!( |
| @@ -4,15 +4,17 @@ use crate::{ · 3 unmodified lines | ||
| 4 | 4 | }; |
| 5 | 5 | use dap::{ |
| 6 | 6 | StoppedEvent, |
| 7 | − requests::{Modules, StackTrace, Threads}, | |
| 7 | + requests::{Initialize, Modules}, | |
| 8 | 8 | }; |
| 9 | 9 | use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext}; |
| 10 | −use project::{FakeFs, Project}; | |
| 10 | +use project::{ | |
| 11 | + FakeFs, Project, | |
| 12 | + debugger::{self}, | |
| 13 | +}; | |
| 11 | 14 | use std::sync::{ |
| 12 | 15 | Arc, |
| 13 | 16 | atomic::{AtomicBool, AtomicI32, Ordering}, |
| 14 | 17 | }; |
| 15 | −use task::LaunchConfig; | |
| 16 | 18 | |
| 17 | 19 | #[gpui::test] |
| 18 | 20 | async fn test_module_list(executor: BackgroundExecutor, cx: &mut TestAppContext) { |
| @@ -29,31 +31,19 @@ async fn test_module_list(executor: BackgroundExecutor, cx: &mut TestAppContext) · 10 unmodified lines | ||
| 29 | 31 | .unwrap(); |
| 30 | 32 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 31 | 33 | |
| 32 | − let task = project.update(cx, |project, cx| { | |
| 33 | − project.fake_debug_session( | |
| 34 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 35 | − Some(dap::Capabilities { | |
| 34 | + let session = debugger::test::start_debug_session(&project, cx, |client| { | |
| 35 | + client.on_request::<Initialize, _>(move |_, _| { | |
| 36 | + Ok(dap::Capabilities { | |
| 36 | 37 | supports_modules_request: Some(true), |
| 37 | 38 | ..Default::default() |
| 38 | − }), | |
| 39 | − false, | |
| 40 | − cx, | |
| 41 | − ) | |
| 42 | − }); | |
| 39 | + }) | |
| 40 | + }); | |
| 41 | + }) | |
| 42 | + .await | |
| 43 | + .unwrap(); | |
| 43 | 44 | |
| 44 | − let session = task.await.unwrap(); | |
| 45 | 45 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 46 | 46 | |
| 47 | − client | |
| 48 | − .on_request::<StackTrace, _>(move |_, args| { | |
| 49 | − assert!(args.thread_id == 1); | |
| 50 | − Ok(dap::StackTraceResponse { | |
| 51 | − stack_frames: Vec::default(), | |
| 52 | − total_frames: None, | |
| 53 | − }) | |
| 54 | − }) | |
| 55 | − .await; | |
| 56 | − | |
| 57 | 47 | let called_modules = Arc::new(AtomicBool::new(false)); |
| 58 | 48 | let modules = vec![ |
| 59 | 49 | dap::Module { |
| @@ -82,38 +72,25 @@ async fn test_module_list(executor: BackgroundExecutor, cx: &mut TestAppContext) · 22 unmodified lines | ||
| 82 | 72 | }, |
| 83 | 73 | ]; |
| 84 | 74 | |
| 85 | − client | |
| 86 | − .on_request::<Threads, _>(move |_, _| { | |
| 87 | − Ok(dap::ThreadsResponse { | |
| 88 | − threads: vec![dap::Thread { | |
| 89 | − id: 1, | |
| 90 | − name: "Thread 1".into(), | |
| 91 | − }], | |
| 75 | + client.on_request::<Modules, _>({ | |
| 76 | + let called_modules = called_modules.clone(); | |
| 77 | + let modules_request_count = AtomicI32::new(0); | |
| 78 | + let modules = modules.clone(); | |
| 79 | + move |_, _| { | |
| 80 | + modules_request_count.fetch_add(1, Ordering::SeqCst); | |
| 81 | + assert_eq!( | |
| 82 | + 1, | |
| 83 | + modules_request_count.load(Ordering::SeqCst), | |
| 84 | + "This request should only be called once from the host" | |
| 85 | + ); | |
| 86 | + called_modules.store(true, Ordering::SeqCst); | |
| 87 | + | |
| 88 | + Ok(dap::ModulesResponse { | |
| 89 | + modules: modules.clone(), | |
| 90 | + total_modules: Some(2u64), | |
| 92 | 91 | }) |
| 93 | − }) | |
| 94 | − .await; | |
| 95 | − | |
| 96 | − client | |
| 97 | − .on_request::<Modules, _>({ | |
| 98 | − let called_modules = called_modules.clone(); | |
| 99 | − let modules_request_count = AtomicI32::new(0); | |
| 100 | − let modules = modules.clone(); | |
| 101 | − move |_, _| { | |
| 102 | − modules_request_count.fetch_add(1, Ordering::SeqCst); | |
| 103 | − assert_eq!( | |
| 104 | − 1, | |
| 105 | − modules_request_count.load(Ordering::SeqCst), | |
| 106 | − "This request should only be called once from the host" | |
| 107 | − ); | |
| 108 | − called_modules.store(true, Ordering::SeqCst); | |
| 109 | − | |
| 110 | − Ok(dap::ModulesResponse { | |
| 111 | − modules: modules.clone(), | |
| 112 | − total_modules: Some(2u64), | |
| 113 | − }) | |
| 114 | − } | |
| 115 | − }) | |
| 116 | − .await; | |
| 92 | + } | |
| 93 | + }); | |
| 117 | 94 | |
| 118 | 95 | client |
| 119 | 96 | .fake_event(dap::messages::Events::Stopped(StoppedEvent { |
| @@ -5,14 +5,13 @@ use crate::{ · 4 unmodified lines | ||
| 5 | 5 | }; |
| 6 | 6 | use dap::{ |
| 7 | 7 | StackFrame, |
| 8 | − requests::{StackTrace, Threads}, | |
| 8 | + requests::{Scopes, StackTrace, Threads}, | |
| 9 | 9 | }; |
| 10 | 10 | use editor::{Editor, ToPoint as _}; |
| 11 | 11 | use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext}; |
| 12 | −use project::{FakeFs, Project}; | |
| 12 | +use project::{FakeFs, Project, debugger}; | |
| 13 | 13 | use serde_json::json; |
| 14 | 14 | use std::sync::Arc; |
| 15 | −use task::LaunchConfig; | |
| 16 | 15 | use unindent::Unindent as _; |
| 17 | 16 | use util::path; |
| 18 | 17 | |
| @@ -51,29 +50,20 @@ async fn test_fetch_initial_stack_frames_and_go_to_stack_frame( · 32 unmodified lines | ||
| 51 | 50 | let project = Project::test(fs, [path!("/project").as_ref()], cx).await; |
| 52 | 51 | let workspace = init_test_workspace(&project, cx).await; |
| 53 | 52 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 54 | − | |
| 55 | − let task = project.update(cx, |project, cx| { | |
| 56 | − project.fake_debug_session( | |
| 57 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 58 | − None, | |
| 59 | − false, | |
| 60 | − cx, | |
| 61 | − ) | |
| 62 | − }); | |
| 63 | − | |
| 64 | − let session = task.await.unwrap(); | |
| 53 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 54 | + .await | |
| 55 | + .unwrap(); | |
| 65 | 56 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 66 | − | |
| 67 | − client | |
| 68 | − .on_request::<Threads, _>(move |_, _| { | |
| 69 | − Ok(dap::ThreadsResponse { | |
| 70 | − threads: vec![dap::Thread { | |
| 71 | − id: 1, | |
| 72 | − name: "Thread 1".into(), | |
| 73 | − }], | |
| 74 | − }) | |
| 57 | + client.on_request::<Scopes, _>(move |_, _| Ok(dap::ScopesResponse { scopes: vec![] })); | |
| 58 | + | |
| 59 | + client.on_request::<Threads, _>(move |_, _| { | |
| 60 | + Ok(dap::ThreadsResponse { | |
| 61 | + threads: vec![dap::Thread { | |
| 62 | + id: 1, | |
| 63 | + name: "Thread 1".into(), | |
| 64 | + }], | |
| 75 | 65 | }) |
| 76 | − .await; | |
| 66 | + }); | |
| 77 | 67 | |
| 78 | 68 | let stack_frames = vec![ |
| 79 | 69 | StackFrame { |
| @@ -122,19 +112,17 @@ async fn test_fetch_initial_stack_frames_and_go_to_stack_frame( · 42 unmodified lines | ||
| 122 | 112 | }, |
| 123 | 113 | ]; |
| 124 | 114 | |
| 125 | − client | |
| 126 | − .on_request::<StackTrace, _>({ | |
| 127 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 128 | − move |_, args| { | |
| 129 | − assert_eq!(1, args.thread_id); | |
| 130 | − | |
| 131 | − Ok(dap::StackTraceResponse { | |
| 132 | − stack_frames: (*stack_frames).clone(), | |
| 133 | − total_frames: None, | |
| 134 | − }) | |
| 135 | − } | |
| 136 | − }) | |
| 137 | − .await; | |
| 115 | + client.on_request::<StackTrace, _>({ | |
| 116 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 117 | + move |_, args| { | |
| 118 | + assert_eq!(1, args.thread_id); | |
| 119 | + | |
| 120 | + Ok(dap::StackTraceResponse { | |
| 121 | + stack_frames: (*stack_frames).clone(), | |
| 122 | + total_frames: None, | |
| 123 | + }) | |
| 124 | + } | |
| 125 | + }); | |
| 138 | 126 | |
| 139 | 127 | client |
| 140 | 128 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -241,29 +229,21 @@ async fn test_select_stack_frame(executor: BackgroundExecutor, cx: &mut TestAppC · 100 unmodified lines | ||
| 241 | 229 | }); |
| 242 | 230 | |
| 243 | 231 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 244 | − | |
| 245 | − let task = project.update(cx, |project, cx| { | |
| 246 | − project.fake_debug_session( | |
| 247 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 248 | − None, | |
| 249 | − false, | |
| 250 | − cx, | |
| 251 | − ) | |
| 252 | − }); | |
| 253 | − | |
| 254 | − let session = task.await.unwrap(); | |
| 232 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 233 | + .await | |
| 234 | + .unwrap(); | |
| 255 | 235 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 256 | 236 | |
| 257 | − client | |
| 258 | − .on_request::<Threads, _>(move |_, _| { | |
| 259 | − Ok(dap::ThreadsResponse { | |
| 260 | − threads: vec![dap::Thread { | |
| 261 | − id: 1, | |
| 262 | − name: "Thread 1".into(), | |
| 263 | − }], | |
| 264 | − }) | |
| 237 | + client.on_request::<Threads, _>(move |_, _| { | |
| 238 | + Ok(dap::ThreadsResponse { | |
| 239 | + threads: vec![dap::Thread { | |
| 240 | + id: 1, | |
| 241 | + name: "Thread 1".into(), | |
| 242 | + }], | |
| 265 | 243 | }) |
| 266 | − .await; | |
| 244 | + }); | |
| 245 | + | |
| 246 | + client.on_request::<Scopes, _>(move |_, _| Ok(dap::ScopesResponse { scopes: vec![] })); | |
| 267 | 247 | |
| 268 | 248 | let stack_frames = vec![ |
| 269 | 249 | StackFrame { |
| @@ -312,19 +292,17 @@ async fn test_select_stack_frame(executor: BackgroundExecutor, cx: &mut TestAppC · 42 unmodified lines | ||
| 312 | 292 | }, |
| 313 | 293 | ]; |
| 314 | 294 | |
| 315 | − client | |
| 316 | − .on_request::<StackTrace, _>({ | |
| 317 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 318 | − move |_, args| { | |
| 319 | − assert_eq!(1, args.thread_id); | |
| 320 | − | |
| 321 | − Ok(dap::StackTraceResponse { | |
| 322 | − stack_frames: (*stack_frames).clone(), | |
| 323 | − total_frames: None, | |
| 324 | − }) | |
| 325 | − } | |
| 326 | − }) | |
| 327 | − .await; | |
| 295 | + client.on_request::<StackTrace, _>({ | |
| 296 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 297 | + move |_, args| { | |
| 298 | + assert_eq!(1, args.thread_id); | |
| 299 | + | |
| 300 | + Ok(dap::StackTraceResponse { | |
| 301 | + stack_frames: (*stack_frames).clone(), | |
| 302 | + total_frames: None, | |
| 303 | + }) | |
| 304 | + } | |
| 305 | + }); | |
| 328 | 306 | |
| 329 | 307 | client |
| 330 | 308 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -517,28 +495,21 @@ async fn test_collapsed_entries(executor: BackgroundExecutor, cx: &mut TestAppCo · 186 unmodified lines | ||
| 517 | 495 | let workspace = init_test_workspace(&project, cx).await; |
| 518 | 496 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 519 | 497 | |
| 520 | − let task = project.update(cx, |project, cx| { | |
| 521 | − project.fake_debug_session( | |
| 522 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 523 | − None, | |
| 524 | − false, | |
| 525 | − cx, | |
| 526 | − ) | |
| 527 | − }); | |
| 528 | − | |
| 529 | − let session = task.await.unwrap(); | |
| 498 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 499 | + .await | |
| 500 | + .unwrap(); | |
| 530 | 501 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 531 | 502 | |
| 532 | − client | |
| 533 | − .on_request::<Threads, _>(move |_, _| { | |
| 534 | − Ok(dap::ThreadsResponse { | |
| 535 | − threads: vec![dap::Thread { | |
| 536 | − id: 1, | |
| 537 | − name: "Thread 1".into(), | |
| 538 | − }], | |
| 539 | − }) | |
| 503 | + client.on_request::<Threads, _>(move |_, _| { | |
| 504 | + Ok(dap::ThreadsResponse { | |
| 505 | + threads: vec![dap::Thread { | |
| 506 | + id: 1, | |
| 507 | + name: "Thread 1".into(), | |
| 508 | + }], | |
| 540 | 509 | }) |
| 541 | − .await; | |
| 510 | + }); | |
| 511 | + | |
| 512 | + client.on_request::<Scopes, _>(move |_, _| Ok(dap::ScopesResponse { scopes: vec![] })); | |
| 542 | 513 | |
| 543 | 514 | let stack_frames = vec![ |
| 544 | 515 | StackFrame { |
| @@ -697,19 +668,17 @@ async fn test_collapsed_entries(executor: BackgroundExecutor, cx: &mut TestAppCo · 152 unmodified lines | ||
| 697 | 668 | }, |
| 698 | 669 | ]; |
| 699 | 670 | |
| 700 | − client | |
| 701 | − .on_request::<StackTrace, _>({ | |
| 702 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 703 | − move |_, args| { | |
| 704 | − assert_eq!(1, args.thread_id); | |
| 705 | − | |
| 706 | − Ok(dap::StackTraceResponse { | |
| 707 | − stack_frames: (*stack_frames).clone(), | |
| 708 | − total_frames: None, | |
| 709 | − }) | |
| 710 | − } | |
| 711 | − }) | |
| 712 | − .await; | |
| 671 | + client.on_request::<StackTrace, _>({ | |
| 672 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 673 | + move |_, args| { | |
| 674 | + assert_eq!(1, args.thread_id); | |
| 675 | + | |
| 676 | + Ok(dap::StackTraceResponse { | |
| 677 | + stack_frames: (*stack_frames).clone(), | |
| 678 | + total_frames: None, | |
| 679 | + }) | |
| 680 | + } | |
| 681 | + }); | |
| 713 | 682 | |
| 714 | 683 | client |
| 715 | 684 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -15,9 +15,8 @@ use dap::{ · 14 unmodified lines | ||
| 15 | 15 | }; |
| 16 | 16 | use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext}; |
| 17 | 17 | use menu::{SelectFirst, SelectNext, SelectPrevious}; |
| 18 | −use project::{FakeFs, Project}; | |
| 18 | +use project::{FakeFs, Project, debugger}; | |
| 19 | 19 | use serde_json::json; |
| 20 | −use task::LaunchConfig; | |
| 21 | 20 | use unindent::Unindent as _; |
| 22 | 21 | use util::path; |
| 23 | 22 | |
| @@ -55,29 +54,19 @@ async fn test_basic_fetch_initial_scope_and_variables( · 31 unmodified lines | ||
| 55 | 54 | }) |
| 56 | 55 | .unwrap(); |
| 57 | 56 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 58 | − | |
| 59 | − let task = project.update(cx, |project, cx| { | |
| 60 | − project.fake_debug_session( | |
| 61 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 62 | − None, | |
| 63 | − false, | |
| 64 | − cx, | |
| 65 | − ) | |
| 66 | − }); | |
| 67 | − | |
| 68 | − let session = task.await.unwrap(); | |
| 57 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 58 | + .await | |
| 59 | + .unwrap(); | |
| 69 | 60 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 70 | 61 | |
| 71 | − client | |
| 72 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 73 | − Ok(dap::ThreadsResponse { | |
| 74 | − threads: vec![dap::Thread { | |
| 75 | − id: 1, | |
| 76 | − name: "Thread 1".into(), | |
| 77 | − }], | |
| 78 | − }) | |
| 62 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 63 | + Ok(dap::ThreadsResponse { | |
| 64 | + threads: vec![dap::Thread { | |
| 65 | + id: 1, | |
| 66 | + name: "Thread 1".into(), | |
| 67 | + }], | |
| 79 | 68 | }) |
| 80 | − .await; | |
| 69 | + }); | |
| 81 | 70 | |
| 82 | 71 | let stack_frames = vec![StackFrame { |
| 83 | 72 | id: 1, |
| @@ -102,19 +91,17 @@ async fn test_basic_fetch_initial_scope_and_variables( · 18 unmodified lines | ||
| 102 | 91 | presentation_hint: None, |
| 103 | 92 | }]; |
| 104 | 93 | |
| 105 | − client | |
| 106 | − .on_request::<StackTrace, _>({ | |
| 107 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 108 | − move |_, args| { | |
| 109 | − assert_eq!(1, args.thread_id); | |
| 110 | − | |
| 111 | − Ok(dap::StackTraceResponse { | |
| 112 | − stack_frames: (*stack_frames).clone(), | |
| 113 | − total_frames: None, | |
| 114 | − }) | |
| 115 | − } | |
| 116 | − }) | |
| 117 | − .await; | |
| 94 | + client.on_request::<StackTrace, _>({ | |
| 95 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 96 | + move |_, args| { | |
| 97 | + assert_eq!(1, args.thread_id); | |
| 98 | + | |
| 99 | + Ok(dap::StackTraceResponse { | |
| 100 | + stack_frames: (*stack_frames).clone(), | |
| 101 | + total_frames: None, | |
| 102 | + }) | |
| 103 | + } | |
| 104 | + }); | |
| 118 | 105 | |
| 119 | 106 | let scopes = vec![Scope { |
| 120 | 107 | name: "Scope 1".into(), |
| @@ -130,18 +117,16 @@ async fn test_basic_fetch_initial_scope_and_variables( · 9 unmodified lines | ||
| 130 | 117 | end_column: None, |
| 131 | 118 | }]; |
| 132 | 119 | |
| 133 | − client | |
| 134 | − .on_request::<Scopes, _>({ | |
| 135 | − let scopes = Arc::new(scopes.clone()); | |
| 136 | − move |_, args| { | |
| 137 | − assert_eq!(1, args.frame_id); | |
| 120 | + client.on_request::<Scopes, _>({ | |
| 121 | + let scopes = Arc::new(scopes.clone()); | |
| 122 | + move |_, args| { | |
| 123 | + assert_eq!(1, args.frame_id); | |
| 138 | 124 | |
| 139 | − Ok(dap::ScopesResponse { | |
| 140 | − scopes: (*scopes).clone(), | |
| 141 | − }) | |
| 142 | − } | |
| 143 | − }) | |
| 144 | − .await; | |
| 125 | + Ok(dap::ScopesResponse { | |
| 126 | + scopes: (*scopes).clone(), | |
| 127 | + }) | |
| 128 | + } | |
| 129 | + }); | |
| 145 | 130 | |
| 146 | 131 | let variables = vec![ |
| 147 | 132 | Variable { |
| @@ -172,18 +157,16 @@ async fn test_basic_fetch_initial_scope_and_variables( · 24 unmodified lines | ||
| 172 | 157 | }, |
| 173 | 158 | ]; |
| 174 | 159 | |
| 175 | − client | |
| 176 | − .on_request::<Variables, _>({ | |
| 177 | − let variables = Arc::new(variables.clone()); | |
| 178 | − move |_, args| { | |
| 179 | − assert_eq!(2, args.variables_reference); | |
| 160 | + client.on_request::<Variables, _>({ | |
| 161 | + let variables = Arc::new(variables.clone()); | |
| 162 | + move |_, args| { | |
| 163 | + assert_eq!(2, args.variables_reference); | |
| 180 | 164 | |
| 181 | − Ok(dap::VariablesResponse { | |
| 182 | − variables: (*variables).clone(), | |
| 183 | − }) | |
| 184 | − } | |
| 185 | − }) | |
| 186 | − .await; | |
| 165 | + Ok(dap::VariablesResponse { | |
| 166 | + variables: (*variables).clone(), | |
| 167 | + }) | |
| 168 | + } | |
| 169 | + }); | |
| 187 | 170 | |
| 188 | 171 | client |
| 189 | 172 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -283,39 +266,28 @@ async fn test_fetch_variables_for_multiple_scopes( · 93 unmodified lines | ||
| 283 | 266 | .unwrap(); |
| 284 | 267 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 285 | 268 | |
| 286 | − let task = project.update(cx, |project, cx| { | |
| 287 | − project.fake_debug_session( | |
| 288 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 289 | − None, | |
| 290 | − false, | |
| 291 | − cx, | |
| 292 | − ) | |
| 293 | − }); | |
| 294 | − | |
| 295 | − let session = task.await.unwrap(); | |
| 269 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 270 | + .await | |
| 271 | + .unwrap(); | |
| 296 | 272 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 297 | 273 | |
| 298 | − client | |
| 299 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 300 | − Ok(dap::ThreadsResponse { | |
| 301 | − threads: vec![dap::Thread { | |
| 302 | − id: 1, | |
| 303 | − name: "Thread 1".into(), | |
| 304 | − }], | |
| 305 | − }) | |
| 274 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 275 | + Ok(dap::ThreadsResponse { | |
| 276 | + threads: vec![dap::Thread { | |
| 277 | + id: 1, | |
| 278 | + name: "Thread 1".into(), | |
| 279 | + }], | |
| 306 | 280 | }) |
| 307 | − .await; | |
| 281 | + }); | |
| 308 | 282 | |
| 309 | − client | |
| 310 | − .on_request::<Initialize, _>(move |_, _| { | |
| 311 | − Ok(dap::Capabilities { | |
| 312 | − supports_step_back: Some(false), | |
| 313 | − ..Default::default() | |
| 314 | − }) | |
| 283 | + client.on_request::<Initialize, _>(move |_, _| { | |
| 284 | + Ok(dap::Capabilities { | |
| 285 | + supports_step_back: Some(false), | |
| 286 | + ..Default::default() | |
| 315 | 287 | }) |
| 316 | − .await; | |
| 288 | + }); | |
| 317 | 289 | |
| 318 | − client.on_request::<Launch, _>(move |_, _| Ok(())).await; | |
| 290 | + client.on_request::<Launch, _>(move |_, _| Ok(())); | |
| 319 | 291 | |
| 320 | 292 | let stack_frames = vec![StackFrame { |
| 321 | 293 | id: 1, |
| @@ -340,19 +312,17 @@ async fn test_fetch_variables_for_multiple_scopes( · 18 unmodified lines | ||
| 340 | 312 | presentation_hint: None, |
| 341 | 313 | }]; |
| 342 | 314 | |
| 343 | − client | |
| 344 | − .on_request::<StackTrace, _>({ | |
| 345 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 346 | − move |_, args| { | |
| 347 | − assert_eq!(1, args.thread_id); | |
| 348 | − | |
| 349 | − Ok(dap::StackTraceResponse { | |
| 350 | − stack_frames: (*stack_frames).clone(), | |
| 351 | − total_frames: None, | |
| 352 | − }) | |
| 353 | − } | |
| 354 | − }) | |
| 355 | − .await; | |
| 315 | + client.on_request::<StackTrace, _>({ | |
| 316 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 317 | + move |_, args| { | |
| 318 | + assert_eq!(1, args.thread_id); | |
| 319 | + | |
| 320 | + Ok(dap::StackTraceResponse { | |
| 321 | + stack_frames: (*stack_frames).clone(), | |
| 322 | + total_frames: None, | |
| 323 | + }) | |
| 324 | + } | |
| 325 | + }); | |
| 356 | 326 | |
| 357 | 327 | let scopes = vec![ |
| 358 | 328 | Scope { |
| @@ -383,18 +353,16 @@ async fn test_fetch_variables_for_multiple_scopes( · 24 unmodified lines | ||
| 383 | 353 | }, |
| 384 | 354 | ]; |
| 385 | 355 | |
| 386 | − client | |
| 387 | − .on_request::<Scopes, _>({ | |
| 388 | − let scopes = Arc::new(scopes.clone()); | |
| 389 | − move |_, args| { | |
| 390 | − assert_eq!(1, args.frame_id); | |
| 356 | + client.on_request::<Scopes, _>({ | |
| 357 | + let scopes = Arc::new(scopes.clone()); | |
| 358 | + move |_, args| { | |
| 359 | + assert_eq!(1, args.frame_id); | |
| 391 | 360 | |
| 392 | − Ok(dap::ScopesResponse { | |
| 393 | − scopes: (*scopes).clone(), | |
| 394 | − }) | |
| 395 | − } | |
| 396 | − }) | |
| 397 | − .await; | |
| 361 | + Ok(dap::ScopesResponse { | |
| 362 | + scopes: (*scopes).clone(), | |
| 363 | + }) | |
| 364 | + } | |
| 365 | + }); | |
| 398 | 366 | |
| 399 | 367 | let mut variables = HashMap::default(); |
| 400 | 368 | variables.insert( |
| @@ -445,16 +413,14 @@ async fn test_fetch_variables_for_multiple_scopes( · 44 unmodified lines | ||
| 445 | 413 | }], |
| 446 | 414 | ); |
| 447 | 415 | |
| 448 | − client | |
| 449 | − .on_request::<Variables, _>({ | |
| 450 | − let variables = Arc::new(variables.clone()); | |
| 451 | − move |_, args| { | |
| 452 | − Ok(dap::VariablesResponse { | |
| 453 | − variables: variables.get(&args.variables_reference).unwrap().clone(), | |
| 454 | − }) | |
| 455 | − } | |
| 456 | − }) | |
| 457 | − .await; | |
| 416 | + client.on_request::<Variables, _>({ | |
| 417 | + let variables = Arc::new(variables.clone()); | |
| 418 | + move |_, args| { | |
| 419 | + Ok(dap::VariablesResponse { | |
| 420 | + variables: variables.get(&args.variables_reference).unwrap().clone(), | |
| 421 | + }) | |
| 422 | + } | |
| 423 | + }); | |
| 458 | 424 | |
| 459 | 425 | client |
| 460 | 426 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -562,40 +528,28 @@ async fn test_keyboard_navigation(executor: BackgroundExecutor, cx: &mut TestApp · 101 unmodified lines | ||
| 562 | 528 | }) |
| 563 | 529 | .unwrap(); |
| 564 | 530 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 565 | − | |
| 566 | − let task = project.update(cx, |project, cx| { | |
| 567 | − project.fake_debug_session( | |
| 568 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 569 | − None, | |
| 570 | − false, | |
| 571 | − cx, | |
| 572 | − ) | |
| 573 | − }); | |
| 574 | − | |
| 575 | − let session = task.await.unwrap(); | |
| 531 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 532 | + .await | |
| 533 | + .unwrap(); | |
| 576 | 534 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 577 | 535 | |
| 578 | − client | |
| 579 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 580 | − Ok(dap::ThreadsResponse { | |
| 581 | − threads: vec![dap::Thread { | |
| 582 | − id: 1, | |
| 583 | − name: "Thread 1".into(), | |
| 584 | − }], | |
| 585 | − }) | |
| 536 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 537 | + Ok(dap::ThreadsResponse { | |
| 538 | + threads: vec![dap::Thread { | |
| 539 | + id: 1, | |
| 540 | + name: "Thread 1".into(), | |
| 541 | + }], | |
| 586 | 542 | }) |
| 587 | − .await; | |
| 543 | + }); | |
| 588 | 544 | |
| 589 | − client | |
| 590 | − .on_request::<Initialize, _>(move |_, _| { | |
| 591 | − Ok(dap::Capabilities { | |
| 592 | − supports_step_back: Some(false), | |
| 593 | − ..Default::default() | |
| 594 | − }) | |
| 545 | + client.on_request::<Initialize, _>(move |_, _| { | |
| 546 | + Ok(dap::Capabilities { | |
| 547 | + supports_step_back: Some(false), | |
| 548 | + ..Default::default() | |
| 595 | 549 | }) |
| 596 | − .await; | |
| 550 | + }); | |
| 597 | 551 | |
| 598 | − client.on_request::<Launch, _>(move |_, _| Ok(())).await; | |
| 552 | + client.on_request::<Launch, _>(move |_, _| Ok(())); | |
| 599 | 553 | |
| 600 | 554 | let stack_frames = vec![StackFrame { |
| 601 | 555 | id: 1, |
| @@ -620,19 +574,17 @@ async fn test_keyboard_navigation(executor: BackgroundExecutor, cx: &mut TestApp · 18 unmodified lines | ||
| 620 | 574 | presentation_hint: None, |
| 621 | 575 | }]; |
| 622 | 576 | |
| 623 | − client | |
| 624 | − .on_request::<StackTrace, _>({ | |
| 625 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 626 | − move |_, args| { | |
| 627 | − assert_eq!(1, args.thread_id); | |
| 628 | − | |
| 629 | − Ok(dap::StackTraceResponse { | |
| 630 | − stack_frames: (*stack_frames).clone(), | |
| 631 | − total_frames: None, | |
| 632 | − }) | |
| 633 | − } | |
| 634 | − }) | |
| 635 | − .await; | |
| 577 | + client.on_request::<StackTrace, _>({ | |
| 578 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 579 | + move |_, args| { | |
| 580 | + assert_eq!(1, args.thread_id); | |
| 581 | + | |
| 582 | + Ok(dap::StackTraceResponse { | |
| 583 | + stack_frames: (*stack_frames).clone(), | |
| 584 | + total_frames: None, | |
| 585 | + }) | |
| 586 | + } | |
| 587 | + }); | |
| 636 | 588 | |
| 637 | 589 | let scopes = vec![ |
| 638 | 590 | Scope { |
| @@ -663,18 +615,16 @@ async fn test_keyboard_navigation(executor: BackgroundExecutor, cx: &mut TestApp · 24 unmodified lines | ||
| 663 | 615 | }, |
| 664 | 616 | ]; |
| 665 | 617 | |
| 666 | − client | |
| 667 | − .on_request::<Scopes, _>({ | |
| 668 | − let scopes = Arc::new(scopes.clone()); | |
| 669 | − move |_, args| { | |
| 670 | − assert_eq!(1, args.frame_id); | |
| 618 | + client.on_request::<Scopes, _>({ | |
| 619 | + let scopes = Arc::new(scopes.clone()); | |
| 620 | + move |_, args| { | |
| 621 | + assert_eq!(1, args.frame_id); | |
| 671 | 622 | |
| 672 | − Ok(dap::ScopesResponse { | |
| 673 | − scopes: (*scopes).clone(), | |
| 674 | − }) | |
| 675 | − } | |
| 676 | − }) | |
| 677 | − .await; | |
| 623 | + Ok(dap::ScopesResponse { | |
| 624 | + scopes: (*scopes).clone(), | |
| 625 | + }) | |
| 626 | + } | |
| 627 | + }); | |
| 678 | 628 | |
| 679 | 629 | let scope1_variables = vec![ |
| 680 | 630 | Variable { |
| @@ -748,25 +698,23 @@ async fn test_keyboard_navigation(executor: BackgroundExecutor, cx: &mut TestApp · 67 unmodified lines | ||
| 748 | 698 | value_location_reference: None, |
| 749 | 699 | }]; |
| 750 | 700 | |
| 751 | − client | |
| 752 | − .on_request::<Variables, _>({ | |
| 753 | − let scope1_variables = Arc::new(scope1_variables.clone()); | |
| 754 | − let nested_variables = Arc::new(nested_variables.clone()); | |
| 755 | − let scope2_variables = Arc::new(scope2_variables.clone()); | |
| 756 | − move |_, args| match args.variables_reference { | |
| 757 | − 4 => Ok(dap::VariablesResponse { | |
| 758 | − variables: (*scope2_variables).clone(), | |
| 759 | − }), | |
| 760 | − 3 => Ok(dap::VariablesResponse { | |
| 761 | − variables: (*nested_variables).clone(), | |
| 762 | − }), | |
| 763 | − 2 => Ok(dap::VariablesResponse { | |
| 764 | − variables: (*scope1_variables).clone(), | |
| 765 | − }), | |
| 766 | − id => unreachable!("unexpected variables reference {id}"), | |
| 767 | − } | |
| 768 | − }) | |
| 769 | − .await; | |
| 701 | + client.on_request::<Variables, _>({ | |
| 702 | + let scope1_variables = Arc::new(scope1_variables.clone()); | |
| 703 | + let nested_variables = Arc::new(nested_variables.clone()); | |
| 704 | + let scope2_variables = Arc::new(scope2_variables.clone()); | |
| 705 | + move |_, args| match args.variables_reference { | |
| 706 | + 4 => Ok(dap::VariablesResponse { | |
| 707 | + variables: (*scope2_variables).clone(), | |
| 708 | + }), | |
| 709 | + 3 => Ok(dap::VariablesResponse { | |
| 710 | + variables: (*nested_variables).clone(), | |
| 711 | + }), | |
| 712 | + 2 => Ok(dap::VariablesResponse { | |
| 713 | + variables: (*scope1_variables).clone(), | |
| 714 | + }), | |
| 715 | + id => unreachable!("unexpected variables reference {id}"), | |
| 716 | + } | |
| 717 | + }); | |
| 770 | 718 | |
| 771 | 719 | client |
| 772 | 720 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -1365,39 +1313,28 @@ async fn test_variable_list_only_sends_requests_when_rendering( · 592 unmodified lines | ||
| 1365 | 1313 | let workspace = init_test_workspace(&project, cx).await; |
| 1366 | 1314 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 1367 | 1315 | |
| 1368 | − let task = project.update(cx, |project, cx| { | |
| 1369 | − project.fake_debug_session( | |
| 1370 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 1371 | − None, | |
| 1372 | − false, | |
| 1373 | − cx, | |
| 1374 | − ) | |
| 1375 | − }); | |
| 1376 | − | |
| 1377 | − let session = task.await.unwrap(); | |
| 1316 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 1317 | + .await | |
| 1318 | + .unwrap(); | |
| 1378 | 1319 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 1379 | 1320 | |
| 1380 | − client | |
| 1381 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 1382 | − Ok(dap::ThreadsResponse { | |
| 1383 | − threads: vec![dap::Thread { | |
| 1384 | − id: 1, | |
| 1385 | − name: "Thread 1".into(), | |
| 1386 | − }], | |
| 1387 | − }) | |
| 1321 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 1322 | + Ok(dap::ThreadsResponse { | |
| 1323 | + threads: vec![dap::Thread { | |
| 1324 | + id: 1, | |
| 1325 | + name: "Thread 1".into(), | |
| 1326 | + }], | |
| 1388 | 1327 | }) |
| 1389 | − .await; | |
| 1328 | + }); | |
| 1390 | 1329 | |
| 1391 | − client | |
| 1392 | − .on_request::<Initialize, _>(move |_, _| { | |
| 1393 | − Ok(dap::Capabilities { | |
| 1394 | − supports_step_back: Some(false), | |
| 1395 | − ..Default::default() | |
| 1396 | − }) | |
| 1330 | + client.on_request::<Initialize, _>(move |_, _| { | |
| 1331 | + Ok(dap::Capabilities { | |
| 1332 | + supports_step_back: Some(false), | |
| 1333 | + ..Default::default() | |
| 1397 | 1334 | }) |
| 1398 | − .await; | |
| 1335 | + }); | |
| 1399 | 1336 | |
| 1400 | − client.on_request::<Launch, _>(move |_, _| Ok(())).await; | |
| 1337 | + client.on_request::<Launch, _>(move |_, _| Ok(())); | |
| 1401 | 1338 | |
| 1402 | 1339 | let stack_frames = vec![ |
| 1403 | 1340 | StackFrame { |
| @@ -1446,19 +1383,17 @@ async fn test_variable_list_only_sends_requests_when_rendering( · 42 unmodified lines | ||
| 1446 | 1383 | }, |
| 1447 | 1384 | ]; |
| 1448 | 1385 | |
| 1449 | − client | |
| 1450 | − .on_request::<StackTrace, _>({ | |
| 1451 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 1452 | − move |_, args| { | |
| 1453 | − assert_eq!(1, args.thread_id); | |
| 1454 | − | |
| 1455 | − Ok(dap::StackTraceResponse { | |
| 1456 | − stack_frames: (*stack_frames).clone(), | |
| 1457 | − total_frames: None, | |
| 1458 | − }) | |
| 1459 | − } | |
| 1460 | − }) | |
| 1461 | − .await; | |
| 1386 | + client.on_request::<StackTrace, _>({ | |
| 1387 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 1388 | + move |_, args| { | |
| 1389 | + assert_eq!(1, args.thread_id); | |
| 1390 | + | |
| 1391 | + Ok(dap::StackTraceResponse { | |
| 1392 | + stack_frames: (*stack_frames).clone(), | |
| 1393 | + total_frames: None, | |
| 1394 | + }) | |
| 1395 | + } | |
| 1396 | + }); | |
| 1462 | 1397 | |
| 1463 | 1398 | let frame_1_scopes = vec![Scope { |
| 1464 | 1399 | name: "Frame 1 Scope 1".into(), |
| @@ -1476,25 +1411,23 @@ async fn test_variable_list_only_sends_requests_when_rendering( · 11 unmodified lines | ||
| 1476 | 1411 | |
| 1477 | 1412 | let made_scopes_request = Arc::new(AtomicBool::new(false)); |
| 1478 | 1413 | |
| 1479 | − client | |
| 1480 | − .on_request::<Scopes, _>({ | |
| 1481 | − let frame_1_scopes = Arc::new(frame_1_scopes.clone()); | |
| 1482 | − let made_scopes_request = made_scopes_request.clone(); | |
| 1483 | − move |_, args| { | |
| 1484 | − assert_eq!(1, args.frame_id); | |
| 1485 | − assert!( | |
| 1486 | − !made_scopes_request.load(Ordering::SeqCst), | |
| 1487 | − "We should be caching the scope request" | |
| 1488 | − ); | |
| 1414 | + client.on_request::<Scopes, _>({ | |
| 1415 | + let frame_1_scopes = Arc::new(frame_1_scopes.clone()); | |
| 1416 | + let made_scopes_request = made_scopes_request.clone(); | |
| 1417 | + move |_, args| { | |
| 1418 | + assert_eq!(1, args.frame_id); | |
| 1419 | + assert!( | |
| 1420 | + !made_scopes_request.load(Ordering::SeqCst), | |
| 1421 | + "We should be caching the scope request" | |
| 1422 | + ); | |
| 1489 | 1423 | |
| 1490 | − made_scopes_request.store(true, Ordering::SeqCst); | |
| 1424 | + made_scopes_request.store(true, Ordering::SeqCst); | |
| 1491 | 1425 | |
| 1492 | − Ok(dap::ScopesResponse { | |
| 1493 | − scopes: (*frame_1_scopes).clone(), | |
| 1494 | − }) | |
| 1495 | − } | |
| 1496 | − }) | |
| 1497 | − .await; | |
| 1426 | + Ok(dap::ScopesResponse { | |
| 1427 | + scopes: (*frame_1_scopes).clone(), | |
| 1428 | + }) | |
| 1429 | + } | |
| 1430 | + }); | |
| 1498 | 1431 | |
| 1499 | 1432 | let frame_1_variables = vec![ |
| 1500 | 1433 | Variable { |
| @@ -1525,18 +1458,16 @@ async fn test_variable_list_only_sends_requests_when_rendering( · 24 unmodified lines | ||
| 1525 | 1458 | }, |
| 1526 | 1459 | ]; |
| 1527 | 1460 | |
| 1528 | − client | |
| 1529 | − .on_request::<Variables, _>({ | |
| 1530 | − let frame_1_variables = Arc::new(frame_1_variables.clone()); | |
| 1531 | − move |_, args| { | |
| 1532 | − assert_eq!(2, args.variables_reference); | |
| 1461 | + client.on_request::<Variables, _>({ | |
| 1462 | + let frame_1_variables = Arc::new(frame_1_variables.clone()); | |
| 1463 | + move |_, args| { | |
| 1464 | + assert_eq!(2, args.variables_reference); | |
| 1533 | 1465 | |
| 1534 | − Ok(dap::VariablesResponse { | |
| 1535 | − variables: (*frame_1_variables).clone(), | |
| 1536 | − }) | |
| 1537 | − } | |
| 1538 | − }) | |
| 1539 | − .await; | |
| 1466 | + Ok(dap::VariablesResponse { | |
| 1467 | + variables: (*frame_1_variables).clone(), | |
| 1468 | + }) | |
| 1469 | + } | |
| 1470 | + }); | |
| 1540 | 1471 | |
| 1541 | 1472 | cx.run_until_parked(); |
| 1542 | 1473 | |
| @@ -1629,39 +1560,28 @@ async fn test_it_fetches_scopes_variables_when_you_select_a_stack_frame( · 86 unmodified lines | ||
| 1629 | 1560 | .unwrap(); |
| 1630 | 1561 | let cx = &mut VisualTestContext::from_window(*workspace, cx); |
| 1631 | 1562 | |
| 1632 | − let task = project.update(cx, |project, cx| { | |
| 1633 | − project.fake_debug_session( | |
| 1634 | − dap::DebugRequestType::Launch(LaunchConfig::default()), | |
| 1635 | − None, | |
| 1636 | − false, | |
| 1637 | − cx, | |
| 1638 | − ) | |
| 1639 | − }); | |
| 1640 | − | |
| 1641 | − let session = task.await.unwrap(); | |
| 1563 | + let session = debugger::test::start_debug_session(&project, cx, |_| {}) | |
| 1564 | + .await | |
| 1565 | + .unwrap(); | |
| 1642 | 1566 | let client = session.update(cx, |session, _| session.adapter_client().unwrap()); |
| 1643 | 1567 | |
| 1644 | − client | |
| 1645 | − .on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 1646 | − Ok(dap::ThreadsResponse { | |
| 1647 | − threads: vec![dap::Thread { | |
| 1648 | − id: 1, | |
| 1649 | − name: "Thread 1".into(), | |
| 1650 | − }], | |
| 1651 | − }) | |
| 1568 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 1569 | + Ok(dap::ThreadsResponse { | |
| 1570 | + threads: vec![dap::Thread { | |
| 1571 | + id: 1, | |
| 1572 | + name: "Thread 1".into(), | |
| 1573 | + }], | |
| 1652 | 1574 | }) |
| 1653 | − .await; | |
| 1575 | + }); | |
| 1654 | 1576 | |
| 1655 | − client | |
| 1656 | − .on_request::<Initialize, _>(move |_, _| { | |
| 1657 | − Ok(dap::Capabilities { | |
| 1658 | − supports_step_back: Some(false), | |
| 1659 | − ..Default::default() | |
| 1660 | − }) | |
| 1577 | + client.on_request::<Initialize, _>(move |_, _| { | |
| 1578 | + Ok(dap::Capabilities { | |
| 1579 | + supports_step_back: Some(false), | |
| 1580 | + ..Default::default() | |
| 1661 | 1581 | }) |
| 1662 | − .await; | |
| 1582 | + }); | |
| 1663 | 1583 | |
| 1664 | − client.on_request::<Launch, _>(move |_, _| Ok(())).await; | |
| 1584 | + client.on_request::<Launch, _>(move |_, _| Ok(())); | |
| 1665 | 1585 | |
| 1666 | 1586 | let stack_frames = vec![ |
| 1667 | 1587 | StackFrame { |
| @@ -1710,19 +1630,17 @@ async fn test_it_fetches_scopes_variables_when_you_select_a_stack_frame( · 42 unmodified lines | ||
| 1710 | 1630 | }, |
| 1711 | 1631 | ]; |
| 1712 | 1632 | |
| 1713 | − client | |
| 1714 | − .on_request::<StackTrace, _>({ | |
| 1715 | − let stack_frames = Arc::new(stack_frames.clone()); | |
| 1716 | − move |_, args| { | |
| 1717 | − assert_eq!(1, args.thread_id); | |
| 1718 | − | |
| 1719 | − Ok(dap::StackTraceResponse { | |
| 1720 | − stack_frames: (*stack_frames).clone(), | |
| 1721 | − total_frames: None, | |
| 1722 | − }) | |
| 1723 | − } | |
| 1724 | − }) | |
| 1725 | − .await; | |
| 1633 | + client.on_request::<StackTrace, _>({ | |
| 1634 | + let stack_frames = Arc::new(stack_frames.clone()); | |
| 1635 | + move |_, args| { | |
| 1636 | + assert_eq!(1, args.thread_id); | |
| 1637 | + | |
| 1638 | + Ok(dap::StackTraceResponse { | |
| 1639 | + stack_frames: (*stack_frames).clone(), | |
| 1640 | + total_frames: None, | |
| 1641 | + }) | |
| 1642 | + } | |
| 1643 | + }); | |
| 1726 | 1644 | |
| 1727 | 1645 | let frame_1_scopes = vec![Scope { |
| 1728 | 1646 | name: "Frame 1 Scope 1".into(), |
| @@ -1757,30 +1675,28 @@ async fn test_it_fetches_scopes_variables_when_you_select_a_stack_frame( · 28 unmodified lines | ||
| 1757 | 1675 | let called_second_stack_frame = Arc::new(AtomicBool::new(false)); |
| 1758 | 1676 | let called_first_stack_frame = Arc::new(AtomicBool::new(false)); |
| 1759 | 1677 | |
| 1760 | − client | |
| 1761 | − .on_request::<Scopes, _>({ | |
| 1762 | − let frame_1_scopes = Arc::new(frame_1_scopes.clone()); | |
| 1763 | − let frame_2_scopes = Arc::new(frame_2_scopes.clone()); | |
| 1764 | − let called_first_stack_frame = called_first_stack_frame.clone(); | |
| 1765 | − let called_second_stack_frame = called_second_stack_frame.clone(); | |
| 1766 | − move |_, args| match args.frame_id { | |
| 1767 | − 1 => { | |
| 1768 | − called_first_stack_frame.store(true, Ordering::SeqCst); | |
| 1769 | − Ok(dap::ScopesResponse { | |
| 1770 | − scopes: (*frame_1_scopes).clone(), | |
| 1771 | − }) | |
| 1772 | − } | |
| 1773 | − 2 => { | |
| 1774 | − called_second_stack_frame.store(true, Ordering::SeqCst); | |
| 1775 | − | |
| 1776 | − Ok(dap::ScopesResponse { | |
| 1777 | − scopes: (*frame_2_scopes).clone(), | |
| 1778 | − }) | |
| 1779 | − } | |
| 1780 | − _ => panic!("Made a scopes request with an invalid frame id"), | |
| 1678 | + client.on_request::<Scopes, _>({ | |
| 1679 | + let frame_1_scopes = Arc::new(frame_1_scopes.clone()); | |
| 1680 | + let frame_2_scopes = Arc::new(frame_2_scopes.clone()); | |
| 1681 | + let called_first_stack_frame = called_first_stack_frame.clone(); | |
| 1682 | + let called_second_stack_frame = called_second_stack_frame.clone(); | |
| 1683 | + move |_, args| match args.frame_id { | |
| 1684 | + 1 => { | |
| 1685 | + called_first_stack_frame.store(true, Ordering::SeqCst); | |
| 1686 | + Ok(dap::ScopesResponse { | |
| 1687 | + scopes: (*frame_1_scopes).clone(), | |
| 1688 | + }) | |
| 1781 | 1689 | } |
| 1782 | − }) | |
| 1783 | − .await; | |
| 1690 | + 2 => { | |
| 1691 | + called_second_stack_frame.store(true, Ordering::SeqCst); | |
| 1692 | + | |
| 1693 | + Ok(dap::ScopesResponse { | |
| 1694 | + scopes: (*frame_2_scopes).clone(), | |
| 1695 | + }) | |
| 1696 | + } | |
| 1697 | + _ => panic!("Made a scopes request with an invalid frame id"), | |
| 1698 | + } | |
| 1699 | + }); | |
| 1784 | 1700 | |
| 1785 | 1701 | let frame_1_variables = vec![ |
| 1786 | 1702 | Variable { |
| @@ -1840,18 +1756,16 @@ async fn test_it_fetches_scopes_variables_when_you_select_a_stack_frame( · 53 unmodified lines | ||
| 1840 | 1756 | }, |
| 1841 | 1757 | ]; |
| 1842 | 1758 | |
| 1843 | − client | |
| 1844 | − .on_request::<Variables, _>({ | |
| 1845 | − let frame_1_variables = Arc::new(frame_1_variables.clone()); | |
| 1846 | − move |_, args| { | |
| 1847 | − assert_eq!(2, args.variables_reference); | |
| 1759 | + client.on_request::<Variables, _>({ | |
| 1760 | + let frame_1_variables = Arc::new(frame_1_variables.clone()); | |
| 1761 | + move |_, args| { | |
| 1762 | + assert_eq!(2, args.variables_reference); | |
| 1848 | 1763 | |
| 1849 | − Ok(dap::VariablesResponse { | |
| 1850 | − variables: (*frame_1_variables).clone(), | |
| 1851 | − }) | |
| 1852 | − } | |
| 1853 | − }) | |
| 1854 | − .await; | |
| 1764 | + Ok(dap::VariablesResponse { | |
| 1765 | + variables: (*frame_1_variables).clone(), | |
| 1766 | + }) | |
| 1767 | + } | |
| 1768 | + }); | |
| 1855 | 1769 | |
| 1856 | 1770 | client |
| 1857 | 1771 | .fake_event(dap::messages::Events::Stopped(dap::StoppedEvent { |
| @@ -1907,18 +1821,16 @@ async fn test_it_fetches_scopes_variables_when_you_select_a_stack_frame( · 49 unmodified lines | ||
| 1907 | 1821 | assert_eq!(frame_1_variables, variables); |
| 1908 | 1822 | }); |
| 1909 | 1823 | |
| 1910 | − client | |
| 1911 | − .on_request::<Variables, _>({ | |
| 1912 | − let frame_2_variables = Arc::new(frame_2_variables.clone()); | |
| 1913 | − move |_, args| { | |
| 1914 | − assert_eq!(3, args.variables_reference); | |
| 1824 | + client.on_request::<Variables, _>({ | |
| 1825 | + let frame_2_variables = Arc::new(frame_2_variables.clone()); | |
| 1826 | + move |_, args| { | |
| 1827 | + assert_eq!(3, args.variables_reference); | |
| 1915 | 1828 | |
| 1916 | − Ok(dap::VariablesResponse { | |
| 1917 | − variables: (*frame_2_variables).clone(), | |
| 1918 | − }) | |
| 1919 | − } | |
| 1920 | − }) | |
| 1921 | − .await; | |
| 1829 | + Ok(dap::VariablesResponse { | |
| 1830 | + variables: (*frame_2_variables).clone(), | |
| 1831 | + }) | |
| 1832 | + } | |
| 1833 | + }); | |
| 1922 | 1834 | |
| 1923 | 1835 | running_state |
| 1924 | 1836 | .update_in(cx, |running_state, window, cx| { |
| @@ -16,3 +16,6 @@ pub mod dap_command; · 15 unmodified lines | ||
| 16 | 16 | pub mod dap_store; |
| 17 | 17 | mod locator_store; |
| 18 | 18 | pub mod session; |
| 19 | + | |
| 20 | +#[cfg(any(feature = "test-support", test))] | |
| 21 | +pub mod test; | |
| @@ -3,15 +3,15 @@ use super::{ · 2 unmodified lines | ||
| 3 | 3 | locator_store::LocatorStore, |
| 4 | 4 | session::{self, Session, SessionStateEvent}, |
| 5 | 5 | }; |
| 6 | −use crate::{ProjectEnvironment, debugger, worktree_store::WorktreeStore}; | |
| 6 | +use crate::{ProjectEnvironment, debugger}; | |
| 7 | 7 | use anyhow::{Result, anyhow}; |
| 8 | 8 | use async_trait::async_trait; |
| 9 | 9 | use collections::HashMap; |
| 10 | 10 | use dap::{ |
| 11 | − Capabilities, CompletionItem, CompletionsArguments, DapRegistry, ErrorResponse, | |
| 12 | − EvaluateArguments, EvaluateArgumentsContext, EvaluateResponse, RunInTerminalRequestArguments, | |
| 13 | − Source, StartDebuggingRequestArguments, | |
| 14 | − adapters::{DapStatus, DebugAdapterName}, | |
| 11 | + Capabilities, CompletionItem, CompletionsArguments, ErrorResponse, EvaluateArguments, | |
| 12 | + EvaluateArgumentsContext, EvaluateResponse, RunInTerminalRequestArguments, Source, | |
| 13 | + StartDebuggingRequestArguments, | |
| 14 | + adapters::{DapStatus, DebugAdapterBinary, DebugAdapterName}, | |
| 15 | 15 | client::SessionId, |
| 16 | 16 | messages::Message, |
| 17 | 17 | requests::{Completions, Evaluate, Request as _, RunInTerminal, StartDebugging}, |
| @@ -42,7 +42,7 @@ use std::{ · 24 unmodified lines | ||
| 42 | 42 | sync::{Arc, atomic::Ordering::SeqCst}, |
| 43 | 43 | }; |
| 44 | 44 | use std::{collections::VecDeque, sync::atomic::AtomicU32}; |
| 45 | −use task::{DebugAdapterConfig, DebugRequestDisposition}; | |
| 45 | +use task::DebugTaskDefinition; | |
| 46 | 46 | use util::ResultExt as _; |
| 47 | 47 | use worktree::Worktree; |
| 48 | 48 | |
| @@ -78,10 +78,8 @@ pub struct LocalDapStore { · 29 unmodified lines | ||
| 78 | 78 | node_runtime: NodeRuntime, |
| 79 | 79 | next_session_id: AtomicU32, |
| 80 | 80 | http_client: Arc<dyn HttpClient>, |
| 81 | − worktree_store: Entity<WorktreeStore>, | |
| 82 | 81 | environment: Entity<ProjectEnvironment>, |
| 83 | 82 | language_registry: Arc<LanguageRegistry>, |
| 84 | − debug_adapters: Arc<DapRegistry>, | |
| 85 | 83 | toolchain_store: Arc<dyn LanguageToolchainStore>, |
| 86 | 84 | locator_store: Arc<LocatorStore>, |
| 87 | 85 | start_debugging_tx: futures::channel::mpsc::UnboundedSender<(SessionId, Message)>, |
| @@ -132,11 +130,9 @@ impl DapStore { · 44 unmodified lines | ||
| 132 | 130 | node_runtime: NodeRuntime, |
| 133 | 131 | fs: Arc<dyn Fs>, |
| 134 | 132 | language_registry: Arc<LanguageRegistry>, |
| 135 | − debug_adapters: Arc<DapRegistry>, | |
| 136 | 133 | environment: Entity<ProjectEnvironment>, |
| 137 | 134 | toolchain_store: Arc<dyn LanguageToolchainStore>, |
| 138 | 135 | breakpoint_store: Entity<BreakpointStore>, |
| 139 | − worktree_store: Entity<WorktreeStore>, | |
| 140 | 136 | cx: &mut Context<Self>, |
| 141 | 137 | ) -> Self { |
| 142 | 138 | cx.on_app_quit(Self::shutdown_sessions).detach(); |
| @@ -170,10 +166,8 @@ impl DapStore { · 27 unmodified lines | ||
| 170 | 166 | environment, |
| 171 | 167 | http_client, |
| 172 | 168 | node_runtime, |
| 173 | − worktree_store, | |
| 174 | 169 | toolchain_store, |
| 175 | 170 | language_registry, |
| 176 | − debug_adapters, | |
| 177 | 171 | start_debugging_tx, |
| 178 | 172 | _start_debugging_task, |
| 179 | 173 | locator_store: Arc::from(LocatorStore::new()), |
| @@ -320,18 +314,12 @@ impl DapStore { · 140 unmodified lines | ||
| 320 | 314 | Ok(()) |
| 321 | 315 | } |
| 322 | 316 | |
| 323 | − pub fn new_session( | |
| 324 | − &mut self, | |
| 325 | − mut config: DebugAdapterConfig, | |
| 326 | − worktree: &Entity<Worktree>, | |
| 327 | − parent_session: Option<Entity<Session>>, | |
| 328 | − cx: &mut Context<Self>, | |
| 329 | − ) -> (SessionId, Task<Result<Entity<Session>>>) { | |
| 317 | + pub fn delegate(&self, worktree: &Entity<Worktree>, cx: &mut App) -> DapAdapterDelegate { | |
| 330 | 318 | let Some(local_store) = self.as_local() else { |
| 331 | 319 | unimplemented!("Starting session on remote side"); |
| 332 | 320 | }; |
| 333 | 321 | |
| 334 | − let delegate = DapAdapterDelegate::new( | |
| 322 | + DapAdapterDelegate::new( | |
| 335 | 323 | local_store.fs.clone(), |
| 336 | 324 | worktree.read(cx).id(), |
| 337 | 325 | local_store.node_runtime.clone(), |
| @@ -341,7 +329,20 @@ impl DapStore { · 3 unmodified lines | ||
| 341 | 329 | local_store.environment.update(cx, |env, cx| { |
| 342 | 330 | env.get_worktree_environment(worktree.clone(), cx) |
| 343 | 331 | }), |
| 344 | − ); | |
| 332 | + ) | |
| 333 | + } | |
| 334 | + | |
| 335 | + pub fn new_session( | |
| 336 | + &mut self, | |
| 337 | + binary: DebugAdapterBinary, | |
| 338 | + mut config: DebugTaskDefinition, | |
| 339 | + parent_session: Option<Entity<Session>>, | |
| 340 | + cx: &mut Context<Self>, | |
| 341 | + ) -> (SessionId, Task<Result<Entity<Session>>>) { | |
| 342 | + let Some(local_store) = self.as_local() else { | |
| 343 | + unimplemented!("Starting session on remote side"); | |
| 344 | + }; | |
| 345 | + | |
| 345 | 346 | let session_id = local_store.next_session_id(); |
| 346 | 347 | |
| 347 | 348 | if let Some(session) = &parent_session { |
| @@ -352,7 +353,6 @@ impl DapStore { · 4 unmodified lines | ||
| 352 | 353 | |
| 353 | 354 | let (initialized_tx, initialized_rx) = oneshot::channel(); |
| 354 | 355 | let locator_store = local_store.locator_store.clone(); |
| 355 | − let debug_adapters = local_store.debug_adapters.clone(); | |
| 356 | 356 | |
| 357 | 357 | let start_debugging_tx = local_store.start_debugging_tx.clone(); |
| 358 | 358 | |
| @@ -373,86 +373,31 @@ impl DapStore { · 14 unmodified lines | ||
| 373 | 373 | this.breakpoint_store.clone(), |
| 374 | 374 | session_id, |
| 375 | 375 | parent_session, |
| 376 | − delegate, | |
| 376 | + binary, | |
| 377 | 377 | config, |
| 378 | 378 | start_debugging_tx.clone(), |
| 379 | 379 | initialized_tx, |
| 380 | − debug_adapters, | |
| 381 | 380 | cx, |
| 382 | 381 | ) |
| 383 | 382 | })?; |
| 384 | 383 | |
| 385 | − this.update(cx, |_, cx| { | |
| 386 | − create_new_session(session_id, initialized_rx, start_client_task, cx) | |
| 387 | − })? | |
| 388 | − .await | |
| 384 | + let ret = this | |
| 385 | + .update(cx, |_, cx| { | |
| 386 | + create_new_session(session_id, initialized_rx, start_client_task, cx) | |
| 387 | + })? | |
| 388 | + .await; | |
| 389 | + ret | |
| 389 | 390 | }); |
| 390 | 391 | |
| 391 | 392 | (session_id, task) |
| 392 | 393 | } |
| 393 | 394 | |
| 394 | − #[cfg(any(test, feature = "test-support"))] | |
| 395 | − pub fn new_fake_session( | |
| 396 | − &mut self, | |
| 397 | − config: DebugAdapterConfig, | |
| 398 | − worktree: &Entity<Worktree>, | |
| 399 | − parent_session: Option<Entity<Session>>, | |
| 400 | − caps: Capabilities, | |
| 401 | − fails: bool, | |
| 402 | − cx: &mut Context<Self>, | |
| 403 | − ) -> (SessionId, Task<Result<Entity<Session>>>) { | |
| 404 | − let Some(local_store) = self.as_local() else { | |
| 405 | − unimplemented!("Starting session on remote side"); | |
| 406 | − }; | |
| 407 | − | |
| 408 | − let delegate = DapAdapterDelegate::new( | |
| 409 | − local_store.fs.clone(), | |
| 410 | − worktree.read(cx).id(), | |
| 411 | − local_store.node_runtime.clone(), | |
| 412 | − local_store.http_client.clone(), | |
| 413 | − local_store.language_registry.clone(), | |
| 414 | − local_store.toolchain_store.clone(), | |
| 415 | − local_store.environment.update(cx, |env, cx| { | |
| 416 | − env.get_worktree_environment(worktree.clone(), cx) | |
| 417 | − }), | |
| 418 | − ); | |
| 419 | − let session_id = local_store.next_session_id(); | |
| 420 | − | |
| 421 | − if let Some(session) = &parent_session { | |
| 422 | − session.update(cx, |session, _| { | |
| 423 | − session.add_child_session_id(session_id); | |
| 424 | − }); | |
| 425 | − } | |
| 426 | − | |
| 427 | − let (initialized_tx, initialized_rx) = oneshot::channel(); | |
| 428 | − | |
| 429 | − let start_client_task = Session::fake( | |
| 430 | − self.breakpoint_store.clone(), | |
| 431 | − session_id, | |
| 432 | − parent_session, | |
| 433 | − delegate, | |
| 434 | − config, | |
| 435 | − local_store.start_debugging_tx.clone(), | |
| 436 | − initialized_tx, | |
| 437 | − caps, | |
| 438 | − fails, | |
| 439 | − cx, | |
| 440 | − ); | |
| 441 | − | |
| 442 | − let task = create_new_session(session_id, initialized_rx, start_client_task, cx); | |
| 443 | − (session_id, task) | |
| 444 | − } | |
| 445 | − | |
| 446 | 395 | fn handle_start_debugging_request( |
| 447 | 396 | &mut self, |
| 448 | 397 | session_id: SessionId, |
| 449 | 398 | request: dap::messages::Request, |
| 450 | 399 | cx: &mut Context<Self>, |
| 451 | 400 | ) -> Task<Result<()>> { |
| 452 | − let Some(local_store) = self.as_local() else { | |
| 453 | − unreachable!("Cannot response for non-local session"); | |
| 454 | − }; | |
| 455 | − | |
| 456 | 401 | let Some(parent_session) = self.session_by_id(session_id) else { |
| 457 | 402 | return Task::ready(Err(anyhow!("Session not found"))); |
| 458 | 403 | }; |
| @@ -461,41 +406,12 @@ impl DapStore { · 2 unmodified lines | ||
| 461 | 406 | request.arguments.unwrap_or_default(), |
| 462 | 407 | ) |
| 463 | 408 | .expect("To parse StartDebuggingRequestArguments"); |
| 464 | − let worktree = local_store | |
| 465 | − .worktree_store | |
| 466 | − .update(cx, |this, _| this.worktrees().next()) | |
| 467 | − .expect("worktree-less project"); | |
| 409 | + let mut binary = parent_session.read(cx).binary().clone(); | |
| 410 | + let config = parent_session.read(cx).configuration().unwrap().clone(); | |
| 411 | + binary.request_args = args; | |
| 468 | 412 | |
| 469 | − let Some(config) = parent_session.read(cx).configuration() else { | |
| 470 | − unreachable!("there must be a config for local sessions"); | |
| 471 | − }; | |
| 472 | − | |
| 473 | − let debug_config = DebugAdapterConfig { | |
| 474 | − label: config.label, | |
| 475 | − adapter: config.adapter, | |
| 476 | − request: DebugRequestDisposition::ReverseRequest(args), | |
| 477 | − initialize_args: config.initialize_args.clone(), | |
| 478 | − tcp_connection: config.tcp_connection.clone(), | |
| 479 | − locator: None, | |
| 480 | − stop_on_entry: config.stop_on_entry, | |
| 481 | − }; | |
| 482 | − | |
| 483 | − #[cfg(any(test, feature = "test-support"))] | |
| 484 | − let new_session_task = { | |
| 485 | − let caps = parent_session.read(cx).capabilities.clone(); | |
| 486 | − self.new_fake_session( | |
| 487 | − debug_config, | |
| 488 | − &worktree, | |
| 489 | − Some(parent_session.clone()), | |
| 490 | − caps, | |
| 491 | − false, | |
| 492 | − cx, | |
| 493 | − ) | |
| 494 | − .1 | |
| 495 | − }; | |
| 496 | − #[cfg(not(any(test, feature = "test-support")))] | |
| 497 | 413 | let new_session_task = self |
| 498 | − .new_session(debug_config, &worktree, Some(parent_session.clone()), cx) | |
| 414 | + .new_session(binary, config, Some(parent_session.clone()), cx) | |
| 499 | 415 | .1; |
| 500 | 416 | |
| 501 | 417 | let request_seq = request.seq; |
| @@ -607,13 +523,7 @@ impl DapStore { · 105 unmodified lines | ||
| 607 | 523 | .map(Arc::from) |
| 608 | 524 | .or_else(|| { |
| 609 | 525 | self.session_by_id(session_id) |
| 610 | − .and_then(|session| { | |
| 611 | − session | |
| 612 | − .read(cx) | |
| 613 | − .configuration() | |
| 614 | − .and_then(|config| config.request.cwd()) | |
| 615 | − }) | |
| 616 | − .map(Arc::from) | |
| 526 | + .and_then(|session| session.read(cx).binary().cwd.as_deref().map(Arc::from)) | |
| 617 | 527 | }); |
| 618 | 528 | cx.emit(DapStoreEvent::RunInTerminal { |
| 619 | 529 | session_id, |
| @@ -852,7 +762,7 @@ fn create_new_session( · 232 unmodified lines | ||
| 852 | 762 | cx.emit(DapStoreEvent::DebugClientStarted(session_id)); |
| 853 | 763 | cx.notify(); |
| 854 | 764 | })?; |
| 855 | − let seq_result = { | |
| 765 | + let seq_result = async || { | |
| 856 | 766 | session |
| 857 | 767 | .update(cx, |session, cx| session.request_initialize(cx))? |
| 858 | 768 | .await?; |
| @@ -863,12 +773,11 @@ fn create_new_session( · 4 unmodified lines | ||
| 863 | 773 | })? |
| 864 | 774 | .await |
| 865 | 775 | }; |
| 866 | − match seq_result { | |
| 776 | + match seq_result().await { | |
| 867 | 777 | Ok(_) => {} |
| 868 | 778 | Err(error) => { |
| 869 | 779 | this.update(cx, |this, cx| { |
| 870 | 780 | cx.emit(DapStoreEvent::Notification(error.to_string())); |
| 871 | − | |
| 872 | 781 | this.shutdown_session(session_id, cx) |
| 873 | 782 | })? |
| 874 | 783 | .await |
| @@ -1,9 +1,9 @@ | ||
| 1 | 1 | use anyhow::{Result, anyhow}; |
| 2 | 2 | use cargo::CargoLocator; |
| 3 | 3 | use collections::HashMap; |
| 4 | −use dap::DebugAdapterConfig; | |
| 5 | 4 | use gpui::SharedString; |
| 6 | 5 | use locators::DapLocator; |
| 6 | +use task::DebugTaskDefinition; | |
| 7 | 7 | |
| 8 | 8 | mod cargo; |
| 9 | 9 | mod locators; |
| @@ -23,7 +23,7 @@ impl LocatorStore { · 13 unmodified lines | ||
| 23 | 23 | |
| 24 | 24 | pub(super) async fn resolve_debug_config( |
| 25 | 25 | &self, |
| 26 | − debug_config: &mut DebugAdapterConfig, | |
| 26 | + debug_config: &mut DebugTaskDefinition, | |
| 27 | 27 | ) -> Result<()> { |
| 28 | 28 | let Some(locator_name) = &debug_config.locator else { |
| 29 | 29 | log::debug!("Attempted to resolve debug config without a locator field"); |
| @@ -1,12 +1,12 @@ | ||
| 1 | 1 | use super::DapLocator; |
| 2 | 2 | use anyhow::{Result, anyhow}; |
| 3 | 3 | use async_trait::async_trait; |
| 4 | −use dap::DebugAdapterConfig; | |
| 5 | 4 | use serde_json::{Value, json}; |
| 6 | 5 | use smol::{ |
| 7 | 6 | io::AsyncReadExt, |
| 8 | 7 | process::{Command, Stdio}, |
| 9 | 8 | }; |
| 9 | +use task::DebugTaskDefinition; | |
| 10 | 10 | use util::maybe; |
| 11 | 11 | |
| 12 | 12 | pub(super) struct CargoLocator; |
| @@ -38,11 +38,9 @@ async fn find_best_executable(executables: &[String], test_name: &str) -> Option · 25 unmodified lines | ||
| 38 | 38 | } |
| 39 | 39 | #[async_trait] |
| 40 | 40 | impl DapLocator for CargoLocator { |
| 41 | − async fn run_locator(&self, debug_config: &mut DebugAdapterConfig) -> Result<()> { | |
| 41 | + async fn run_locator(&self, debug_config: &mut DebugTaskDefinition) -> Result<()> { | |
| 42 | 42 | let Some(launch_config) = (match &mut debug_config.request { |
| 43 | − task::DebugRequestDisposition::UserConfigured(task::DebugRequestType::Launch( | |
| 44 | − launch_config, | |
| 45 | − )) => Some(launch_config), | |
| 43 | + task::DebugRequestType::Launch(launch_config) => Some(launch_config), | |
| 46 | 44 | _ => None, |
| 47 | 45 | }) else { |
| 48 | 46 | return Err(anyhow!("Couldn't get launch config in locator")); |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | use anyhow::Result; |
| 2 | 2 | use async_trait::async_trait; |
| 3 | −use dap::DebugAdapterConfig; | |
| 3 | +use task::DebugTaskDefinition; | |
| 4 | 4 | |
| 5 | 5 | #[async_trait] |
| 6 | 6 | pub(super) trait DapLocator: Send + Sync { |
| 7 | − async fn run_locator(&self, debug_config: &mut DebugAdapterConfig) -> Result<()>; | |
| 7 | + async fn run_locator(&self, debug_config: &mut DebugTaskDefinition) -> Result<()>; | |
| 8 | 8 | } |
| @@ -1,5 +1,3 @@ | ||
| 1 | −use crate::project_settings::ProjectSettings; | |
| 2 | − | |
| 3 | 1 | use super::breakpoint_store::{ |
| 4 | 2 | BreakpointStore, BreakpointStoreEvent, BreakpointUpdatedReason, SourceBreakpoint, |
| 5 | 3 | }; |
| @@ -11,22 +9,17 @@ use super::dap_command::{ · 5 unmodified lines | ||
| 11 | 9 | StepBackCommand, StepCommand, StepInCommand, StepOutCommand, TerminateCommand, |
| 12 | 10 | TerminateThreadsCommand, ThreadsCommand, VariablesCommand, |
| 13 | 11 | }; |
| 14 | −use super::dap_store::DapAdapterDelegate; | |
| 15 | 12 | use anyhow::{Context as _, Result, anyhow}; |
| 16 | 13 | use collections::{HashMap, HashSet, IndexMap, IndexSet}; |
| 17 | −use dap::adapters::{DebugAdapter, DebugAdapterBinary}; | |
| 14 | +use dap::adapters::DebugAdapterBinary; | |
| 18 | 15 | use dap::messages::Response; |
| 19 | 16 | use dap::{ |
| 20 | 17 | Capabilities, ContinueArguments, EvaluateArgumentsContext, Module, Source, StackFrameId, |
| 21 | 18 | SteppingGranularity, StoppedEvent, VariableReference, |
| 22 | − adapters::{DapDelegate, DapStatus}, | |
| 23 | 19 | client::{DebugAdapterClient, SessionId}, |
| 24 | 20 | messages::{Events, Message}, |
| 25 | 21 | }; |
| 26 | −use dap::{ | |
| 27 | − DapRegistry, DebugRequestType, ExceptionBreakpointsFilter, ExceptionFilterOptions, | |
| 28 | − OutputEventCategory, | |
| 29 | −}; | |
| 22 | +use dap::{ExceptionBreakpointsFilter, ExceptionFilterOptions, OutputEventCategory}; | |
| 30 | 23 | use futures::channel::oneshot; |
| 31 | 24 | use futures::{FutureExt, future::Shared}; |
| 32 | 25 | use gpui::{ |
| @@ -35,11 +28,9 @@ use gpui::{ · 2 unmodified lines | ||
| 35 | 28 | }; |
| 36 | 29 | use rpc::AnyProtoClient; |
| 37 | 30 | use serde_json::{Value, json}; |
| 38 | −use settings::Settings; | |
| 39 | 31 | use smol::stream::StreamExt; |
| 40 | 32 | use std::any::TypeId; |
| 41 | 33 | use std::collections::BTreeMap; |
| 42 | −use std::path::PathBuf; | |
| 43 | 34 | use std::u64; |
| 44 | 35 | use std::{ |
| 45 | 36 | any::Any, |
| @@ -48,7 +39,7 @@ use std::{ · 2 unmodified lines | ||
| 48 | 39 | path::Path, |
| 49 | 40 | sync::Arc, |
| 50 | 41 | }; |
| 51 | −use task::{DebugAdapterConfig, DebugTaskDefinition}; | |
| 42 | +use task::DebugTaskDefinition; | |
| 52 | 43 | use text::{PointUtf16, ToPointUtf16}; |
| 53 | 44 | use util::{ResultExt, merge_json_value_into}; |
| 54 | 45 | |
| @@ -168,9 +159,9 @@ enum Mode { · 113 unmodified lines | ||
| 168 | 159 | #[derive(Clone)] |
| 169 | 160 | pub struct LocalMode { |
| 170 | 161 | client: Arc<DebugAdapterClient>, |
| 171 | − config: DebugAdapterConfig, | |
| 172 | − adapter: Arc<dyn DebugAdapter>, | |
| 173 | − breakpoint_store: Entity<BreakpointStore>, | |
| 162 | + definition: DebugTaskDefinition, | |
| 163 | + binary: DebugAdapterBinary, | |
| 164 | + pub(crate) breakpoint_store: Entity<BreakpointStore>, | |
| 174 | 165 | tmp_breakpoint: Option<SourceBreakpoint>, |
| 175 | 166 | } |
| 176 | 167 | |
| @@ -191,185 +182,37 @@ fn client_source(abs_path: &Path) -> dap::Source { · 14 unmodified lines | ||
| 191 | 182 | |
| 192 | 183 | impl LocalMode { |
| 193 | 184 | fn new( |
| 194 | − debug_adapters: Arc<DapRegistry>, | |
| 195 | 185 | session_id: SessionId, |
| 196 | 186 | parent_session: Option<Entity<Session>>, |
| 197 | 187 | breakpoint_store: Entity<BreakpointStore>, |
| 198 | − config: DebugAdapterConfig, | |
| 199 | − delegate: DapAdapterDelegate, | |
| 188 | + config: DebugTaskDefinition, | |
| 189 | + binary: DebugAdapterBinary, | |
| 200 | 190 | messages_tx: futures::channel::mpsc::UnboundedSender<Message>, |
| 201 | 191 | cx: AsyncApp, |
| 202 | 192 | ) -> Task<Result<Self>> { |
| 203 | 193 | Self::new_inner( |
| 204 | − debug_adapters, | |
| 205 | 194 | session_id, |
| 206 | 195 | parent_session, |
| 207 | 196 | breakpoint_store, |
| 208 | 197 | config, |
| 209 | − delegate, | |
| 198 | + binary, | |
| 210 | 199 | messages_tx, |
| 211 | 200 | async |_, _| {}, |
| 212 | 201 | cx, |
| 213 | 202 | ) |
| 214 | 203 | } |
| 215 | − #[cfg(any(test, feature = "test-support"))] | |
| 216 | − fn new_fake( | |
| 217 | − session_id: SessionId, | |
| 218 | − parent_session: Option<Entity<Session>>, | |
| 219 | − breakpoint_store: Entity<BreakpointStore>, | |
| 220 | − config: DebugAdapterConfig, | |
| 221 | − delegate: DapAdapterDelegate, | |
| 222 | − messages_tx: futures::channel::mpsc::UnboundedSender<Message>, | |
| 223 | − caps: Capabilities, | |
| 224 | − fail: bool, | |
| 225 | − cx: AsyncApp, | |
| 226 | − ) -> Task<Result<Self>> { | |
| 227 | − use task::DebugRequestDisposition; | |
| 228 | − | |
| 229 | − let request = match config.request.clone() { | |
| 230 | − DebugRequestDisposition::UserConfigured(request) => request, | |
| 231 | − DebugRequestDisposition::ReverseRequest(reverse_request_args) => { | |
| 232 | − match reverse_request_args.request { | |
| 233 | − dap::StartDebuggingRequestArgumentsRequest::Launch => { | |
| 234 | − DebugRequestType::Launch(task::LaunchConfig { | |
| 235 | − program: "".to_owned(), | |
| 236 | − cwd: None, | |
| 237 | − args: Default::default(), | |
| 238 | − }) | |
| 239 | − } | |
| 240 | − dap::StartDebuggingRequestArgumentsRequest::Attach => { | |
| 241 | − DebugRequestType::Attach(task::AttachConfig { | |
| 242 | − process_id: Some(0), | |
| 243 | − }) | |
| 244 | − } | |
| 245 | − } | |
| 246 | − } | |
| 247 | − }; | |
| 248 | − | |
| 249 | − let callback = async move |session: &mut LocalMode, cx: AsyncApp| { | |
| 250 | − session | |
| 251 | − .client | |
| 252 | − .on_request::<dap::requests::Initialize, _>(move |_, _| Ok(caps.clone())) | |
| 253 | − .await; | |
| 254 | − | |
| 255 | − let paths = cx | |
| 256 | − .update(|cx| session.breakpoint_store.read(cx).breakpoint_paths()) | |
| 257 | − .expect("Breakpoint store should exist in all tests that start debuggers"); | |
| 258 | − | |
| 259 | − session | |
| 260 | − .client | |
| 261 | − .on_request::<dap::requests::SetBreakpoints, _>(move |_, args| { | |
| 262 | − let p = Arc::from(Path::new(&args.source.path.unwrap())); | |
| 263 | − if !paths.contains(&p) { | |
| 264 | − panic!("Sent breakpoints for path without any") | |
| 265 | − } | |
| 266 | 204 | |
| 267 | − Ok(dap::SetBreakpointsResponse { | |
| 268 | − breakpoints: Vec::default(), | |
| 269 | − }) | |
| 270 | − }) | |
| 271 | − .await; | |
| 272 | − | |
| 273 | − match request { | |
| 274 | − dap::DebugRequestType::Launch(_) => { | |
| 275 | − if fail { | |
| 276 | − session | |
| 277 | − .client | |
| 278 | − .on_request::<dap::requests::Launch, _>(move |_, _| { | |
| 279 | − Err(dap::ErrorResponse { | |
| 280 | − error: Some(dap::Message { | |
| 281 | − id: 1, | |
| 282 | − format: "error".into(), | |
| 283 | − variables: None, | |
| 284 | − send_telemetry: None, | |
| 285 | − show_user: None, | |
| 286 | − url: None, | |
| 287 | − url_label: None, | |
| 288 | − }), | |
| 289 | − }) | |
| 290 | − }) | |
| 291 | − .await; | |
| 292 | − } else { | |
| 293 | − session | |
| 294 | − .client | |
| 295 | − .on_request::<dap::requests::Launch, _>(move |_, _| Ok(())) | |
| 296 | − .await; | |
| 297 | − } | |
| 298 | − } | |
| 299 | − dap::DebugRequestType::Attach(attach_config) => { | |
| 300 | − if fail { | |
| 301 | − session | |
| 302 | − .client | |
| 303 | − .on_request::<dap::requests::Attach, _>(move |_, _| { | |
| 304 | − Err(dap::ErrorResponse { | |
| 305 | − error: Some(dap::Message { | |
| 306 | − id: 1, | |
| 307 | − format: "error".into(), | |
| 308 | − variables: None, | |
| 309 | − send_telemetry: None, | |
| 310 | − show_user: None, | |
| 311 | − url: None, | |
| 312 | − url_label: None, | |
| 313 | − }), | |
| 314 | − }) | |
| 315 | − }) | |
| 316 | − .await; | |
| 317 | − } else { | |
| 318 | − session | |
| 319 | − .client | |
| 320 | − .on_request::<dap::requests::Attach, _>(move |_, args| { | |
| 321 | − assert_eq!( | |
| 322 | − json!({"request": "attach", "process_id": attach_config.process_id.unwrap()}), | |
| 323 | − args.raw | |
| 324 | − ); | |
| 325 | − | |
| 326 | − Ok(()) | |
| 327 | − }) | |
| 328 | − .await; | |
| 329 | − } | |
| 330 | − } | |
| 331 | − } | |
| 332 | − | |
| 333 | − session | |
| 334 | − .client | |
| 335 | − .on_request::<dap::requests::SetExceptionBreakpoints, _>(move |_, _| { | |
| 336 | − Ok(dap::SetExceptionBreakpointsResponse { breakpoints: None }) | |
| 337 | − }) | |
| 338 | − .await; | |
| 339 | − | |
| 340 | − session | |
| 341 | − .client | |
| 342 | − .on_request::<dap::requests::Disconnect, _>(move |_, _| Ok(())) | |
| 343 | − .await; | |
| 344 | − session.client.fake_event(Events::Initialized(None)).await; | |
| 345 | − }; | |
| 346 | − Self::new_inner( | |
| 347 | − DapRegistry::fake().into(), | |
| 348 | − session_id, | |
| 349 | − parent_session, | |
| 350 | − breakpoint_store, | |
| 351 | − config, | |
| 352 | − delegate, | |
| 353 | − messages_tx, | |
| 354 | − callback, | |
| 355 | − cx, | |
| 356 | − ) | |
| 357 | − } | |
| 358 | 205 | fn new_inner( |
| 359 | − registry: Arc<DapRegistry>, | |
| 360 | 206 | session_id: SessionId, |
| 361 | 207 | parent_session: Option<Entity<Session>>, |
| 362 | 208 | breakpoint_store: Entity<BreakpointStore>, |
| 363 | − config: DebugAdapterConfig, | |
| 364 | − delegate: DapAdapterDelegate, | |
| 209 | + config: DebugTaskDefinition, | |
| 210 | + binary: DebugAdapterBinary, | |
| 365 | 211 | messages_tx: futures::channel::mpsc::UnboundedSender<Message>, |
| 366 | 212 | on_initialized: impl AsyncFnOnce(&mut LocalMode, AsyncApp) + 'static, |
| 367 | 213 | cx: AsyncApp, |
| 368 | 214 | ) -> Task<Result<Self>> { |
| 369 | 215 | cx.spawn(async move |cx| { |
| 370 | − let (adapter, binary) = | |
| 371 | − Self::get_adapter_binary(®istry, &config, &delegate, cx).await?; | |
| 372 | − | |
| 373 | 216 | let message_handler = Box::new(move |message| { |
| 374 | 217 | messages_tx.unbounded_send(message).ok(); |
| 375 | 218 | }); |
| @@ -380,13 +223,12 @@ impl LocalMode { · 4 unmodified lines | ||
| 380 | 223 | .flatten() |
| 381 | 224 | { |
| 382 | 225 | client |
| 383 | − .reconnect(session_id, binary, message_handler, cx.clone()) | |
| 226 | + .reconnect(session_id, binary.clone(), message_handler, cx.clone()) | |
| 384 | 227 | .await? |
| 385 | 228 | } else { |
| 386 | 229 | DebugAdapterClient::start( |
| 387 | 230 | session_id, |
| 388 | − adapter.name(), | |
| 389 | − binary, | |
| 231 | + binary.clone(), | |
| 390 | 232 | message_handler, |
| 391 | 233 | cx.clone(), |
| 392 | 234 | ) |
| @@ -397,10 +239,10 @@ impl LocalMode { · 4 unmodified lines | ||
| 397 | 239 | |
| 398 | 240 | let mut session = Self { |
| 399 | 241 | client, |
| 400 | − adapter, | |
| 401 | 242 | breakpoint_store, |
| 402 | 243 | tmp_breakpoint: None, |
| 403 | − config: config.clone(), | |
| 244 | + definition: config, | |
| 245 | + binary, | |
| 404 | 246 | }; |
| 405 | 247 | |
| 406 | 248 | on_initialized(&mut session, cx.clone()).await; |
| @@ -533,55 +375,12 @@ impl LocalMode { · 126 unmodified lines | ||
| 533 | 375 | }) |
| 534 | 376 | } |
| 535 | 377 | |
| 536 | − async fn get_adapter_binary( | |
| 537 | − registry: &Arc<DapRegistry>, | |
| 538 | − config: &DebugAdapterConfig, | |
| 539 | − delegate: &DapAdapterDelegate, | |
| 540 | − cx: &mut AsyncApp, | |
| 541 | − ) -> Result<(Arc<dyn DebugAdapter>, DebugAdapterBinary)> { | |
| 542 | − let adapter = registry | |
| 543 | − .adapter(&config.adapter) | |
| 544 | − .ok_or_else(|| anyhow!("Debug adapter with name `{}` was not found", config.adapter))?; | |
| 545 | − | |
| 546 | − let binary = cx.update(|cx| { | |
| 547 | − ProjectSettings::get_global(cx) | |
| 548 | − .dap | |
| 549 | − .get(&adapter.name()) | |
| 550 | − .and_then(|s| s.binary.as_ref().map(PathBuf::from)) | |
| 551 | − })?; | |
| 552 | − | |
| 553 | − let binary = match adapter.get_binary(delegate, &config, binary, cx).await { | |
| 554 | − Err(error) => { | |
| 555 | − delegate.update_status( | |
| 556 | − adapter.name(), | |
| 557 | − DapStatus::Failed { | |
| 558 | − error: error.to_string(), | |
| 559 | − }, | |
| 560 | − ); | |
| 561 | − | |
| 562 | − return Err(error); | |
| 563 | − } | |
| 564 | − Ok(mut binary) => { | |
| 565 | − delegate.update_status(adapter.name(), DapStatus::None); | |
| 566 | − | |
| 567 | − let shell_env = delegate.shell_env().await; | |
| 568 | − let mut envs = binary.envs.unwrap_or_default(); | |
| 569 | − envs.extend(shell_env); | |
| 570 | − binary.envs = Some(envs); | |
| 571 | − | |
| 572 | − binary | |
| 573 | − } | |
| 574 | − }; | |
| 575 | − | |
| 576 | − Ok((adapter, binary)) | |
| 577 | − } | |
| 578 | − | |
| 579 | 378 | pub fn label(&self) -> String { |
| 580 | − self.config.label.clone() | |
| 379 | + self.definition.label.clone() | |
| 581 | 380 | } |
| 582 | 381 | |
| 583 | 382 | fn request_initialization(&self, cx: &App) -> Task<Result<Capabilities>> { |
| 584 | − let adapter_id = self.adapter.name().to_string(); | |
| 383 | + let adapter_id = self.binary.adapter_name.to_string(); | |
| 585 | 384 | |
| 586 | 385 | self.request(Initialize { adapter_id }, cx.background_executor().clone()) |
| 587 | 386 | } |
| @@ -592,36 +391,26 @@ impl LocalMode { · 4 unmodified lines | ||
| 592 | 391 | initialized_rx: oneshot::Receiver<()>, |
| 593 | 392 | cx: &App, |
| 594 | 393 | ) -> Task<Result<()>> { |
| 595 | − let (mut raw, is_launch) = match &self.config.request { | |
| 596 | − task::DebugRequestDisposition::UserConfigured(_) => { | |
| 597 | − let Ok(raw) = DebugTaskDefinition::try_from(self.config.clone()) else { | |
| 598 | − debug_assert!(false, "This part of code should be unreachable in practice"); | |
| 599 | − return Task::ready(Err(anyhow!( | |
| 600 | − "Expected debug config conversion to succeed" | |
| 601 | − ))); | |
| 602 | − }; | |
| 603 | − let is_launch = matches!(raw.request, DebugRequestType::Launch(_)); | |
| 604 | − let raw = self.adapter.request_args(&raw); | |
| 605 | − (raw, is_launch) | |
| 606 | − } | |
| 607 | − task::DebugRequestDisposition::ReverseRequest(start_debugging_request_arguments) => ( | |
| 608 | − start_debugging_request_arguments.configuration.clone(), | |
| 609 | − matches!( | |
| 610 | − start_debugging_request_arguments.request, | |
| 611 | − dap::StartDebuggingRequestArgumentsRequest::Launch | |
| 612 | − ), | |
| 613 | − ), | |
| 614 | − }; | |
| 394 | + let mut raw = self.binary.request_args.clone(); | |
| 615 | 395 | |
| 616 | 396 | merge_json_value_into( |
| 617 | − self.config.initialize_args.clone().unwrap_or(json!({})), | |
| 618 | − &mut raw, | |
| 397 | + self.definition.initialize_args.clone().unwrap_or(json!({})), | |
| 398 | + &mut raw.configuration, | |
| 619 | 399 | ); |
| 620 | 400 | // Of relevance: https://github.com/microsoft/vscode/issues/4902#issuecomment-368583522 |
| 621 | − let launch = if is_launch { | |
| 622 | − self.request(Launch { raw }, cx.background_executor().clone()) | |
| 623 | − } else { | |
| 624 | − self.request(Attach { raw }, cx.background_executor().clone()) | |
| 401 | + let launch = match raw.request { | |
| 402 | + dap::StartDebuggingRequestArgumentsRequest::Launch => self.request( | |
| 403 | + Launch { | |
| 404 | + raw: raw.configuration, | |
| 405 | + }, | |
| 406 | + cx.background_executor().clone(), | |
| 407 | + ), | |
| 408 | + dap::StartDebuggingRequestArgumentsRequest::Attach => self.request( | |
| 409 | + Attach { | |
| 410 | + raw: raw.configuration, | |
| 411 | + }, | |
| 412 | + cx.background_executor().clone(), | |
| 413 | + ), | |
| 625 | 414 | }; |
| 626 | 415 | |
| 627 | 416 | let configuration_done_supported = ConfigurationDone::is_supported(capabilities); |
| @@ -656,12 +445,13 @@ impl LocalMode { · 28 unmodified lines | ||
| 656 | 445 | })? |
| 657 | 446 | .await |
| 658 | 447 | .ok(); |
| 659 | − if configuration_done_supported { | |
| 448 | + let ret = if configuration_done_supported { | |
| 660 | 449 | this.request(ConfigurationDone {}, cx.background_executor().clone()) |
| 661 | 450 | } else { |
| 662 | 451 | Task::ready(Ok(())) |
| 663 | 452 | } |
| 664 | − .await | |
| 453 | + .await; | |
| 454 | + ret | |
| 665 | 455 | } |
| 666 | 456 | }); |
| 667 | 457 | |
| @@ -909,68 +699,22 @@ impl Session { · 241 unmodified lines | ||
| 909 | 699 | breakpoint_store: Entity<BreakpointStore>, |
| 910 | 700 | session_id: SessionId, |
| 911 | 701 | parent_session: Option<Entity<Session>>, |
| 912 | − delegate: DapAdapterDelegate, | |
| 913 | − config: DebugAdapterConfig, | |
| 702 | + binary: DebugAdapterBinary, | |
| 703 | + config: DebugTaskDefinition, | |
| 914 | 704 | start_debugging_requests_tx: futures::channel::mpsc::UnboundedSender<(SessionId, Message)>, |
| 915 | 705 | initialized_tx: oneshot::Sender<()>, |
| 916 | − debug_adapters: Arc<DapRegistry>, | |
| 917 | 706 | cx: &mut App, |
| 918 | 707 | ) -> Task<Result<Entity<Self>>> { |
| 919 | 708 | let (message_tx, message_rx) = futures::channel::mpsc::unbounded(); |
| 920 | 709 | |
| 921 | 710 | cx.spawn(async move |cx| { |
| 922 | 711 | let mode = LocalMode::new( |
| 923 | − debug_adapters, | |
| 924 | − session_id, | |
| 925 | − parent_session.clone(), | |
| 926 | − breakpoint_store.clone(), | |
| 927 | − config.clone(), | |
| 928 | − delegate, | |
| 929 | − message_tx, | |
| 930 | − cx.clone(), | |
| 931 | − ) | |
| 932 | − .await?; | |
| 933 | − | |
| 934 | − cx.new(|cx| { | |
| 935 | − create_local_session( | |
| 936 | − breakpoint_store, | |
| 937 | − session_id, | |
| 938 | − parent_session, | |
| 939 | − start_debugging_requests_tx, | |
| 940 | − initialized_tx, | |
| 941 | − message_rx, | |
| 942 | − mode, | |
| 943 | − cx, | |
| 944 | − ) | |
| 945 | − }) | |
| 946 | − }) | |
| 947 | − } | |
| 948 | − | |
| 949 | − #[cfg(any(test, feature = "test-support"))] | |
| 950 | − pub(crate) fn fake( | |
| 951 | − breakpoint_store: Entity<BreakpointStore>, | |
| 952 | − session_id: SessionId, | |
| 953 | − parent_session: Option<Entity<Session>>, | |
| 954 | − delegate: DapAdapterDelegate, | |
| 955 | − config: DebugAdapterConfig, | |
| 956 | − start_debugging_requests_tx: futures::channel::mpsc::UnboundedSender<(SessionId, Message)>, | |
| 957 | − initialized_tx: oneshot::Sender<()>, | |
| 958 | − caps: Capabilities, | |
| 959 | − fails: bool, | |
| 960 | − cx: &mut App, | |
| 961 | − ) -> Task<Result<Entity<Session>>> { | |
| 962 | − let (message_tx, message_rx) = futures::channel::mpsc::unbounded(); | |
| 963 | − | |
| 964 | − cx.spawn(async move |cx| { | |
| 965 | − let mode = LocalMode::new_fake( | |
| 966 | 712 | session_id, |
| 967 | 713 | parent_session.clone(), |
| 968 | 714 | breakpoint_store.clone(), |
| 969 | 715 | config.clone(), |
| 970 | − delegate, | |
| 716 | + binary, | |
| 971 | 717 | message_tx, |
| 972 | − caps, | |
| 973 | − fails, | |
| 974 | 718 | cx.clone(), |
| 975 | 719 | ) |
| 976 | 720 | .await?; |
| @@ -1047,16 +791,23 @@ impl Session { · 70 unmodified lines | ||
| 1047 | 791 | &self.capabilities |
| 1048 | 792 | } |
| 1049 | 793 | |
| 794 | + pub fn binary(&self) -> &DebugAdapterBinary { | |
| 795 | + let Mode::Local(local_mode) = &self.mode else { | |
| 796 | + panic!("Session is not local"); | |
| 797 | + }; | |
| 798 | + &local_mode.binary | |
| 799 | + } | |
| 800 | + | |
| 1050 | 801 | pub fn adapter_name(&self) -> SharedString { |
| 1051 | 802 | match &self.mode { |
| 1052 | − Mode::Local(local_mode) => local_mode.adapter.name().into(), | |
| 803 | + Mode::Local(local_mode) => local_mode.definition.adapter.clone().into(), | |
| 1053 | 804 | Mode::Remote(remote_mode) => remote_mode._adapter_name.clone(), |
| 1054 | 805 | } |
| 1055 | 806 | } |
| 1056 | 807 | |
| 1057 | − pub fn configuration(&self) -> Option<DebugAdapterConfig> { | |
| 808 | + pub fn configuration(&self) -> Option<DebugTaskDefinition> { | |
| 1058 | 809 | if let Mode::Local(local_mode) = &self.mode { |
| 1059 | − Some(local_mode.config.clone()) | |
| 810 | + Some(local_mode.definition.clone()) | |
| 1060 | 811 | } else { |
| 1061 | 812 | None |
| 1062 | 813 | } |
| @@ -0,0 +1,98 @@ | ||
| 1 | +use std::{path::Path, sync::Arc}; | |
| 2 | + | |
| 3 | +use anyhow::Result; | |
| 4 | +use dap::{DebugRequestType, client::DebugAdapterClient}; | |
| 5 | +use gpui::{App, AppContext, Entity, Subscription, Task}; | |
| 6 | +use task::DebugTaskDefinition; | |
| 7 | + | |
| 8 | +use crate::Project; | |
| 9 | + | |
| 10 | +use super::session::Session; | |
| 11 | + | |
| 12 | +pub fn intercept_debug_sessions<T: Fn(&Arc<DebugAdapterClient>) + 'static>( | |
| 13 | + cx: &mut gpui::TestAppContext, | |
| 14 | + configure: T, | |
| 15 | +) -> Subscription { | |
| 16 | + cx.update(|cx| { | |
| 17 | + cx.observe_new::<Session>(move |session, _, cx| { | |
| 18 | + let client = session.adapter_client().unwrap(); | |
| 19 | + register_default_handlers(session, &client, cx); | |
| 20 | + configure(&client); | |
| 21 | + cx.background_spawn(async move { | |
| 22 | + client | |
| 23 | + .fake_event(dap::messages::Events::Initialized(Some(Default::default()))) | |
| 24 | + .await | |
| 25 | + }) | |
| 26 | + .detach(); | |
| 27 | + }) | |
| 28 | + }) | |
| 29 | +} | |
| 30 | + | |
| 31 | +pub fn start_debug_session_with<T: Fn(&Arc<DebugAdapterClient>) + 'static>( | |
| 32 | + project: &Entity<Project>, | |
| 33 | + cx: &mut gpui::TestAppContext, | |
| 34 | + config: DebugTaskDefinition, | |
| 35 | + configure: T, | |
| 36 | +) -> Task<Result<Entity<Session>>> { | |
| 37 | + let subscription = intercept_debug_sessions(cx, configure); | |
| 38 | + let task = project.update(cx, |project, cx| project.start_debug_session(config, cx)); | |
| 39 | + cx.spawn(async move |_| { | |
| 40 | + let result = task.await; | |
| 41 | + drop(subscription); | |
| 42 | + result | |
| 43 | + }) | |
| 44 | +} | |
| 45 | + | |
| 46 | +pub fn start_debug_session<T: Fn(&Arc<DebugAdapterClient>) + 'static>( | |
| 47 | + project: &Entity<Project>, | |
| 48 | + cx: &mut gpui::TestAppContext, | |
| 49 | + configure: T, | |
| 50 | +) -> Task<Result<Entity<Session>>> { | |
| 51 | + start_debug_session_with( | |
| 52 | + project, | |
| 53 | + cx, | |
| 54 | + DebugTaskDefinition { | |
| 55 | + adapter: "fake-adapter".to_string(), | |
| 56 | + request: DebugRequestType::Launch(Default::default()), | |
| 57 | + label: "test".to_string(), | |
| 58 | + initialize_args: None, | |
| 59 | + tcp_connection: None, | |
| 60 | + locator: None, | |
| 61 | + stop_on_entry: None, | |
| 62 | + }, | |
| 63 | + configure, | |
| 64 | + ) | |
| 65 | +} | |
| 66 | + | |
| 67 | +fn register_default_handlers(session: &Session, client: &Arc<DebugAdapterClient>, cx: &mut App) { | |
| 68 | + client.on_request::<dap::requests::Initialize, _>(move |_, _| Ok(Default::default())); | |
| 69 | + let paths = session | |
| 70 | + .as_local() | |
| 71 | + .unwrap() | |
| 72 | + .breakpoint_store | |
| 73 | + .read(cx) | |
| 74 | + .breakpoint_paths(); | |
| 75 | + | |
| 76 | + client.on_request::<dap::requests::SetBreakpoints, _>(move |_, args| { | |
| 77 | + let p = Arc::from(Path::new(&args.source.path.unwrap())); | |
| 78 | + if !paths.contains(&p) { | |
| 79 | + panic!("Sent breakpoints for path without any") | |
| 80 | + } | |
| 81 | + | |
| 82 | + Ok(dap::SetBreakpointsResponse { | |
| 83 | + breakpoints: Vec::default(), | |
| 84 | + }) | |
| 85 | + }); | |
| 86 | + | |
| 87 | + client.on_request::<dap::requests::Launch, _>(move |_, _| Ok(())); | |
| 88 | + | |
| 89 | + client.on_request::<dap::requests::SetExceptionBreakpoints, _>(move |_, _| { | |
| 90 | + Ok(dap::SetExceptionBreakpointsResponse { breakpoints: None }) | |
| 91 | + }); | |
| 92 | + | |
| 93 | + client.on_request::<dap::requests::Disconnect, _>(move |_, _| Ok(())); | |
| 94 | + | |
| 95 | + client.on_request::<dap::requests::Threads, _>(move |_, _| { | |
| 96 | + Ok(dap::ThreadsResponse { threads: vec![] }) | |
| 97 | + }); | |
| 98 | +} | |
| @@ -25,6 +25,7 @@ mod environment; · 24 unmodified lines | ||
| 25 | 25 | use buffer_diff::BufferDiff; |
| 26 | 26 | pub use environment::{EnvironmentErrorMessage, ProjectEnvironmentEvent}; |
| 27 | 27 | use git_store::{Repository, RepositoryId}; |
| 28 | +use task::DebugTaskDefinition; | |
| 28 | 29 | pub mod search_history; |
| 29 | 30 | mod yarn; |
| 30 | 31 | |
| @@ -38,7 +39,7 @@ use client::{ · 7 unmodified lines | ||
| 38 | 39 | }; |
| 39 | 40 | use clock::ReplicaId; |
| 40 | 41 | |
| 41 | −use dap::{DapRegistry, DebugAdapterConfig, client::DebugAdapterClient}; | |
| 42 | +use dap::{DapRegistry, client::DebugAdapterClient}; | |
| 42 | 43 | |
| 43 | 44 | use collections::{BTreeSet, HashMap, HashSet}; |
| 44 | 45 | use debounced_delay::DebouncedDelay; |
| @@ -106,7 +107,7 @@ use terminals::Terminals; · 61 unmodified lines | ||
| 106 | 107 | use text::{Anchor, BufferId}; |
| 107 | 108 | use toolchain_store::EmptyToolchainStore; |
| 108 | 109 | use util::{ |
| 109 | − ResultExt as _, maybe, | |
| 110 | + ResultExt as _, | |
| 110 | 111 | paths::{SanitizedPath, compare_paths}, |
| 111 | 112 | }; |
| 112 | 113 | use worktree::{CreatedEntry, Snapshot, Traversal}; |
| @@ -870,11 +871,9 @@ impl Project { · 757 unmodified lines | ||
| 870 | 871 | node.clone(), |
| 871 | 872 | fs.clone(), |
| 872 | 873 | languages.clone(), |
| 873 | − debug_adapters.clone(), | |
| 874 | 874 | environment.clone(), |
| 875 | 875 | toolchain_store.read(cx).as_language_toolchain_store(), |
| 876 | 876 | breakpoint_store.clone(), |
| 877 | − worktree_store.clone(), | |
| 878 | 877 | cx, |
| 879 | 878 | ) |
| 880 | 879 | }); |
| @@ -1458,64 +1457,46 @@ impl Project { · 577 unmodified lines | ||
| 1458 | 1457 | } |
| 1459 | 1458 | } |
| 1460 | 1459 | |
| 1461 | − pub fn queue_debug_session(&mut self, config: DebugAdapterConfig, cx: &mut Context<Self>) { | |
| 1462 | − if config.locator.is_none() { | |
| 1463 | − self.start_debug_session(config, cx).detach_and_log_err(cx); | |
| 1464 | − } | |
| 1465 | − } | |
| 1466 | − | |
| 1467 | 1460 | pub fn start_debug_session( |
| 1468 | 1461 | &mut self, |
| 1469 | − config: DebugAdapterConfig, | |
| 1462 | + config: DebugTaskDefinition, | |
| 1470 | 1463 | cx: &mut Context<Self>, |
| 1471 | 1464 | ) -> Task<Result<Entity<Session>>> { |
| 1472 | − let worktree = maybe!({ self.worktrees(cx).next() }); | |
| 1473 | − | |
| 1474 | − let Some(worktree) = &worktree else { | |
| 1465 | + let Some(worktree) = self.worktrees(cx).next() else { | |
| 1475 | 1466 | return Task::ready(Err(anyhow!("Failed to find a worktree"))); |
| 1476 | 1467 | }; |
| 1477 | 1468 | |
| 1478 | − self.dap_store | |
| 1479 | − .update(cx, |dap_store, cx| { | |
| 1480 | − dap_store.new_session(config, worktree, None, cx) | |
| 1481 | − }) | |
| 1482 | − .1 | |
| 1483 | − } | |
| 1469 | + let Some(adapter) = self.debug_adapters.adapter(&config.adapter) else { | |
| 1470 | + return Task::ready(Err(anyhow!("Failed to find a debug adapter"))); | |
| 1471 | + }; | |
| 1484 | 1472 | |
| 1485 | − #[cfg(any(test, feature = "test-support"))] | |
| 1486 | − pub fn fake_debug_session( | |
| 1487 | − &mut self, | |
| 1488 | − request: task::DebugRequestType, | |
| 1489 | − caps: Option<dap::Capabilities>, | |
| 1490 | − fails: bool, | |
| 1491 | − cx: &mut Context<Self>, | |
| 1492 | − ) -> Task<Result<Entity<Session>>> { | |
| 1493 | − use dap::{Capabilities, FakeAdapter}; | |
| 1494 | − use task::DebugRequestDisposition; | |
| 1473 | + let user_installed_path = ProjectSettings::get_global(cx) | |
| 1474 | + .dap | |
| 1475 | + .get(&adapter.name()) | |
| 1476 | + .and_then(|s| s.binary.as_ref().map(PathBuf::from)); | |
| 1495 | 1477 | |
| 1496 | − let worktree = maybe!({ self.worktrees(cx).next() }); | |
| 1478 | + let result = cx.spawn(async move |this, cx| { | |
| 1479 | + let delegate = this.update(cx, |project, cx| { | |
| 1480 | + project | |
| 1481 | + .dap_store | |
| 1482 | + .update(cx, |dap_store, cx| dap_store.delegate(&worktree, cx)) | |
| 1483 | + })?; | |
| 1497 | 1484 | |
| 1498 | − let Some(worktree) = &worktree else { | |
| 1499 | − return Task::ready(Err(anyhow!("Failed to find a worktree"))); | |
| 1500 | − }; | |
| 1501 | − let config = DebugAdapterConfig { | |
| 1502 | − label: "test config".into(), | |
| 1503 | − adapter: FakeAdapter::ADAPTER_NAME.into(), | |
| 1504 | − request: DebugRequestDisposition::UserConfigured(request), | |
| 1505 | − initialize_args: None, | |
| 1506 | − tcp_connection: None, | |
| 1507 | − locator: None, | |
| 1508 | − stop_on_entry: None, | |
| 1509 | − }; | |
| 1510 | − let caps = caps.unwrap_or(Capabilities { | |
| 1511 | − supports_step_back: Some(false), | |
| 1512 | − ..Default::default() | |
| 1485 | + let binary = adapter | |
| 1486 | + .get_binary(&delegate, &config, user_installed_path, cx) | |
| 1487 | + .await?; | |
| 1488 | + | |
| 1489 | + let ret = this | |
| 1490 | + .update(cx, |project, cx| { | |
| 1491 | + project.dap_store.update(cx, |dap_store, cx| { | |
| 1492 | + dap_store.new_session(binary, config, None, cx) | |
| 1493 | + }) | |
| 1494 | + })? | |
| 1495 | + .1 | |
| 1496 | + .await; | |
| 1497 | + ret | |
| 1513 | 1498 | }); |
| 1514 | − self.dap_store | |
| 1515 | − .update(cx, |dap_store, cx| { | |
| 1516 | − dap_store.new_fake_session(config, worktree, None, caps, fails, cx) | |
| 1517 | − }) | |
| 1518 | − .1 | |
| 1499 | + result | |
| 1519 | 1500 | } |
| 1520 | 1501 | |
| 1521 | 1502 | #[cfg(any(test, feature = "test-support"))] |
| @@ -39,7 +39,7 @@ use std::{env, mem, num::NonZeroU32, ops::Range, str::FromStr, sync::OnceLock, t · 38 unmodified lines | ||
| 39 | 39 | use task::{ResolvedTask, TaskContext}; |
| 40 | 40 | use unindent::Unindent as _; |
| 41 | 41 | use util::{ |
| 42 | − TryFutureExt as _, assert_set_eq, path, | |
| 42 | + TryFutureExt as _, assert_set_eq, maybe, path, | |
| 43 | 43 | paths::PathMatcher, |
| 44 | 44 | separator, |
| 45 | 45 | test::{TempTree, marked_text_offsets}, |
| @@ -72,7 +72,7 @@ impl HeadlessProject { · 71 unmodified lines | ||
| 72 | 72 | http_client, |
| 73 | 73 | node_runtime, |
| 74 | 74 | languages, |
| 75 | − debug_adapters, | |
| 75 | + debug_adapters: _debug_adapters, | |
| 76 | 76 | extension_host_proxy: proxy, |
| 77 | 77 | }: HeadlessAppState, |
| 78 | 78 | cx: &mut Context<Self>, |
| @@ -112,11 +112,9 @@ impl HeadlessProject { · 33 unmodified lines | ||
| 112 | 112 | node_runtime.clone(), |
| 113 | 113 | fs.clone(), |
| 114 | 114 | languages.clone(), |
| 115 | − debug_adapters.clone(), | |
| 116 | 115 | environment.clone(), |
| 117 | 116 | toolchain_store.read(cx).as_language_toolchain_store(), |
| 118 | 117 | breakpoint_store.clone(), |
| 119 | − worktree_store.clone(), | |
| 120 | 118 | cx, |
| 121 | 119 | ) |
| 122 | 120 | }); |
| @@ -104,7 +104,7 @@ impl ResolvedTask { · 103 unmodified lines | ||
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 | /// Get the configuration for the debug adapter that should be used for this task. |
| 107 | − pub fn resolved_debug_adapter_config(&self) -> Option<DebugAdapterConfig> { | |
| 107 | + pub fn resolved_debug_adapter_config(&self) -> Option<DebugTaskDefinition> { | |
| 108 | 108 | match self.original_task.task_type.clone() { |
| 109 | 109 | TaskType::Debug(debug_args) if self.resolved.is_some() => { |
| 110 | 110 | let resolved = self |
| @@ -127,10 +127,10 @@ impl ResolvedTask { · 16 unmodified lines | ||
| 127 | 127 | }) |
| 128 | 128 | .collect(); |
| 129 | 129 | |
| 130 | − Some(DebugAdapterConfig { | |
| 130 | + Some(DebugTaskDefinition { | |
| 131 | 131 | label: resolved.label.clone(), |
| 132 | 132 | adapter: debug_args.adapter.clone(), |
| 133 | − request: DebugRequestDisposition::UserConfigured(match debug_args.request { | |
| 133 | + request: match debug_args.request { | |
| 134 | 134 | crate::task_template::DebugArgsRequest::Launch => { |
| 135 | 135 | DebugRequestType::Launch(LaunchConfig { |
| 136 | 136 | program: resolved.command.clone(), |
| @@ -141,7 +141,7 @@ impl ResolvedTask { · 4 unmodified lines | ||
| 141 | 141 | crate::task_template::DebugArgsRequest::Attach(attach_config) => { |
| 142 | 142 | DebugRequestType::Attach(attach_config) |
| 143 | 143 | } |
| 144 | − }), | |
| 144 | + }, | |
| 145 | 145 | initialize_args: debug_args.initialize_args, |
| 146 | 146 | tcp_connection: debug_args.tcp_connection, |
| 147 | 147 | locator: debug_args.locator.clone(), |
| @@ -361,9 +361,8 @@ impl PickerDelegate for TasksModalDelegate { · 360 unmodified lines | ||
| 361 | 361 | |
| 362 | 362 | match task.task_type() { |
| 363 | 363 | TaskType::Debug(config) if config.locator.is_none() => { |
| 364 | − let Some(config): Option<DebugTaskDefinition> = task | |
| 365 | − .resolved_debug_adapter_config() | |
| 366 | − .and_then(|config| config.try_into().ok()) | |
| 364 | + let Some(config): Option<DebugTaskDefinition> = | |
| 365 | + task.resolved_debug_adapter_config() | |
| 367 | 366 | else { |
| 368 | 367 | return; |
| 369 | 368 | }; |
| @@ -382,7 +381,7 @@ impl PickerDelegate for TasksModalDelegate { · 12 unmodified lines | ||
| 382 | 381 | .update(cx, |workspace, cx| { |
| 383 | 382 | workspace.project().update(cx, |project, cx| { |
| 384 | 383 | project |
| 385 | − .start_debug_session(config.into(), cx) | |
| 384 | + .start_debug_session(config, cx) | |
| 386 | 385 | .detach_and_log_err(cx); |
| 387 | 386 | }); |
| 388 | 387 | }) |
| @@ -96,7 +96,7 @@ use std::{ · 95 unmodified lines | ||
| 96 | 96 | sync::{Arc, LazyLock, Weak, atomic::AtomicUsize}, |
| 97 | 97 | time::Duration, |
| 98 | 98 | }; |
| 99 | −use task::{DebugAdapterConfig, SpawnInTerminal, TaskId}; | |
| 99 | +use task::{DebugTaskDefinition, SpawnInTerminal, TaskId}; | |
| 100 | 100 | use theme::{ActiveTheme, SystemAppearance, ThemeSettings}; |
| 101 | 101 | pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView}; |
| 102 | 102 | pub use ui; |
| @@ -858,7 +858,7 @@ pub struct Workspace { · 755 unmodified lines | ||
| 858 | 858 | serialized_ssh_project: Option<SerializedSshProject>, |
| 859 | 859 | _items_serializer: Task<Result<()>>, |
| 860 | 860 | session_id: Option<String>, |
| 861 | − debug_task_queue: HashMap<task::TaskId, DebugAdapterConfig>, | |
| 861 | + debug_task_queue: HashMap<task::TaskId, DebugTaskDefinition>, | |
| 862 | 862 | } |
| 863 | 863 | |
| 864 | 864 | impl EventEmitter<Event> for Workspace {} |