From 83cc4524659cd352d65ad730f360a9d9e428c2bd Mon Sep 17 00:00:00 2001 From: Remco Smits Date: Sun, 1 Sep 2024 11:44:32 +0200 Subject: [PATCH] Make stepping granularity configurable (#33) This commit also changes the default granularity to line, before this was statement but most editors have line as the default. --- assets/settings/default.json | 2 +- crates/dap/src/client.rs | 62 ++++--------------- crates/dap/src/debugger_settings.rs | 28 +++++++++ crates/debugger_ui/src/debugger_panel_item.rs | 11 +++- 4 files changed, 50 insertions(+), 53 deletions(-) diff --git a/assets/settings/default.json b/assets/settings/default.json index 399cdd0043..77da4180af 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -1031,7 +1031,7 @@ "ssh_connections": null, "debugger": { - // Save breakpoints across different Zed sessions + "stepping_granularity": "line", "save_breakpoints": true, "button": true }, diff --git a/crates/dap/src/client.rs b/crates/dap/src/client.rs index b98fd08775..3b7864979b 100644 --- a/crates/dap/src/client.rs +++ b/crates/dap/src/client.rs @@ -476,16 +476,12 @@ impl DebugAdapterClient { self.request::(ContinueArguments { thread_id, - single_thread: if supports_single_thread_execution_requests { - Some(true) - } else { - None - }, + single_thread: supports_single_thread_execution_requests.then(|| true), }) .await } - pub async fn step_over(&self, thread_id: u64) -> Result<()> { + pub async fn step_over(&self, thread_id: u64, granularity: SteppingGranularity) -> Result<()> { let capabilities = self.capabilities(); let supports_single_thread_execution_requests = capabilities @@ -497,21 +493,13 @@ impl DebugAdapterClient { self.request::(NextArguments { thread_id, - granularity: if supports_stepping_granularity { - Some(SteppingGranularity::Statement) - } else { - None - }, - single_thread: if supports_single_thread_execution_requests { - Some(true) - } else { - None - }, + granularity: supports_stepping_granularity.then(|| granularity), + single_thread: supports_single_thread_execution_requests.then(|| true), }) .await } - pub async fn step_in(&self, thread_id: u64) -> Result<()> { + pub async fn step_in(&self, thread_id: u64, granularity: SteppingGranularity) -> Result<()> { let capabilities = self.capabilities(); let supports_single_thread_execution_requests = capabilities @@ -524,21 +512,13 @@ impl DebugAdapterClient { self.request::(StepInArguments { thread_id, target_id: None, - granularity: if supports_stepping_granularity { - Some(SteppingGranularity::Statement) - } else { - None - }, - single_thread: if supports_single_thread_execution_requests { - Some(true) - } else { - None - }, + granularity: supports_stepping_granularity.then(|| granularity), + single_thread: supports_single_thread_execution_requests.then(|| true), }) .await } - pub async fn step_out(&self, thread_id: u64) -> Result<()> { + pub async fn step_out(&self, thread_id: u64, granularity: SteppingGranularity) -> Result<()> { let capabilities = self.capabilities(); let supports_single_thread_execution_requests = capabilities @@ -550,21 +530,13 @@ impl DebugAdapterClient { self.request::(StepOutArguments { thread_id, - granularity: if supports_stepping_granularity { - Some(SteppingGranularity::Statement) - } else { - None - }, - single_thread: if supports_single_thread_execution_requests { - Some(true) - } else { - None - }, + granularity: supports_stepping_granularity.then(|| granularity), + single_thread: supports_single_thread_execution_requests.then(|| true), }) .await } - pub async fn step_back(&self, thread_id: u64) -> Result<()> { + pub async fn step_back(&self, thread_id: u64, granularity: SteppingGranularity) -> Result<()> { let capabilities = self.capabilities(); let supports_single_thread_execution_requests = capabilities @@ -576,16 +548,8 @@ impl DebugAdapterClient { self.request::(StepBackArguments { thread_id, - granularity: if supports_stepping_granularity { - Some(SteppingGranularity::Statement) - } else { - None - }, - single_thread: if supports_single_thread_execution_requests { - Some(true) - } else { - None - }, + granularity: supports_stepping_granularity.then(|| granularity), + single_thread: supports_single_thread_execution_requests.then(|| true), }) .await } diff --git a/crates/dap/src/debugger_settings.rs b/crates/dap/src/debugger_settings.rs index b75c9dbc08..d8ac68a3b1 100644 --- a/crates/dap/src/debugger_settings.rs +++ b/crates/dap/src/debugger_settings.rs @@ -6,6 +6,10 @@ use settings::{Settings, SettingsSources}; #[derive(Serialize, Deserialize, JsonSchema, Clone, Copy)] #[serde(default)] pub struct DebuggerSettings { + /// Determines the stepping granularity. + /// + /// Default: line + pub stepping_granularity: SteppingGranularity, /// Whether the breakpoints should be reused across Zed sessions. /// /// Default: true @@ -16,11 +20,35 @@ pub struct DebuggerSettings { pub button: bool, } +#[derive(Serialize, Deserialize, JsonSchema, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum SteppingGranularity { + /// The step should allow the program to run until the current statement has finished executing. + /// The meaning of a statement is determined by the adapter and it may be considered equivalent to a line. + /// For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'. + Statement, + /// The step should allow the program to run until the current source line has executed. + Line, + /// The step should allow one instruction to execute (e.g. one x86 instruction). + Instruction, +} + impl Default for DebuggerSettings { fn default() -> Self { Self { button: true, save_breakpoints: true, + stepping_granularity: SteppingGranularity::Line, + } + } +} + +impl DebuggerSettings { + pub fn stepping_granularity(&self) -> dap_types::SteppingGranularity { + match &self.stepping_granularity { + SteppingGranularity::Statement => dap_types::SteppingGranularity::Statement, + SteppingGranularity::Line => dap_types::SteppingGranularity::Line, + SteppingGranularity::Instruction => dap_types::SteppingGranularity::Instruction, } } } diff --git a/crates/debugger_ui/src/debugger_panel_item.rs b/crates/debugger_ui/src/debugger_panel_item.rs index f26a45fa70..3f0bd73b37 100644 --- a/crates/debugger_ui/src/debugger_panel_item.rs +++ b/crates/debugger_ui/src/debugger_panel_item.rs @@ -4,6 +4,7 @@ use crate::variable_list::VariableList; use anyhow::Result; use dap::client::{DebugAdapterClient, DebugAdapterClientId, ThreadState, ThreadStatus}; +use dap::debugger_settings::DebuggerSettings; use dap::{ OutputEvent, OutputEventCategory, Scope, StackFrame, StoppedEvent, ThreadEvent, Variable, }; @@ -13,6 +14,7 @@ use gpui::{ FocusableView, ListState, Subscription, View, WeakView, }; use serde::Deserialize; +use settings::Settings; use std::sync::Arc; use ui::WindowContext; use ui::{prelude::*, Tooltip}; @@ -441,9 +443,10 @@ impl DebugPanelItem { let client = self.client.clone(); let thread_id = self.thread_id; let previous_status = self.current_thread_state().status; + let granularity = DebuggerSettings::get_global(cx).stepping_granularity(); cx.spawn(|this, cx| async move { - client.step_over(thread_id).await?; + client.step_over(thread_id, granularity).await?; Self::update_thread_state(this, previous_status, None, cx) }) @@ -454,9 +457,10 @@ impl DebugPanelItem { let client = self.client.clone(); let thread_id = self.thread_id; let previous_status = self.current_thread_state().status; + let granularity = DebuggerSettings::get_global(cx).stepping_granularity(); cx.spawn(|this, cx| async move { - client.step_in(thread_id).await?; + client.step_in(thread_id, granularity).await?; Self::update_thread_state(this, previous_status, None, cx) }) @@ -467,9 +471,10 @@ impl DebugPanelItem { let client = self.client.clone(); let thread_id = self.thread_id; let previous_status = self.current_thread_state().status; + let granularity = DebuggerSettings::get_global(cx).stepping_granularity(); cx.spawn(|this, cx| async move { - client.step_out(thread_id).await?; + client.step_out(thread_id, granularity).await?; Self::update_thread_state(this, previous_status, None, cx) })