php.rs

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