dap_command.rs

   1use std::sync::Arc;
   2
   3use anyhow::{Context as _, Ok, Result};
   4use dap::{
   5    Capabilities, ContinueArguments, ExceptionFilterOptions, InitializeRequestArguments,
   6    InitializeRequestArgumentsPathFormat, NextArguments, SetVariableResponse, SourceBreakpoint,
   7    StepInArguments, StepOutArguments, SteppingGranularity, ValueFormat, Variable,
   8    VariablesArgumentsFilter,
   9    client::SessionId,
  10    proto_conversions::ProtoConversion,
  11    requests::{Continue, Next},
  12};
  13use rpc::proto;
  14use serde_json::Value;
  15use util::ResultExt;
  16
  17pub trait LocalDapCommand: 'static + Send + Sync + std::fmt::Debug {
  18    type Response: 'static + Send + std::fmt::Debug;
  19    type DapRequest: 'static + Send + dap::requests::Request;
  20    /// Is this request idempotent? Is it safe to cache the response for as long as the execution environment is unchanged?
  21    const CACHEABLE: bool = false;
  22
  23    fn is_supported(_capabilities: &Capabilities) -> bool {
  24        true
  25    }
  26
  27    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments;
  28
  29    fn response_from_dap(
  30        &self,
  31        message: <Self::DapRequest as dap::requests::Request>::Response,
  32    ) -> Result<Self::Response>;
  33}
  34
  35pub trait DapCommand: LocalDapCommand {
  36    type ProtoRequest: 'static + Send;
  37    type ProtoResponse: 'static + Send;
  38
  39    #[allow(dead_code)]
  40    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId;
  41
  42    #[allow(dead_code)]
  43    fn from_proto(request: &Self::ProtoRequest) -> Self;
  44
  45    #[allow(unused)]
  46    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest;
  47
  48    #[allow(dead_code)]
  49    fn response_to_proto(
  50        debug_client_id: SessionId,
  51        message: Self::Response,
  52    ) -> Self::ProtoResponse;
  53
  54    #[allow(unused)]
  55    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response>;
  56}
  57
  58impl<T: LocalDapCommand> LocalDapCommand for Arc<T> {
  59    type Response = T::Response;
  60    type DapRequest = T::DapRequest;
  61
  62    fn is_supported(capabilities: &Capabilities) -> bool {
  63        T::is_supported(capabilities)
  64    }
  65
  66    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
  67        T::to_dap(self)
  68    }
  69
  70    fn response_from_dap(
  71        &self,
  72        message: <Self::DapRequest as dap::requests::Request>::Response,
  73    ) -> Result<Self::Response> {
  74        T::response_from_dap(self, message)
  75    }
  76}
  77
  78impl<T: DapCommand> DapCommand for Arc<T> {
  79    type ProtoRequest = T::ProtoRequest;
  80    type ProtoResponse = T::ProtoResponse;
  81
  82    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
  83        T::client_id_from_proto(request)
  84    }
  85
  86    fn from_proto(request: &Self::ProtoRequest) -> Self {
  87        Arc::new(T::from_proto(request))
  88    }
  89
  90    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
  91        T::to_proto(self, debug_client_id, upstream_project_id)
  92    }
  93
  94    fn response_to_proto(
  95        debug_client_id: SessionId,
  96        message: Self::Response,
  97    ) -> Self::ProtoResponse {
  98        T::response_to_proto(debug_client_id, message)
  99    }
 100
 101    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 102        T::response_from_proto(self, message)
 103    }
 104}
 105
 106#[derive(Debug, Hash, PartialEq, Eq)]
 107pub struct StepCommand {
 108    pub thread_id: u64,
 109    pub granularity: Option<SteppingGranularity>,
 110    pub single_thread: Option<bool>,
 111}
 112
 113impl StepCommand {
 114    fn from_proto(message: proto::DapNextRequest) -> Self {
 115        const LINE: i32 = proto::SteppingGranularity::Line as i32;
 116        const INSTRUCTION: i32 = proto::SteppingGranularity::Instruction as i32;
 117
 118        let granularity = message.granularity.map(|granularity| match granularity {
 119            LINE => SteppingGranularity::Line,
 120            INSTRUCTION => SteppingGranularity::Instruction,
 121            _ => SteppingGranularity::Statement,
 122        });
 123
 124        Self {
 125            thread_id: message.thread_id,
 126            granularity,
 127            single_thread: message.single_thread,
 128        }
 129    }
 130}
 131
 132#[derive(Debug, Hash, PartialEq, Eq)]
 133pub(crate) struct NextCommand {
 134    pub inner: StepCommand,
 135}
 136
 137impl LocalDapCommand for NextCommand {
 138    type Response = <Next as dap::requests::Request>::Response;
 139    type DapRequest = Next;
 140
 141    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 142        NextArguments {
 143            thread_id: self.inner.thread_id,
 144            single_thread: self.inner.single_thread,
 145            granularity: self.inner.granularity,
 146        }
 147    }
 148    fn response_from_dap(
 149        &self,
 150        _message: <Self::DapRequest as dap::requests::Request>::Response,
 151    ) -> Result<Self::Response> {
 152        Ok(())
 153    }
 154}
 155
 156impl DapCommand for NextCommand {
 157    type ProtoRequest = proto::DapNextRequest;
 158    type ProtoResponse = proto::Ack;
 159
 160    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 161        SessionId::from_proto(request.client_id)
 162    }
 163
 164    fn from_proto(request: &Self::ProtoRequest) -> Self {
 165        Self {
 166            inner: StepCommand::from_proto(request.clone()),
 167        }
 168    }
 169
 170    fn response_to_proto(
 171        _debug_client_id: SessionId,
 172        _message: Self::Response,
 173    ) -> Self::ProtoResponse {
 174        proto::Ack {}
 175    }
 176
 177    fn to_proto(
 178        &self,
 179        debug_client_id: SessionId,
 180        upstream_project_id: u64,
 181    ) -> proto::DapNextRequest {
 182        proto::DapNextRequest {
 183            project_id: upstream_project_id,
 184            client_id: debug_client_id.to_proto(),
 185            thread_id: self.inner.thread_id,
 186            single_thread: self.inner.single_thread,
 187            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 188        }
 189    }
 190
 191    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 192        Ok(())
 193    }
 194}
 195
 196#[derive(Debug, Hash, PartialEq, Eq)]
 197pub(crate) struct StepInCommand {
 198    pub inner: StepCommand,
 199}
 200
 201impl LocalDapCommand for StepInCommand {
 202    type Response = <dap::requests::StepIn as dap::requests::Request>::Response;
 203    type DapRequest = dap::requests::StepIn;
 204
 205    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 206        StepInArguments {
 207            thread_id: self.inner.thread_id,
 208            single_thread: self.inner.single_thread,
 209            target_id: None,
 210            granularity: self.inner.granularity,
 211        }
 212    }
 213
 214    fn response_from_dap(
 215        &self,
 216        _message: <Self::DapRequest as dap::requests::Request>::Response,
 217    ) -> Result<Self::Response> {
 218        Ok(())
 219    }
 220}
 221
 222impl DapCommand for StepInCommand {
 223    type ProtoRequest = proto::DapStepInRequest;
 224    type ProtoResponse = proto::Ack;
 225
 226    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 227        SessionId::from_proto(request.client_id)
 228    }
 229
 230    fn from_proto(request: &Self::ProtoRequest) -> Self {
 231        Self {
 232            inner: StepCommand::from_proto(proto::DapNextRequest {
 233                project_id: request.project_id,
 234                client_id: request.client_id,
 235                thread_id: request.thread_id,
 236                single_thread: request.single_thread,
 237                granularity: request.granularity,
 238            }),
 239        }
 240    }
 241
 242    fn response_to_proto(
 243        _debug_client_id: SessionId,
 244        _message: Self::Response,
 245    ) -> Self::ProtoResponse {
 246        proto::Ack {}
 247    }
 248
 249    fn to_proto(
 250        &self,
 251        debug_client_id: SessionId,
 252        upstream_project_id: u64,
 253    ) -> proto::DapStepInRequest {
 254        proto::DapStepInRequest {
 255            project_id: upstream_project_id,
 256            client_id: debug_client_id.to_proto(),
 257            thread_id: self.inner.thread_id,
 258            single_thread: self.inner.single_thread,
 259            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 260            target_id: None,
 261        }
 262    }
 263
 264    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 265        Ok(())
 266    }
 267}
 268
 269#[derive(Debug, Hash, PartialEq, Eq)]
 270pub(crate) struct StepOutCommand {
 271    pub inner: StepCommand,
 272}
 273
 274impl LocalDapCommand for StepOutCommand {
 275    type Response = <dap::requests::StepOut as dap::requests::Request>::Response;
 276    type DapRequest = dap::requests::StepOut;
 277
 278    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 279        StepOutArguments {
 280            thread_id: self.inner.thread_id,
 281            single_thread: self.inner.single_thread,
 282            granularity: self.inner.granularity,
 283        }
 284    }
 285
 286    fn response_from_dap(
 287        &self,
 288        _message: <Self::DapRequest as dap::requests::Request>::Response,
 289    ) -> Result<Self::Response> {
 290        Ok(())
 291    }
 292}
 293
 294impl DapCommand for StepOutCommand {
 295    type ProtoRequest = proto::DapStepOutRequest;
 296    type ProtoResponse = proto::Ack;
 297
 298    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 299        SessionId::from_proto(request.client_id)
 300    }
 301
 302    fn from_proto(request: &Self::ProtoRequest) -> Self {
 303        Self {
 304            inner: StepCommand::from_proto(proto::DapNextRequest {
 305                project_id: request.project_id,
 306                client_id: request.client_id,
 307                thread_id: request.thread_id,
 308                single_thread: request.single_thread,
 309                granularity: request.granularity,
 310            }),
 311        }
 312    }
 313
 314    fn response_to_proto(
 315        _debug_client_id: SessionId,
 316        _message: Self::Response,
 317    ) -> Self::ProtoResponse {
 318        proto::Ack {}
 319    }
 320
 321    fn to_proto(
 322        &self,
 323        debug_client_id: SessionId,
 324        upstream_project_id: u64,
 325    ) -> proto::DapStepOutRequest {
 326        proto::DapStepOutRequest {
 327            project_id: upstream_project_id,
 328            client_id: debug_client_id.to_proto(),
 329            thread_id: self.inner.thread_id,
 330            single_thread: self.inner.single_thread,
 331            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 332        }
 333    }
 334
 335    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 336        Ok(())
 337    }
 338}
 339
 340#[derive(Debug, Hash, PartialEq, Eq)]
 341pub(crate) struct StepBackCommand {
 342    pub inner: StepCommand,
 343}
 344impl LocalDapCommand for StepBackCommand {
 345    type Response = <dap::requests::StepBack as dap::requests::Request>::Response;
 346    type DapRequest = dap::requests::StepBack;
 347
 348    fn is_supported(capabilities: &Capabilities) -> bool {
 349        capabilities.supports_step_back.unwrap_or_default()
 350    }
 351
 352    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 353        dap::StepBackArguments {
 354            thread_id: self.inner.thread_id,
 355            single_thread: self.inner.single_thread,
 356            granularity: self.inner.granularity,
 357        }
 358    }
 359
 360    fn response_from_dap(
 361        &self,
 362        _message: <Self::DapRequest as dap::requests::Request>::Response,
 363    ) -> Result<Self::Response> {
 364        Ok(())
 365    }
 366}
 367
 368impl DapCommand for StepBackCommand {
 369    type ProtoRequest = proto::DapStepBackRequest;
 370    type ProtoResponse = proto::Ack;
 371
 372    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 373        SessionId::from_proto(request.client_id)
 374    }
 375
 376    fn from_proto(request: &Self::ProtoRequest) -> Self {
 377        Self {
 378            inner: StepCommand::from_proto(proto::DapNextRequest {
 379                project_id: request.project_id,
 380                client_id: request.client_id,
 381                thread_id: request.thread_id,
 382                single_thread: request.single_thread,
 383                granularity: request.granularity,
 384            }),
 385        }
 386    }
 387
 388    fn response_to_proto(
 389        _debug_client_id: SessionId,
 390        _message: Self::Response,
 391    ) -> Self::ProtoResponse {
 392        proto::Ack {}
 393    }
 394
 395    fn to_proto(
 396        &self,
 397        debug_client_id: SessionId,
 398        upstream_project_id: u64,
 399    ) -> proto::DapStepBackRequest {
 400        proto::DapStepBackRequest {
 401            project_id: upstream_project_id,
 402            client_id: debug_client_id.to_proto(),
 403            thread_id: self.inner.thread_id,
 404            single_thread: self.inner.single_thread,
 405            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
 406        }
 407    }
 408
 409    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 410        Ok(())
 411    }
 412}
 413
 414#[derive(Debug, Hash, PartialEq, Eq)]
 415pub(crate) struct ContinueCommand {
 416    pub args: ContinueArguments,
 417}
 418
 419impl LocalDapCommand for ContinueCommand {
 420    type Response = <Continue as dap::requests::Request>::Response;
 421    type DapRequest = Continue;
 422
 423    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 424        self.args.clone()
 425    }
 426
 427    fn response_from_dap(
 428        &self,
 429        message: <Self::DapRequest as dap::requests::Request>::Response,
 430    ) -> Result<Self::Response> {
 431        Ok(message)
 432    }
 433}
 434
 435impl DapCommand for ContinueCommand {
 436    type ProtoRequest = proto::DapContinueRequest;
 437    type ProtoResponse = proto::DapContinueResponse;
 438
 439    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 440        SessionId::from_proto(request.client_id)
 441    }
 442
 443    fn to_proto(
 444        &self,
 445        debug_client_id: SessionId,
 446        upstream_project_id: u64,
 447    ) -> proto::DapContinueRequest {
 448        proto::DapContinueRequest {
 449            project_id: upstream_project_id,
 450            client_id: debug_client_id.to_proto(),
 451            thread_id: self.args.thread_id,
 452            single_thread: self.args.single_thread,
 453        }
 454    }
 455
 456    fn from_proto(request: &Self::ProtoRequest) -> Self {
 457        Self {
 458            args: ContinueArguments {
 459                thread_id: request.thread_id,
 460                single_thread: request.single_thread,
 461            },
 462        }
 463    }
 464
 465    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 466        Ok(Self::Response {
 467            all_threads_continued: message.all_threads_continued,
 468        })
 469    }
 470
 471    fn response_to_proto(
 472        debug_client_id: SessionId,
 473        message: Self::Response,
 474    ) -> Self::ProtoResponse {
 475        proto::DapContinueResponse {
 476            client_id: debug_client_id.to_proto(),
 477            all_threads_continued: message.all_threads_continued,
 478        }
 479    }
 480}
 481
 482#[derive(Debug, Hash, PartialEq, Eq)]
 483pub(crate) struct PauseCommand {
 484    pub thread_id: u64,
 485}
 486
 487impl LocalDapCommand for PauseCommand {
 488    type Response = <dap::requests::Pause as dap::requests::Request>::Response;
 489    type DapRequest = dap::requests::Pause;
 490    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 491        dap::PauseArguments {
 492            thread_id: self.thread_id,
 493        }
 494    }
 495
 496    fn response_from_dap(
 497        &self,
 498        _message: <Self::DapRequest as dap::requests::Request>::Response,
 499    ) -> Result<Self::Response> {
 500        Ok(())
 501    }
 502}
 503
 504impl DapCommand for PauseCommand {
 505    type ProtoRequest = proto::DapPauseRequest;
 506    type ProtoResponse = proto::Ack;
 507
 508    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 509        SessionId::from_proto(request.client_id)
 510    }
 511
 512    fn from_proto(request: &Self::ProtoRequest) -> Self {
 513        Self {
 514            thread_id: request.thread_id,
 515        }
 516    }
 517
 518    fn to_proto(
 519        &self,
 520        debug_client_id: SessionId,
 521        upstream_project_id: u64,
 522    ) -> proto::DapPauseRequest {
 523        proto::DapPauseRequest {
 524            project_id: upstream_project_id,
 525            client_id: debug_client_id.to_proto(),
 526            thread_id: self.thread_id,
 527        }
 528    }
 529
 530    fn response_to_proto(
 531        _debug_client_id: SessionId,
 532        _message: Self::Response,
 533    ) -> Self::ProtoResponse {
 534        proto::Ack {}
 535    }
 536
 537    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 538        Ok(())
 539    }
 540}
 541
 542#[derive(Debug, Hash, PartialEq, Eq)]
 543pub(crate) struct DisconnectCommand {
 544    pub restart: Option<bool>,
 545    pub terminate_debuggee: Option<bool>,
 546    pub suspend_debuggee: Option<bool>,
 547}
 548
 549impl LocalDapCommand for DisconnectCommand {
 550    type Response = <dap::requests::Disconnect as dap::requests::Request>::Response;
 551    type DapRequest = dap::requests::Disconnect;
 552
 553    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 554        dap::DisconnectArguments {
 555            restart: self.restart,
 556            terminate_debuggee: self.terminate_debuggee,
 557            suspend_debuggee: self.suspend_debuggee,
 558        }
 559    }
 560
 561    fn response_from_dap(
 562        &self,
 563        _message: <Self::DapRequest as dap::requests::Request>::Response,
 564    ) -> Result<Self::Response> {
 565        Ok(())
 566    }
 567}
 568
 569impl DapCommand for DisconnectCommand {
 570    type ProtoRequest = proto::DapDisconnectRequest;
 571    type ProtoResponse = proto::Ack;
 572
 573    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 574        SessionId::from_proto(request.client_id)
 575    }
 576
 577    fn from_proto(request: &Self::ProtoRequest) -> Self {
 578        Self {
 579            restart: request.restart,
 580            terminate_debuggee: request.terminate_debuggee,
 581            suspend_debuggee: request.suspend_debuggee,
 582        }
 583    }
 584
 585    fn to_proto(
 586        &self,
 587        debug_client_id: SessionId,
 588        upstream_project_id: u64,
 589    ) -> proto::DapDisconnectRequest {
 590        proto::DapDisconnectRequest {
 591            project_id: upstream_project_id,
 592            client_id: debug_client_id.to_proto(),
 593            restart: self.restart,
 594            terminate_debuggee: self.terminate_debuggee,
 595            suspend_debuggee: self.suspend_debuggee,
 596        }
 597    }
 598
 599    fn response_to_proto(
 600        _debug_client_id: SessionId,
 601        _message: Self::Response,
 602    ) -> Self::ProtoResponse {
 603        proto::Ack {}
 604    }
 605
 606    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 607        Ok(())
 608    }
 609}
 610
 611#[derive(Debug, Hash, PartialEq, Eq)]
 612pub(crate) struct TerminateThreadsCommand {
 613    pub thread_ids: Option<Vec<u64>>,
 614}
 615
 616impl LocalDapCommand for TerminateThreadsCommand {
 617    type Response = <dap::requests::TerminateThreads as dap::requests::Request>::Response;
 618    type DapRequest = dap::requests::TerminateThreads;
 619
 620    fn is_supported(capabilities: &Capabilities) -> bool {
 621        capabilities
 622            .supports_terminate_threads_request
 623            .unwrap_or_default()
 624    }
 625
 626    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 627        dap::TerminateThreadsArguments {
 628            thread_ids: self.thread_ids.clone(),
 629        }
 630    }
 631
 632    fn response_from_dap(
 633        &self,
 634        _message: <Self::DapRequest as dap::requests::Request>::Response,
 635    ) -> Result<Self::Response> {
 636        Ok(())
 637    }
 638}
 639
 640impl DapCommand for TerminateThreadsCommand {
 641    type ProtoRequest = proto::DapTerminateThreadsRequest;
 642    type ProtoResponse = proto::Ack;
 643
 644    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 645        SessionId::from_proto(request.client_id)
 646    }
 647
 648    fn from_proto(request: &Self::ProtoRequest) -> Self {
 649        let thread_ids = if request.thread_ids.is_empty() {
 650            None
 651        } else {
 652            Some(request.thread_ids.clone())
 653        };
 654
 655        Self { thread_ids }
 656    }
 657
 658    fn to_proto(
 659        &self,
 660        debug_client_id: SessionId,
 661        upstream_project_id: u64,
 662    ) -> proto::DapTerminateThreadsRequest {
 663        proto::DapTerminateThreadsRequest {
 664            project_id: upstream_project_id,
 665            client_id: debug_client_id.to_proto(),
 666            thread_ids: self.thread_ids.clone().unwrap_or_default(),
 667        }
 668    }
 669
 670    fn response_to_proto(
 671        _debug_client_id: SessionId,
 672        _message: Self::Response,
 673    ) -> Self::ProtoResponse {
 674        proto::Ack {}
 675    }
 676
 677    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 678        Ok(())
 679    }
 680}
 681
 682#[derive(Debug, Hash, PartialEq, Eq)]
 683pub(crate) struct TerminateCommand {
 684    pub restart: Option<bool>,
 685}
 686
 687impl LocalDapCommand for TerminateCommand {
 688    type Response = <dap::requests::Terminate as dap::requests::Request>::Response;
 689    type DapRequest = dap::requests::Terminate;
 690
 691    fn is_supported(capabilities: &Capabilities) -> bool {
 692        capabilities.supports_terminate_request.unwrap_or_default()
 693    }
 694    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 695        dap::TerminateArguments {
 696            restart: self.restart,
 697        }
 698    }
 699
 700    fn response_from_dap(
 701        &self,
 702        _message: <Self::DapRequest as dap::requests::Request>::Response,
 703    ) -> Result<Self::Response> {
 704        Ok(())
 705    }
 706}
 707
 708impl DapCommand for TerminateCommand {
 709    type ProtoRequest = proto::DapTerminateRequest;
 710    type ProtoResponse = proto::Ack;
 711
 712    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 713        SessionId::from_proto(request.client_id)
 714    }
 715
 716    fn from_proto(request: &Self::ProtoRequest) -> Self {
 717        Self {
 718            restart: request.restart,
 719        }
 720    }
 721
 722    fn to_proto(
 723        &self,
 724        debug_client_id: SessionId,
 725        upstream_project_id: u64,
 726    ) -> proto::DapTerminateRequest {
 727        proto::DapTerminateRequest {
 728            project_id: upstream_project_id,
 729            client_id: debug_client_id.to_proto(),
 730            restart: self.restart,
 731        }
 732    }
 733
 734    fn response_to_proto(
 735        _debug_client_id: SessionId,
 736        _message: Self::Response,
 737    ) -> Self::ProtoResponse {
 738        proto::Ack {}
 739    }
 740
 741    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 742        Ok(())
 743    }
 744}
 745
 746#[derive(Debug, Hash, PartialEq, Eq)]
 747pub(crate) struct RestartCommand {
 748    pub raw: serde_json::Value,
 749}
 750
 751impl LocalDapCommand for RestartCommand {
 752    type Response = <dap::requests::Restart as dap::requests::Request>::Response;
 753    type DapRequest = dap::requests::Restart;
 754
 755    fn is_supported(capabilities: &Capabilities) -> bool {
 756        capabilities.supports_restart_request.unwrap_or_default()
 757    }
 758
 759    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 760        dap::RestartArguments {
 761            raw: self.raw.clone(),
 762        }
 763    }
 764
 765    fn response_from_dap(
 766        &self,
 767        _message: <Self::DapRequest as dap::requests::Request>::Response,
 768    ) -> Result<Self::Response> {
 769        Ok(())
 770    }
 771}
 772
 773impl DapCommand for RestartCommand {
 774    type ProtoRequest = proto::DapRestartRequest;
 775    type ProtoResponse = proto::Ack;
 776
 777    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 778        SessionId::from_proto(request.client_id)
 779    }
 780
 781    fn from_proto(request: &Self::ProtoRequest) -> Self {
 782        Self {
 783            raw: serde_json::from_slice(&request.raw_args)
 784                .log_err()
 785                .unwrap_or(serde_json::Value::Null),
 786        }
 787    }
 788
 789    fn to_proto(
 790        &self,
 791        debug_client_id: SessionId,
 792        upstream_project_id: u64,
 793    ) -> proto::DapRestartRequest {
 794        let raw_args = serde_json::to_vec(&self.raw).log_err().unwrap_or_default();
 795
 796        proto::DapRestartRequest {
 797            project_id: upstream_project_id,
 798            client_id: debug_client_id.to_proto(),
 799            raw_args,
 800        }
 801    }
 802
 803    fn response_to_proto(
 804        _debug_client_id: SessionId,
 805        _message: Self::Response,
 806    ) -> Self::ProtoResponse {
 807        proto::Ack {}
 808    }
 809
 810    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
 811        Ok(())
 812    }
 813}
 814
 815#[derive(Debug, Hash, PartialEq, Eq)]
 816pub struct VariablesCommand {
 817    pub variables_reference: u64,
 818    pub filter: Option<VariablesArgumentsFilter>,
 819    pub start: Option<u64>,
 820    pub count: Option<u64>,
 821    pub format: Option<ValueFormat>,
 822}
 823
 824impl LocalDapCommand for VariablesCommand {
 825    type Response = Vec<Variable>;
 826    type DapRequest = dap::requests::Variables;
 827    const CACHEABLE: bool = true;
 828
 829    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 830        dap::VariablesArguments {
 831            variables_reference: self.variables_reference,
 832            filter: self.filter,
 833            start: self.start,
 834            count: self.count,
 835            format: self.format.clone(),
 836        }
 837    }
 838
 839    fn response_from_dap(
 840        &self,
 841        message: <Self::DapRequest as dap::requests::Request>::Response,
 842    ) -> Result<Self::Response> {
 843        Ok(message.variables)
 844    }
 845}
 846
 847impl DapCommand for VariablesCommand {
 848    type ProtoRequest = proto::VariablesRequest;
 849    type ProtoResponse = proto::DapVariables;
 850
 851    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 852        SessionId::from_proto(request.client_id)
 853    }
 854
 855    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
 856        proto::VariablesRequest {
 857            project_id: upstream_project_id,
 858            client_id: debug_client_id.to_proto(),
 859            variables_reference: self.variables_reference,
 860            filter: None,
 861            start: self.start,
 862            count: self.count,
 863            format: None,
 864        }
 865    }
 866
 867    fn from_proto(request: &Self::ProtoRequest) -> Self {
 868        Self {
 869            variables_reference: request.variables_reference,
 870            filter: None,
 871            start: request.start,
 872            count: request.count,
 873            format: None,
 874        }
 875    }
 876
 877    fn response_to_proto(
 878        debug_client_id: SessionId,
 879        message: Self::Response,
 880    ) -> Self::ProtoResponse {
 881        proto::DapVariables {
 882            client_id: debug_client_id.to_proto(),
 883            variables: message.to_proto(),
 884        }
 885    }
 886
 887    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 888        Ok(Vec::from_proto(message.variables))
 889    }
 890}
 891
 892#[derive(Debug, Hash, PartialEq, Eq)]
 893pub(crate) struct SetVariableValueCommand {
 894    pub name: String,
 895    pub value: String,
 896    pub variables_reference: u64,
 897}
 898impl LocalDapCommand for SetVariableValueCommand {
 899    type Response = SetVariableResponse;
 900    type DapRequest = dap::requests::SetVariable;
 901    fn is_supported(capabilities: &Capabilities) -> bool {
 902        capabilities.supports_set_variable.unwrap_or_default()
 903    }
 904    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 905        dap::SetVariableArguments {
 906            format: None,
 907            name: self.name.clone(),
 908            value: self.value.clone(),
 909            variables_reference: self.variables_reference,
 910        }
 911    }
 912    fn response_from_dap(
 913        &self,
 914        message: <Self::DapRequest as dap::requests::Request>::Response,
 915    ) -> Result<Self::Response> {
 916        Ok(message)
 917    }
 918}
 919
 920impl DapCommand for SetVariableValueCommand {
 921    type ProtoRequest = proto::DapSetVariableValueRequest;
 922    type ProtoResponse = proto::DapSetVariableValueResponse;
 923
 924    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
 925        SessionId::from_proto(request.client_id)
 926    }
 927
 928    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
 929        proto::DapSetVariableValueRequest {
 930            project_id: upstream_project_id,
 931            client_id: debug_client_id.to_proto(),
 932            variables_reference: self.variables_reference,
 933            value: self.value.clone(),
 934            name: self.name.clone(),
 935        }
 936    }
 937
 938    fn from_proto(request: &Self::ProtoRequest) -> Self {
 939        Self {
 940            variables_reference: request.variables_reference,
 941            name: request.name.clone(),
 942            value: request.value.clone(),
 943        }
 944    }
 945
 946    fn response_to_proto(
 947        debug_client_id: SessionId,
 948        message: Self::Response,
 949    ) -> Self::ProtoResponse {
 950        proto::DapSetVariableValueResponse {
 951            client_id: debug_client_id.to_proto(),
 952            value: message.value,
 953            variable_type: message.type_,
 954            named_variables: message.named_variables,
 955            variables_reference: message.variables_reference,
 956            indexed_variables: message.indexed_variables,
 957            memory_reference: message.memory_reference,
 958        }
 959    }
 960
 961    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
 962        Ok(SetVariableResponse {
 963            value: message.value,
 964            type_: message.variable_type,
 965            variables_reference: message.variables_reference,
 966            named_variables: message.named_variables,
 967            indexed_variables: message.indexed_variables,
 968            memory_reference: message.memory_reference,
 969            value_location_reference: None, // TODO
 970        })
 971    }
 972}
 973
 974#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 975pub(crate) struct RestartStackFrameCommand {
 976    pub stack_frame_id: u64,
 977}
 978
 979impl LocalDapCommand for RestartStackFrameCommand {
 980    type Response = <dap::requests::RestartFrame as dap::requests::Request>::Response;
 981    type DapRequest = dap::requests::RestartFrame;
 982
 983    fn is_supported(capabilities: &Capabilities) -> bool {
 984        capabilities.supports_restart_frame.unwrap_or_default()
 985    }
 986
 987    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
 988        dap::RestartFrameArguments {
 989            frame_id: self.stack_frame_id,
 990        }
 991    }
 992
 993    fn response_from_dap(
 994        &self,
 995        _message: <Self::DapRequest as dap::requests::Request>::Response,
 996    ) -> Result<Self::Response> {
 997        Ok(())
 998    }
 999}
