1use anyhow::Context as _;
2use dap::{StartDebuggingRequestArguments, adapters::DebugTaskDefinition};
3use gpui::{AsyncApp, SharedString};
4use language::LanguageName;
5use std::{collections::HashMap, ffi::OsStr, path::PathBuf};
6
7use crate::*;
8
9#[derive(Default, Debug)]
10pub(crate) struct GoDebugAdapter;
11
12impl GoDebugAdapter {
13 const ADAPTER_NAME: &'static str = "Delve";
14 fn request_args(&self, config: &DebugTaskDefinition) -> StartDebuggingRequestArguments {
15 let mut args = match &config.request {
16 dap::DebugRequest::Attach(attach_config) => {
17 json!({
18 "processId": attach_config.process_id,
19 })
20 }
21 dap::DebugRequest::Launch(launch_config) => json!({
22 "program": launch_config.program,
23 "cwd": launch_config.cwd,
24 "args": launch_config.args,
25 "env": launch_config.env_json()
26 }),
27 };
28
29 let map = args.as_object_mut().unwrap();
30
31 if let Some(stop_on_entry) = config.stop_on_entry {
32 map.insert("stopOnEntry".into(), stop_on_entry.into());
33 }
34
35 StartDebuggingRequestArguments {
36 configuration: args,
37 request: config.request.to_dap(),
38 }
39 }
40}
41
42#[async_trait(?Send)]
43impl DebugAdapter for GoDebugAdapter {
44 fn name(&self) -> DebugAdapterName {
45 DebugAdapterName(Self::ADAPTER_NAME.into())
46 }
47
48 fn adapter_language_name(&self) -> Option<LanguageName> {
49 Some(SharedString::new_static("Go").into())
50 }
51
52 async fn get_binary(
53 &self,
54 delegate: &Arc<dyn DapDelegate>,
55 config: &DebugTaskDefinition,
56 _user_installed_path: Option<PathBuf>,
57 _cx: &mut AsyncApp,
58 ) -> Result<DebugAdapterBinary> {
59 let delve_path = delegate
60 .which(OsStr::new("dlv"))
61 .await
62 .and_then(|p| p.to_str().map(|p| p.to_string()))
63 .context("Dlv not found in path")?;
64
65 let tcp_connection = config.tcp_connection.clone().unwrap_or_default();
66 let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
67
68 Ok(DebugAdapterBinary {
69 command: delve_path,
70 arguments: vec!["dap".into(), "--listen".into(), format!("{host}:{port}")],
71 cwd: None,
72 envs: HashMap::default(),
73 connection: Some(adapters::TcpArguments {
74 host,
75 port,
76 timeout,
77 }),
78 request_args: self.request_args(config),
79 })
80 }
81}