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