1use std::{path::PathBuf, sync::Arc};
2
3use anyhow::Result;
4use async_trait::async_trait;
5use dap::adapters::{
6 DapDelegate, DebugAdapter, DebugAdapterBinary, DebugAdapterName, DebugTaskDefinition,
7};
8use extension::{Extension, WorktreeDelegate};
9use gpui::AsyncApp;
10use task::{DebugScenario, ZedDebugConfig};
11
12pub(crate) struct ExtensionDapAdapter {
13 extension: Arc<dyn Extension>,
14 debug_adapter_name: Arc<str>,
15}
16
17impl ExtensionDapAdapter {
18 pub(crate) fn new(
19 extension: Arc<dyn extension::Extension>,
20 debug_adapter_name: Arc<str>,
21 ) -> Self {
22 Self {
23 extension,
24 debug_adapter_name,
25 }
26 }
27}
28
29/// An adapter that allows an [`dap::adapters::DapDelegate`] to be used as a [`WorktreeDelegate`].
30struct WorktreeDelegateAdapter(pub Arc<dyn DapDelegate>);
31
32#[async_trait]
33impl WorktreeDelegate for WorktreeDelegateAdapter {
34 fn id(&self) -> u64 {
35 self.0.worktree_id().to_proto()
36 }
37
38 fn root_path(&self) -> String {
39 self.0.worktree_root_path().to_string_lossy().to_string()
40 }
41
42 async fn read_text_file(&self, path: PathBuf) -> Result<String> {
43 self.0.read_text_file(path).await
44 }
45
46 async fn which(&self, binary_name: String) -> Option<String> {
47 self.0
48 .which(binary_name.as_ref())
49 .await
50 .map(|path| path.to_string_lossy().to_string())
51 }
52
53 async fn shell_env(&self) -> Vec<(String, String)> {
54 self.0.shell_env().await.into_iter().collect()
55 }
56}
57
58#[async_trait(?Send)]
59impl DebugAdapter for ExtensionDapAdapter {
60 fn name(&self) -> DebugAdapterName {
61 self.debug_adapter_name.as_ref().into()
62 }
63
64 async fn dap_schema(&self) -> serde_json::Value {
65 self.extension.get_dap_schema().await.unwrap_or_default()
66 }
67
68 async fn get_binary(
69 &self,
70 delegate: &Arc<dyn DapDelegate>,
71 config: &DebugTaskDefinition,
72 user_installed_path: Option<PathBuf>,
73 _cx: &mut AsyncApp,
74 ) -> Result<DebugAdapterBinary> {
75 self.extension
76 .get_dap_binary(
77 self.debug_adapter_name.clone(),
78 config.clone(),
79 user_installed_path,
80 Arc::new(WorktreeDelegateAdapter(delegate.clone())),
81 )
82 .await
83 }
84
85 fn config_from_zed_format(&self, _zed_scenario: ZedDebugConfig) -> Result<DebugScenario> {
86 Err(anyhow::anyhow!("DAP extensions are not implemented yet"))
87 }
88}