1use std::{ffi::OsStr, path::PathBuf};
2
3use anyhow::Result;
4use async_trait::async_trait;
5use gpui::AsyncApp;
6use task::{DebugAdapterConfig, DebugRequestType, DebugTaskDefinition};
7
8use crate::*;
9
10#[derive(Default)]
11pub(crate) struct LldbDebugAdapter;
12
13impl LldbDebugAdapter {
14 const ADAPTER_NAME: &'static str = "LLDB";
15}
16
17#[async_trait(?Send)]
18impl DebugAdapter for LldbDebugAdapter {
19 fn name(&self) -> DebugAdapterName {
20 DebugAdapterName(Self::ADAPTER_NAME.into())
21 }
22
23 async fn get_binary(
24 &self,
25 delegate: &dyn DapDelegate,
26 _: &DebugAdapterConfig,
27 user_installed_path: Option<PathBuf>,
28 _: &mut AsyncApp,
29 ) -> Result<DebugAdapterBinary> {
30 let lldb_dap_path = if let Some(user_installed_path) = user_installed_path {
31 user_installed_path.to_string_lossy().into()
32 } else {
33 delegate
34 .which(OsStr::new("lldb-dap"))
35 .and_then(|p| p.to_str().map(|s| s.to_string()))
36 .ok_or(anyhow!("Could not find lldb-dap in path"))?
37 };
38
39 Ok(DebugAdapterBinary {
40 command: lldb_dap_path,
41 arguments: None,
42 envs: None,
43 cwd: None,
44 connection: None,
45 })
46 }
47
48 async fn install_binary(
49 &self,
50 _version: AdapterVersion,
51 _delegate: &dyn DapDelegate,
52 ) -> Result<()> {
53 unimplemented!("LLDB debug adapter cannot be installed by Zed (yet)")
54 }
55
56 async fn fetch_latest_adapter_version(&self, _: &dyn DapDelegate) -> Result<AdapterVersion> {
57 unimplemented!("Fetch latest adapter version not implemented for lldb (yet)")
58 }
59
60 async fn get_installed_binary(
61 &self,
62 _: &dyn DapDelegate,
63 _: &DebugAdapterConfig,
64 _: Option<PathBuf>,
65 _: &mut AsyncApp,
66 ) -> Result<DebugAdapterBinary> {
67 unimplemented!("LLDB debug adapter cannot be installed by Zed (yet)")
68 }
69
70 fn request_args(&self, config: &DebugTaskDefinition) -> Value {
71 let mut args = json!({
72 "request": match config.request {
73 DebugRequestType::Launch(_) => "launch",
74 DebugRequestType::Attach(_) => "attach",
75 },
76 });
77 let map = args.as_object_mut().unwrap();
78 match &config.request {
79 DebugRequestType::Attach(attach) => {
80 map.insert("pid".into(), attach.process_id.into());
81 }
82 DebugRequestType::Launch(launch) => {
83 map.insert("program".into(), launch.program.clone().into());
84
85 if !launch.args.is_empty() {
86 map.insert("args".into(), launch.args.clone().into());
87 }
88
89 if let Some(stop_on_entry) = config.stop_on_entry {
90 map.insert("stopOnEntry".into(), stop_on_entry.into());
91 }
92 if let Some(cwd) = launch.cwd.as_ref() {
93 map.insert("cwd".into(), cwd.to_string_lossy().into_owned().into());
94 }
95 }
96 }
97 args
98 }
99}