1000
1001impl DapCommand for RestartStackFrameCommand {
1002    type ProtoRequest = proto::DapRestartStackFrameRequest;
1003    type ProtoResponse = proto::Ack;
1004
1005    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1006        SessionId::from_proto(request.client_id)
1007    }
1008
1009    fn from_proto(request: &Self::ProtoRequest) -> Self {
1010        Self {
1011            stack_frame_id: request.stack_frame_id,
1012        }
1013    }
1014
1015    fn to_proto(
1016        &self,
1017        debug_client_id: SessionId,
1018        upstream_project_id: u64,
1019    ) -> proto::DapRestartStackFrameRequest {
1020        proto::DapRestartStackFrameRequest {
1021            project_id: upstream_project_id,
1022            client_id: debug_client_id.to_proto(),
1023            stack_frame_id: self.stack_frame_id,
1024        }
1025    }
1026
1027    fn response_to_proto(
1028        _debug_client_id: SessionId,
1029        _message: Self::Response,
1030    ) -> Self::ProtoResponse {
1031        proto::Ack {}
1032    }
1033
1034    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
1035        Ok(())
1036    }
1037}
1038
1039#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1040pub(crate) struct ModulesCommand;
1041
1042impl LocalDapCommand for ModulesCommand {
1043    type Response = Vec<dap::Module>;
1044    type DapRequest = dap::requests::Modules;
1045    const CACHEABLE: bool = true;
1046
1047    fn is_supported(capabilities: &Capabilities) -> bool {
1048        capabilities.supports_modules_request.unwrap_or_default()
1049    }
1050
1051    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1052        dap::ModulesArguments {
1053            start_module: None,
1054            module_count: None,
1055        }
1056    }
1057
1058    fn response_from_dap(
1059        &self,
1060        message: <Self::DapRequest as dap::requests::Request>::Response,
1061    ) -> Result<Self::Response> {
1062        Ok(message.modules)
1063    }
1064}
1065
1066impl DapCommand for ModulesCommand {
1067    type ProtoRequest = proto::DapModulesRequest;
1068    type ProtoResponse = proto::DapModulesResponse;
1069
1070    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1071        SessionId::from_proto(request.client_id)
1072    }
1073
1074    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1075        Self {}
1076    }
1077
1078    fn to_proto(
1079        &self,
1080        debug_client_id: SessionId,
1081        upstream_project_id: u64,
1082    ) -> proto::DapModulesRequest {
1083        proto::DapModulesRequest {
1084            project_id: upstream_project_id,
1085            client_id: debug_client_id.to_proto(),
1086        }
1087    }
1088
1089    fn response_to_proto(
1090        debug_client_id: SessionId,
1091        message: Self::Response,
1092    ) -> Self::ProtoResponse {
1093        proto::DapModulesResponse {
1094            modules: message
1095                .into_iter()
1096                .map(|module| module.to_proto())
1097                .collect(),
1098            client_id: debug_client_id.to_proto(),
1099        }
1100    }
1101
1102    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1103        Ok(message
1104            .modules
1105            .into_iter()
1106            .filter_map(|module| dap::Module::from_proto(module).ok())
1107            .collect())
1108    }
1109}
1110
1111#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1112pub(crate) struct LoadedSourcesCommand;
1113
1114impl LocalDapCommand for LoadedSourcesCommand {
1115    type Response = Vec<dap::Source>;
1116    type DapRequest = dap::requests::LoadedSources;
1117    const CACHEABLE: bool = true;
1118
1119    fn is_supported(capabilities: &Capabilities) -> bool {
1120        capabilities
1121            .supports_loaded_sources_request
1122            .unwrap_or_default()
1123    }
1124    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1125        dap::LoadedSourcesArguments {}
1126    }
1127
1128    fn response_from_dap(
1129        &self,
1130        message: <Self::DapRequest as dap::requests::Request>::Response,
1131    ) -> Result<Self::Response> {
1132        Ok(message.sources)
1133    }
1134}
1135
1136impl DapCommand for LoadedSourcesCommand {
1137    type ProtoRequest = proto::DapLoadedSourcesRequest;
1138    type ProtoResponse = proto::DapLoadedSourcesResponse;
1139
1140    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1141        SessionId::from_proto(request.client_id)
1142    }
1143
1144    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1145        Self {}
1146    }
1147
1148    fn to_proto(
1149        &self,
1150        debug_client_id: SessionId,
1151        upstream_project_id: u64,
1152    ) -> proto::DapLoadedSourcesRequest {
1153        proto::DapLoadedSourcesRequest {
1154            project_id: upstream_project_id,
1155            client_id: debug_client_id.to_proto(),
1156        }
1157    }
1158
1159    fn response_to_proto(
1160        debug_client_id: SessionId,
1161        message: Self::Response,
1162    ) -> Self::ProtoResponse {
1163        proto::DapLoadedSourcesResponse {
1164            sources: message
1165                .into_iter()
1166                .map(|source| source.to_proto())
1167                .collect(),
1168            client_id: debug_client_id.to_proto(),
1169        }
1170    }
1171
1172    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1173        Ok(message
1174            .sources
1175            .into_iter()
1176            .map(dap::Source::from_proto)
1177            .collect())
1178    }
1179}
1180
1181#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1182pub(crate) struct StackTraceCommand {
1183    pub thread_id: u64,
1184    pub start_frame: Option<u64>,
1185    pub levels: Option<u64>,
1186}
1187
1188impl LocalDapCommand for StackTraceCommand {
1189    type Response = Vec<dap::StackFrame>;
1190    type DapRequest = dap::requests::StackTrace;
1191    const CACHEABLE: bool = true;
1192
1193    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1194        dap::StackTraceArguments {
1195            thread_id: self.thread_id,
1196            start_frame: self.start_frame,
1197            levels: self.levels,
1198            format: None,
1199        }
1200    }
1201
1202    fn response_from_dap(
1203        &self,
1204        message: <Self::DapRequest as dap::requests::Request>::Response,
1205    ) -> Result<Self::Response> {
1206        Ok(message.stack_frames)
1207    }
1208}
1209
1210impl DapCommand for StackTraceCommand {
1211    type ProtoRequest = proto::DapStackTraceRequest;
1212    type ProtoResponse = proto::DapStackTraceResponse;
1213
1214    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1215        proto::DapStackTraceRequest {
1216            project_id: upstream_project_id,
1217            client_id: debug_client_id.to_proto(),
1218            thread_id: self.thread_id,
1219            start_frame: self.start_frame,
1220            stack_trace_levels: self.levels,
1221        }
1222    }
1223
1224    fn from_proto(request: &Self::ProtoRequest) -> Self {
1225        Self {
1226            thread_id: request.thread_id,
1227            start_frame: request.start_frame,
1228            levels: request.stack_trace_levels,
1229        }
1230    }
1231
1232    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1233        SessionId::from_proto(request.client_id)
1234    }
1235
1236    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1237        Ok(message
1238            .frames
1239            .into_iter()
1240            .map(dap::StackFrame::from_proto)
1241            .collect())
1242    }
1243
1244    fn response_to_proto(
1245        _debug_client_id: SessionId,
1246        message: Self::Response,
1247    ) -> Self::ProtoResponse {
1248        proto::DapStackTraceResponse {
1249            frames: message.to_proto(),
1250        }
1251    }
1252}
1253
1254#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1255pub(crate) struct ScopesCommand {
1256    pub stack_frame_id: u64,
1257}
1258
1259impl LocalDapCommand for ScopesCommand {
1260    type Response = Vec<dap::Scope>;
1261    type DapRequest = dap::requests::Scopes;
1262    const CACHEABLE: bool = true;
1263
1264    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1265        dap::ScopesArguments {
1266            frame_id: self.stack_frame_id,
1267        }
1268    }
1269
1270    fn response_from_dap(
1271        &self,
1272        message: <Self::DapRequest as dap::requests::Request>::Response,
1273    ) -> Result<Self::Response> {
1274        Ok(message.scopes)
1275    }
1276}
1277
1278impl DapCommand for ScopesCommand {
1279    type ProtoRequest = proto::DapScopesRequest;
1280    type ProtoResponse = proto::DapScopesResponse;
1281
1282    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1283        proto::DapScopesRequest {
1284            project_id: upstream_project_id,
1285            client_id: debug_client_id.to_proto(),
1286            stack_frame_id: self.stack_frame_id,
1287        }
1288    }
1289
1290    fn from_proto(request: &Self::ProtoRequest) -> Self {
1291        Self {
1292            stack_frame_id: request.stack_frame_id,
1293        }
1294    }
1295
1296    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1297        SessionId::from_proto(request.client_id)
1298    }
1299
1300    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1301        Ok(Vec::from_proto(message.scopes))
1302    }
1303
1304    fn response_to_proto(
1305        _debug_client_id: SessionId,
1306        message: Self::Response,
1307    ) -> Self::ProtoResponse {
1308        proto::DapScopesResponse {
1309            scopes: message.to_proto(),
1310        }
1311    }
1312}
1313
1314impl LocalDapCommand for super::session::CompletionsQuery {
1315    type Response = dap::CompletionsResponse;
1316    type DapRequest = dap::requests::Completions;
1317    const CACHEABLE: bool = true;
1318
1319    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1320        dap::CompletionsArguments {
1321            text: self.query.clone(),
1322            frame_id: self.frame_id,
1323            column: self.column,
1324            line: None,
1325        }
1326    }
1327
1328    fn response_from_dap(
1329        &self,
1330        message: <Self::DapRequest as dap::requests::Request>::Response,
1331    ) -> Result<Self::Response> {
1332        Ok(message)
1333    }
1334
1335    fn is_supported(capabilities: &Capabilities) -> bool {
1336        capabilities
1337            .supports_completions_request
1338            .unwrap_or_default()
1339    }
1340}
1341
1342impl DapCommand for super::session::CompletionsQuery {
1343    type ProtoRequest = proto::DapCompletionRequest;
1344    type ProtoResponse = proto::DapCompletionResponse;
1345
1346    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1347        proto::DapCompletionRequest {
1348            client_id: debug_client_id.to_proto(),
1349            project_id: upstream_project_id,
1350            frame_id: self.frame_id,
1351            query: self.query.clone(),
1352            column: self.column,
1353            line: self.line,
1354        }
1355    }
1356
1357    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1358        SessionId::from_proto(request.client_id)
1359    }
1360
1361    fn from_proto(request: &Self::ProtoRequest) -> Self {
1362        Self {
1363            query: request.query.clone(),
1364            frame_id: request.frame_id,
1365            column: request.column,
1366            line: request.line,
1367        }
1368    }
1369
1370    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1371        Ok(dap::CompletionsResponse {
1372            targets: Vec::from_proto(message.completions),
1373        })
1374    }
1375
1376    fn response_to_proto(
1377        _debug_client_id: SessionId,
1378        message: Self::Response,
1379    ) -> Self::ProtoResponse {
1380        proto::DapCompletionResponse {
1381            client_id: _debug_client_id.to_proto(),
1382            completions: message.targets.to_proto(),
1383        }
1384    }
1385}
1386
1387#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1388pub(crate) struct EvaluateCommand {
1389    pub expression: String,
1390    pub frame_id: Option<u64>,
1391    pub context: Option<dap::EvaluateArgumentsContext>,
1392    pub source: Option<dap::Source>,
1393}
1394
1395impl LocalDapCommand for EvaluateCommand {
1396    type Response = dap::EvaluateResponse;
1397    type DapRequest = dap::requests::Evaluate;
1398    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1399        dap::EvaluateArguments {
1400            expression: self.expression.clone(),
1401            frame_id: self.frame_id,
1402            context: self.context.clone(),
1403            source: self.source.clone(),
1404            line: None,
1405            column: None,
1406            format: None,
1407        }
1408    }
1409
1410    fn response_from_dap(
1411        &self,
1412        message: <Self::DapRequest as dap::requests::Request>::Response,
1413    ) -> Result<Self::Response> {
1414        Ok(message)
1415    }
1416}
1417impl DapCommand for EvaluateCommand {
1418    type ProtoRequest = proto::DapEvaluateRequest;
1419    type ProtoResponse = proto::DapEvaluateResponse;
1420
1421    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1422        proto::DapEvaluateRequest {
1423            client_id: debug_client_id.to_proto(),
1424            project_id: upstream_project_id,
1425            expression: self.expression.clone(),
1426            frame_id: self.frame_id,
1427            context: self
1428                .context
1429                .clone()
1430                .map(|context| context.to_proto().into()),
1431        }
1432    }
1433
1434    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1435        SessionId::from_proto(request.client_id)
1436    }
1437
1438    fn from_proto(request: &Self::ProtoRequest) -> Self {
1439        Self {
1440            expression: request.expression.clone(),
1441            frame_id: request.frame_id,
1442            context: Some(dap::EvaluateArgumentsContext::from_proto(request.context())),
1443            source: None,
1444        }
1445    }
1446
1447    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1448        Ok(dap::EvaluateResponse {
1449            result: message.result.clone(),
1450            type_: message.evaluate_type.clone(),
1451            presentation_hint: None,
1452            variables_reference: message.variable_reference,
1453            named_variables: message.named_variables,
1454            indexed_variables: message.indexed_variables,
1455            memory_reference: message.memory_reference.clone(),
1456            value_location_reference: None, //TODO
1457        })
1458    }
1459
1460    fn response_to_proto(
1461        _debug_client_id: SessionId,
1462        message: Self::Response,
1463    ) -> Self::ProtoResponse {
1464        proto::DapEvaluateResponse {
1465            result: message.result,
1466            evaluate_type: message.type_,
1467            variable_reference: message.variables_reference,
1468            named_variables: message.named_variables,
1469            indexed_variables: message.indexed_variables,
1470            memory_reference: message.memory_reference,
1471        }
1472    }
1473}
1474
1475#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1476pub(crate) struct ThreadsCommand;
1477
1478impl LocalDapCommand for ThreadsCommand {
1479    type Response = Vec<dap::Thread>;
1480    type DapRequest = dap::requests::Threads;
1481    const CACHEABLE: bool = true;
1482
1483    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1484        dap::ThreadsArgument {}
1485    }
1486
1487    fn response_from_dap(
1488        &self,
1489        message: <Self::DapRequest as dap::requests::Request>::Response,
1490    ) -> Result<Self::Response> {
1491        Ok(message.threads)
1492    }
1493}
1494
1495impl DapCommand for ThreadsCommand {
1496    type ProtoRequest = proto::DapThreadsRequest;
1497    type ProtoResponse = proto::DapThreadsResponse;
1498
1499    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1500        proto::DapThreadsRequest {
1501            project_id: upstream_project_id,
1502            client_id: debug_client_id.to_proto(),
1503        }
1504    }
1505
1506    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1507        Self {}
1508    }
1509
1510    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1511        SessionId::from_proto(request.client_id)
1512    }
1513
1514    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1515        Ok(Vec::from_proto(message.threads))
1516    }
1517
1518    fn response_to_proto(
1519        _debug_client_id: SessionId,
1520        message: Self::Response,
1521    ) -> Self::ProtoResponse {
1522        proto::DapThreadsResponse {
1523            threads: message.to_proto(),
1524        }
1525    }
1526}
1527
1528#[derive(Clone, Debug, Hash, PartialEq)]
1529pub(super) struct Initialize {
1530    pub(super) adapter_id: String,
1531}
1532
1533fn dap_client_capabilities(adapter_id: String) -> InitializeRequestArguments {
1534    InitializeRequestArguments {
1535        client_id: Some("zed".to_owned()),
1536        client_name: Some("Zed".to_owned()),
1537        adapter_id,
1538        locale: Some("en-US".to_owned()),
1539        path_format: Some(InitializeRequestArgumentsPathFormat::Path),
1540        supports_variable_type: Some(true),
1541        supports_variable_paging: Some(false),
1542        supports_run_in_terminal_request: Some(true),
1543        supports_memory_references: Some(true),
1544        supports_progress_reporting: Some(false),
1545        supports_invalidated_event: Some(false),
1546        lines_start_at1: Some(true),
1547        columns_start_at1: Some(true),
1548        supports_memory_event: Some(false),
1549        supports_args_can_be_interpreted_by_shell: Some(false),
1550        supports_start_debugging_request: Some(true),
1551        supports_ansistyling: Some(true),
1552    }
1553}
1554
1555impl LocalDapCommand for Initialize {
1556    type Response = Capabilities;
1557    type DapRequest = dap::requests::Initialize;
1558
1559    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1560        dap_client_capabilities(self.adapter_id.clone())
1561    }
1562
1563    fn response_from_dap(
1564        &self,
1565        message: <Self::DapRequest as dap::requests::Request>::Response,
1566    ) -> Result<Self::Response> {
1567        Ok(message)
1568    }
1569}
1570
1571#[derive(Clone, Debug, Hash, PartialEq)]
1572pub(super) struct ConfigurationDone {}
1573
1574impl LocalDapCommand for ConfigurationDone {
1575    type Response = ();
1576    type DapRequest = dap::requests::ConfigurationDone;
1577
1578    fn is_supported(capabilities: &Capabilities) -> bool {
1579        capabilities
1580            .supports_configuration_done_request
1581            .unwrap_or_default()
1582    }
1583
1584    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1585        dap::ConfigurationDoneArguments {}
1586    }
1587
1588    fn response_from_dap(
1589        &self,
1590        message: <Self::DapRequest as dap::requests::Request>::Response,
1591    ) -> Result<Self::Response> {
1592        Ok(message)
1593    }
1594}
1595
1596#[derive(Clone, Debug, Hash, PartialEq)]
1597pub(super) struct Launch {
1598    pub(super) raw: Value,
1599}
1600
1601impl LocalDapCommand for Launch {
1602    type Response = ();
1603    type DapRequest = dap::requests::Launch;
1604
1605    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1606        dap::LaunchRequestArguments {
1607            raw: self.raw.clone(),
1608        }
1609    }
1610
1611    fn response_from_dap(
1612        &self,
1613        message: <Self::DapRequest as dap::requests::Request>::Response,
1614    ) -> Result<Self::Response> {
1615        Ok(message)
1616    }
1617}
1618
1619#[derive(Clone, Debug, Hash, PartialEq)]
1620pub(super) struct Attach {
1621    pub(super) raw: Value,
1622}
1623
1624impl LocalDapCommand for Attach {
1625    type Response = ();
1626    type DapRequest = dap::requests::Attach;
1627
1628    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1629        dap::AttachRequestArguments {
1630            raw: self.raw.clone(),
1631        }
1632    }
1633
1634    fn response_from_dap(
1635        &self,
1636        message: <Self::DapRequest as dap::requests::Request>::Response,
1637    ) -> Result<Self::Response> {
1638        Ok(message)
1639    }
1640}
1641
1642#[derive(Clone, Debug, Hash, PartialEq)]
1643pub(super) struct SetBreakpoints {
1644    pub(super) source: dap::Source,
1645    pub(super) breakpoints: Vec<SourceBreakpoint>,
1646    pub(super) source_modified: Option<bool>,
1647}
1648
1649impl LocalDapCommand for SetBreakpoints {
1650    type Response = Vec<dap::Breakpoint>;
1651    type DapRequest = dap::requests::SetBreakpoints;
1652
1653    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1654        dap::SetBreakpointsArguments {
1655            lines: None,
1656            source_modified: self.source_modified,
1657            source: self.source.clone(),
1658            breakpoints: Some(self.breakpoints.clone()),
1659        }
1660    }
1661
1662    fn response_from_dap(
1663        &self,
1664        message: <Self::DapRequest as dap::requests::Request>::Response,
1665    ) -> Result<Self::Response> {
1666        Ok(message.breakpoints)
1667    }
1668}
1669#[derive(Clone, Debug, Hash, PartialEq)]
1670pub(super) enum SetExceptionBreakpoints {
1671    Plain {
1672        filters: Vec<String>,
1673    },
1674    WithOptions {
1675        filters: Vec<ExceptionFilterOptions>,
1676    },
1677}
1678
1679impl LocalDapCommand for SetExceptionBreakpoints {
1680    type Response = Vec<dap::Breakpoint>;
1681    type DapRequest = dap::requests::SetExceptionBreakpoints;
1682
1683    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1684        match self {
1685            SetExceptionBreakpoints::Plain { filters } => dap::SetExceptionBreakpointsArguments {
1686                filters: filters.clone(),
1687                exception_options: None,
1688                filter_options: None,
1689            },
1690            SetExceptionBreakpoints::WithOptions { filters } => {
1691                dap::SetExceptionBreakpointsArguments {
1692                    filters: vec![],
1693                    filter_options: Some(filters.clone()),
1694                    exception_options: None,
1695                }
1696            }
1697        }
1698    }
1699
1700    fn response_from_dap(
1701        &self,
1702        message: <Self::DapRequest as dap::requests::Request>::Response,
1703    ) -> Result<Self::Response> {
1704        Ok(message.breakpoints.unwrap_or_default())
1705    }
1706}
1707
1708#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1709pub(super) struct LocationsCommand {
1710    pub(super) reference: u64,
1711}
1712
1713impl LocalDapCommand for LocationsCommand {
1714    type Response = dap::LocationsResponse;
1715    type DapRequest = dap::requests::Locations;
1716    const CACHEABLE: bool = true;
1717
1718    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1719        dap::LocationsArguments {
1720            location_reference: self.reference,
1721        }
1722    }
1723
1724    fn response_from_dap(
1725        &self,
1726        message: <Self::DapRequest as dap::requests::Request>::Response,
1727    ) -> Result<Self::Response> {
1728        Ok(message)
1729    }
1730}
1731
1732impl DapCommand for LocationsCommand {
1733    type ProtoRequest = proto::DapLocationsRequest;
1734    type ProtoResponse = proto::DapLocationsResponse;
1735
1736    fn client_id_from_proto(message: &Self::ProtoRequest) -> SessionId {
1737        SessionId::from_proto(message.session_id)
1738    }
1739
1740    fn from_proto(message: &Self::ProtoRequest) -> Self {
1741        Self {
1742            reference: message.location_reference,
1743        }
1744    }
1745
1746    fn to_proto(&self, session_id: SessionId, project_id: u64) -> Self::ProtoRequest {
1747        proto::DapLocationsRequest {
1748            project_id,
1749            session_id: session_id.to_proto(),
1750            location_reference: self.reference,
1751        }
1752    }
1753
1754    fn response_to_proto(_: SessionId, response: Self::Response) -> Self::ProtoResponse {
1755        proto::DapLocationsResponse {
1756            source: Some(response.source.to_proto()),
1757            line: response.line,
1758            column: response.column,
1759            end_line: response.end_line,
1760            end_column: response.end_column,
1761        }
1762    }
1763
1764    fn response_from_proto(&self, response: Self::ProtoResponse) -> Result<Self::Response> {
1765        Ok(dap::LocationsResponse {
1766            source: response
1767                .source
1768                .map(<dap::Source as ProtoConversion>::from_proto)
1769                .context("Missing `source` field in Locations proto")?,
1770            line: response.line,
1771            column: response.column,
1772            end_line: response.end_line,
1773            end_column: response.end_column,
1774        })
1775    }
1776}