1use adapters::latest_github_release;
2use dap::adapters::TcpArguments;
3use gpui::AsyncApp;
4use std::path::PathBuf;
5use task::DebugTaskDefinition;
6
7use crate::*;
8
9#[derive(Default)]
10pub(crate) struct PhpDebugAdapter;
11
12impl PhpDebugAdapter {
13 const ADAPTER_NAME: &'static str = "PHP";
14 const ADAPTER_PACKAGE_NAME: &'static str = "vscode-php-debug";
15 const ADAPTER_PATH: &'static str = "extension/out/phpDebug.js";
16}
17
18#[async_trait(?Send)]
19impl DebugAdapter for PhpDebugAdapter {
20 fn name(&self) -> DebugAdapterName {
21 DebugAdapterName(Self::ADAPTER_NAME.into())
22 }
23
24 async fn fetch_latest_adapter_version(
25 &self,
26 delegate: &dyn DapDelegate,
27 ) -> Result<AdapterVersion> {
28 let release = latest_github_release(
29 &format!("{}/{}", "xdebug", Self::ADAPTER_PACKAGE_NAME),
30 true,
31 false,
32 delegate.http_client(),
33 )
34 .await?;
35
36 let asset_name = format!("php-debug-{}.vsix", release.tag_name.replace("v", ""));
37
38 Ok(AdapterVersion {
39 tag_name: release.tag_name,
40 url: release
41 .assets
42 .iter()
43 .find(|asset| asset.name == asset_name)
44 .ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?
45 .browser_download_url
46 .clone(),
47 })
48 }
49
50 async fn get_installed_binary(
51 &self,
52 delegate: &dyn DapDelegate,
53 config: &DebugAdapterConfig,
54 user_installed_path: Option<PathBuf>,
55 _: &mut AsyncApp,
56 ) -> Result<DebugAdapterBinary> {
57 let adapter_path = if let Some(user_installed_path) = user_installed_path {
58 user_installed_path
59 } else {
60 let adapter_path = paths::debug_adapters_dir().join(self.name().as_ref());
61
62 let file_name_prefix = format!("{}_", self.name());
63
64 util::fs::find_file_name_in_dir(adapter_path.as_path(), |file_name| {
65 file_name.starts_with(&file_name_prefix)
66 })
67 .await
68 .ok_or_else(|| anyhow!("Couldn't find PHP dap directory"))?
69 };
70
71 let tcp_connection = config.tcp_connection.clone().unwrap_or_default();
72 let (host, port, timeout) = crate::configure_tcp_connection(tcp_connection).await?;
73
74 Ok(DebugAdapterBinary {
75 command: delegate
76 .node_runtime()
77 .binary_path()
78 .await?
79 .to_string_lossy()
80 .into_owned(),
81 arguments: Some(vec![
82 adapter_path.join(Self::ADAPTER_PATH).into(),
83 format!("--server={}", port).into(),
84 ]),
85 connection: Some(TcpArguments {
86 port,
87 host,
88 timeout,
89 }),
90 cwd: None,
91 envs: None,
92 })
93 }
94
95 async fn install_binary(
96 &self,
97 version: AdapterVersion,
98 delegate: &dyn DapDelegate,
99 ) -> Result<()> {
100 adapters::download_adapter_from_github(
101 self.name(),
102 version,
103 adapters::DownloadedFileType::Vsix,
104 delegate,
105 )
106 .await?;
107
108 Ok(())
109 }
110
111 fn request_args(&self, config: &DebugTaskDefinition) -> Value {
112 match &config.request {
113 dap::DebugRequestType::Attach(_) => {
114 // php adapter does not support attaching
115 json!({})
116 }
117 dap::DebugRequestType::Launch(launch_config) => {
118 json!({
119 "program": launch_config.program,
120 "cwd": launch_config.cwd,
121 "args": launch_config.args,
122 "stopOnEntry": config.stop_on_entry.unwrap_or_default(),
123 })
124 }
125 }
126 }
127}