debugger: A support for data breakpoint's on variables (#34391)
Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ... --------- Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com> Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
co-authored by
Piotr Osiewicz
Mikayla Maki
Mikayla Maki
parent
8b6b039b63
commit
fd5650d4ed
@@ -11,6 +11,7 @@ use dap::{
|
||||
proto_conversions::ProtoConversion,
|
||||
requests::{Continue, Next},
|
||||
};
|
||||
|
||||
use rpc::proto;
|
||||
use serde_json::Value;
|
||||
use util::ResultExt;
|
||||
@@ -813,7 +814,7 @@ impl DapCommand for RestartCommand {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub struct VariablesCommand {
|
||||
pub variables_reference: u64,
|
||||
pub filter: Option<VariablesArgumentsFilter>,
|
||||
@@ -1667,6 +1668,130 @@ impl LocalDapCommand for SetBreakpoints {
|
||||
Ok(message.breakpoints)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum DataBreakpointContext {
|
||||
Variable {
|
||||
variables_reference: u64,
|
||||
name: String,
|
||||
bytes: Option<u64>,
|
||||
},
|
||||
Expression {
|
||||
expression: String,
|
||||
frame_id: Option<u64>,
|
||||
},
|
||||
Address {
|
||||
address: String,
|
||||
bytes: Option<u64>,
|
||||
},
|
||||
}
|
||||
|
||||
impl DataBreakpointContext {
|
||||
pub fn human_readable_label(&self) -> String {
|
||||
match self {
|
||||
DataBreakpointContext::Variable { name, .. } => format!("Variable: {}", name),
|
||||
DataBreakpointContext::Expression { expression, .. } => {
|
||||
format!("Expression: {}", expression)
|
||||
}
|
||||
DataBreakpointContext::Address { address, bytes } => {
|
||||
let mut label = format!("Address: {}", address);
|
||||
if let Some(bytes) = bytes {
|
||||
label.push_str(&format!(
|
||||
" ({} byte{})",
|
||||
bytes,
|
||||
if *bytes == 1 { "" } else { "s" }
|
||||
));
|
||||
}
|
||||
label
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub(crate) struct DataBreakpointInfoCommand {
|
||||
pub context: Arc<DataBreakpointContext>,
|
||||
pub mode: Option<String>,
|
||||
}
|
||||
|
||||
impl LocalDapCommand for DataBreakpointInfoCommand {
|
||||
type Response = dap::DataBreakpointInfoResponse;
|
||||
type DapRequest = dap::requests::DataBreakpointInfo;
|
||||
const CACHEABLE: bool = true;
|
||||
|
||||
// todo(debugger): We should expand this trait in the future to take a &self
|
||||
// Depending on this command is_supported could be differentb
|
||||
fn is_supported(capabilities: &Capabilities) -> bool {
|
||||
capabilities.supports_data_breakpoints.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
|
||||
let (variables_reference, name, frame_id, as_address, bytes) = match &*self.context {
|
||||
DataBreakpointContext::Variable {
|
||||
variables_reference,
|
||||
name,
|
||||
bytes,
|
||||
} => (
|
||||
Some(*variables_reference),
|
||||
name.clone(),
|
||||
None,
|
||||
Some(false),
|
||||
*bytes,
|
||||
),
|
||||
DataBreakpointContext::Expression {
|
||||
expression,
|
||||
frame_id,
|
||||
} => (None, expression.clone(), *frame_id, Some(false), None),
|
||||
DataBreakpointContext::Address { address, bytes } => {
|
||||
(None, address.clone(), None, Some(true), *bytes)
|
||||
}
|
||||
};
|
||||
|
||||
dap::DataBreakpointInfoArguments {
|
||||
variables_reference,
|
||||
name,
|
||||
frame_id,
|
||||
bytes,
|
||||
as_address,
|
||||
mode: self.mode.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn response_from_dap(
|
||||
&self,
|
||||
message: <Self::DapRequest as dap::requests::Request>::Response,
|
||||
) -> Result<Self::Response> {
|
||||
Ok(message)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub(crate) struct SetDataBreakpointsCommand {
|
||||
pub breakpoints: Vec<dap::DataBreakpoint>,
|
||||
}
|
||||
|
||||
impl LocalDapCommand for SetDataBreakpointsCommand {
|
||||
type Response = Vec<dap::Breakpoint>;
|
||||
type DapRequest = dap::requests::SetDataBreakpoints;
|
||||
|
||||
fn is_supported(capabilities: &Capabilities) -> bool {
|
||||
capabilities.supports_data_breakpoints.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
|
||||
dap::SetDataBreakpointsArguments {
|
||||
breakpoints: self.breakpoints.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn response_from_dap(
|
||||
&self,
|
||||
message: <Self::DapRequest as dap::requests::Request>::Response,
|
||||
) -> Result<Self::Response> {
|
||||
Ok(message.breakpoints)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq)]
|
||||
pub(super) enum SetExceptionBreakpoints {
|
||||
Plain {
|
||||
@@ -1776,7 +1901,7 @@ impl DapCommand for LocationsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub(crate) struct ReadMemory {
|
||||
pub(crate) memory_reference: String,
|
||||
pub(crate) offset: Option<u64>,
|
||||
@@ -1829,25 +1954,6 @@ impl LocalDapCommand for ReadMemory {
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalDapCommand for dap::DataBreakpointInfoArguments {
|
||||
type Response = dap::DataBreakpointInfoResponse;
|
||||
type DapRequest = dap::requests::DataBreakpointInfo;
|
||||
const CACHEABLE: bool = true;
|
||||
fn is_supported(capabilities: &Capabilities) -> bool {
|
||||
capabilities.supports_data_breakpoints.unwrap_or_default()
|
||||
}
|
||||
fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
fn response_from_dap(
|
||||
&self,
|
||||
message: <Self::DapRequest as dap::requests::Request>::Response,
|
||||
) -> Result<Self::Response> {
|
||||
Ok(message)
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalDapCommand for dap::WriteMemoryArguments {
|
||||
type Response = dap::WriteMemoryResponse;
|
||||
type DapRequest = dap::requests::WriteMemory;
|
||||
|
||||
Reference in New Issue
Block a user