From 14d9a4189f058d8736339b06ff2340101eaea5af Mon Sep 17 00:00:00 2001 From: Anthony Eid <56899983+Anthony-Eid@users.noreply.github.com> Date: Fri, 23 May 2025 17:19:24 +0300 Subject: [PATCH] debugger beta: Auto download Delve (Go's DAP) & fix grammar errors in docs (#31273) Release Notes: - debugger beta: Go's debug adapter will now automatically download if not found on user's PATH Co-authored-by: Remco Smits --- crates/dap_adapters/src/codelldb.rs | 3 -- crates/dap_adapters/src/go.rs | 76 +++++++++++++++++++++++++---- docs/src/debugger.md | 14 +++--- 3 files changed, 74 insertions(+), 19 deletions(-) diff --git a/crates/dap_adapters/src/codelldb.rs b/crates/dap_adapters/src/codelldb.rs index 8f86f43fca..a123f399da 100644 --- a/crates/dap_adapters/src/codelldb.rs +++ b/crates/dap_adapters/src/codelldb.rs @@ -339,9 +339,6 @@ impl DebugAdapter for CodeLldbDebugAdapter { }, { "required": ["targetCreateCommands"] - }, - { - "required": ["cargo"] } ] } diff --git a/crates/dap_adapters/src/go.rs b/crates/dap_adapters/src/go.rs index 699b9f8ee8..9140f983d1 100644 --- a/crates/dap_adapters/src/go.rs +++ b/crates/dap_adapters/src/go.rs @@ -1,4 +1,4 @@ -use anyhow::{Context as _, anyhow}; +use anyhow::{Context as _, anyhow, bail}; use dap::{ StartDebuggingRequestArguments, StartDebuggingRequestArgumentsRequest, adapters::DebugTaskDefinition, @@ -7,6 +7,7 @@ use dap::{ use gpui::{AsyncApp, SharedString}; use language::LanguageName; use std::{collections::HashMap, ffi::OsStr, path::PathBuf}; +use util; use crate::*; @@ -15,6 +16,7 @@ pub(crate) struct GoDebugAdapter; impl GoDebugAdapter { const ADAPTER_NAME: &'static str = "Delve"; + const DEFAULT_TIMEOUT_MS: u64 = 60000; } #[async_trait(?Send)] @@ -338,19 +340,75 @@ impl DebugAdapter for GoDebugAdapter { _user_installed_path: Option, _cx: &mut AsyncApp, ) -> Result { - let delve_path = delegate - .which(OsStr::new("dlv")) - .await - .and_then(|p| p.to_str().map(|p| p.to_string())) - .context("Dlv not found in path")?; + let adapter_path = paths::debug_adapters_dir().join(&Self::ADAPTER_NAME); + let dlv_path = adapter_path.join("dlv"); + + let delve_path = if let Some(path) = delegate.which(OsStr::new("dlv")).await { + path.to_string_lossy().to_string() + } else if delegate.fs().is_file(&dlv_path).await { + dlv_path.to_string_lossy().to_string() + } else { + let go = delegate + .which(OsStr::new("go")) + .await + .context("Go not found in path. Please install Go first, then Dlv will be installed automatically.")?; + + let adapter_path = paths::debug_adapters_dir().join(&Self::ADAPTER_NAME); + + let install_output = util::command::new_smol_command(&go) + .env("GO111MODULE", "on") + .env("GOBIN", &adapter_path) + .args(&["install", "github.com/go-delve/delve/cmd/dlv@latest"]) + .output() + .await?; + + if !install_output.status.success() { + bail!( + "failed to install dlv via `go install`. stdout: {:?}, stderr: {:?}\n Please try installing it manually using 'go install github.com/go-delve/delve/cmd/dlv@latest'", + String::from_utf8_lossy(&install_output.stdout), + String::from_utf8_lossy(&install_output.stderr) + ); + } + + adapter_path.join("dlv").to_string_lossy().to_string() + }; + + let mut tcp_connection = task_definition.tcp_connection.clone().unwrap_or_default(); + + if tcp_connection.timeout.is_none() + || tcp_connection.timeout.unwrap_or(0) < Self::DEFAULT_TIMEOUT_MS + { + tcp_connection.timeout = Some(Self::DEFAULT_TIMEOUT_MS); + } - let tcp_connection = task_definition.tcp_connection.clone().unwrap_or_default(); let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?; + let cwd = task_definition + .config + .get("cwd") + .and_then(|s| s.as_str()) + .map(PathBuf::from) + .unwrap_or_else(|| delegate.worktree_root_path().to_path_buf()); + + let arguments = if cfg!(windows) { + vec![ + "dap".into(), + "--listen".into(), + format!("{}:{}", host, port), + "--headless".into(), + ] + } else { + vec![ + "dap".into(), + "--listen".into(), + format!("{}:{}", host, port), + ] + }; + Ok(DebugAdapterBinary { command: delve_path, - arguments: vec!["dap".into(), "--listen".into(), format!("{host}:{port}")], - cwd: Some(delegate.worktree_root_path().to_path_buf()), + arguments, + cwd: Some(cwd), envs: HashMap::default(), connection: Some(adapters::TcpArguments { host, diff --git a/docs/src/debugger.md b/docs/src/debugger.md index f3e91ab843..ccfc6dd00f 100644 --- a/docs/src/debugger.md +++ b/docs/src/debugger.md @@ -28,15 +28,15 @@ These adapters enable Zed to provide a consistent debugging experience across mu ## Getting Started -For basic debugging you can set up a new configuration by opening up the `New Session Modal` either by the `debugger: start` (default: f4) or clicking the plus icon at the top right of the debug panel. Once the `New Session Modal` is open you can click custom on the bottom left to open a view that allows you to create a custom debug configuration. Once you have created a configuration you can save it to your workspace's `.zed/debug.json` by clicking on the save button on the bottom left. +For basic debugging you can set up a new configuration by opening the `New Session Modal` either via the `debugger: start` (default: f4) or clicking the plus icon at the top right of the debug panel. -For more advance use cases you can create debug configurations by directly editing the `.zed/debug.json` file in your project root directory. Once you fill out the adapter and label fields completions will show you the available options of the selected debug adapter. +For more advanced use cases you can create debug configurations by directly editing the `.zed/debug.json` file in your project root directory. You can then use the `New Session Modal` to select a configuration then start debugging. ### Configuration -While configuration fields are debug adapter dependent, most adapters support the follow fields. +While configuration fields are debug adapter dependent, most adapters support the following fields. ```json [ @@ -71,7 +71,7 @@ Zed currently supports these types of breakpoints - Conditional Breakpoints: Stop at the breakpoint when it's hit if the condition is met - Hit Breakpoints: Stop at the breakpoint when it's hit a certain number of times -Standard breakpoints can be toggled by left clicking on the editor gutter or using the Toggle Breakpoint action. Right clicking on a breakpoint, right clicking on a code runner symbol brings up the breakpoint context menu. That has options for toggling breakpoints and editing log breakpoints. +Standard breakpoints can be toggled by left clicking on the editor gutter or using the Toggle Breakpoint action. Right clicking on a breakpoint or on a code runner symbol brings up the breakpoint context menu. This has options for toggling breakpoints and editing log breakpoints. Other kinds of breakpoints can be toggled/edited by right clicking on the breakpoint icon in the gutter and selecting the desired option. @@ -216,10 +216,10 @@ Other kinds of breakpoints can be toggled/edited by right clicking on the breakp ## Theme -The Debugger supports the following theme options +The Debugger supports the following theme options: - /// Color used to accent some of the debuggers elements - /// Only accent breakpoint & breakpoint related symbols right now + /// Color used to accent some of the debugger's elements + /// Only accents breakpoint & breakpoint related symbols right now **debugger.accent**: Color used to accent breakpoint & breakpoint related symbols **editor.debugger_active_line.background**: Background color of active debug line