Setup C adapter with test binary

Julia created

Change summary

crates/copilot/src/copilot.rs   |  2 +-
crates/language/src/language.rs | 12 +++++++++---
crates/lsp/src/lsp.rs           |  4 ++--
crates/project/src/project.rs   | 32 +++++++++++++++++---------------
crates/zed/src/languages/c.rs   | 14 +++++++++++---
5 files changed, 40 insertions(+), 24 deletions(-)

Detailed changes

crates/copilot/src/copilot.rs 🔗

@@ -368,7 +368,7 @@ impl Copilot {
                 };
                 let binaries = LanguageServerBinaries {
                     binary: binary.clone(),
-                    installation_test_binary: binary,
+                    installation_test_binary: Some(binary),
                 };
                 let server = LanguageServer::new(
                     LanguageServerId(0),

crates/language/src/language.rs 🔗

@@ -141,8 +141,11 @@ impl CachedLspAdapter {
         self.adapter.cached_server_binary(container_dir).await
     }
 
-    async fn installation_test_binary(&self, container_dir: PathBuf) -> LanguageServerBinary {
-        self.adapter.installation_test_binary(container_dir)
+    async fn installation_test_binary(
+        &self,
+        container_dir: PathBuf,
+    ) -> Option<LanguageServerBinary> {
+        self.adapter.installation_test_binary(container_dir).await
     }
 
     pub fn code_action_kinds(&self) -> Option<Vec<CodeActionKind>> {
@@ -202,7 +205,10 @@ pub trait LspAdapter: 'static + Send + Sync {
 
     async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary>;
 
-    fn installation_test_binary(&self, _container_dir: PathBuf) -> LanguageServerBinary {
+    async fn installation_test_binary(
+        &self,
+        _container_dir: PathBuf,
+    ) -> Option<LanguageServerBinary> {
         unimplemented!();
     }
 

crates/lsp/src/lsp.rs 🔗

@@ -46,7 +46,7 @@ pub struct LanguageServerBinary {
 #[derive(Debug, Clone, Deserialize)]
 pub struct LanguageServerBinaries {
     pub binary: LanguageServerBinary,
-    pub installation_test_binary: LanguageServerBinary,
+    pub installation_test_binary: Option<LanguageServerBinary>,
 }
 
 pub struct LanguageServer {
@@ -162,7 +162,7 @@ impl LanguageServer {
             stdin,
             stout,
             Some(server),
-            Some(binaries.installation_test_binary),
+            binaries.installation_test_binary,
             root_path,
             code_action_kinds,
             cx,

crates/project/src/project.rs 🔗

@@ -3002,27 +3002,29 @@ impl Project {
             if !language_server.is_dead() {
                 return;
             }
-
             let server_id = language_server.server_id();
-            let test_binary = match language_server.test_installation_binary() {
-                Some(test_binary) => test_binary.clone(),
-                None => return,
-            };
+
+            // A lack of test binary counts as a failure
+            let process = language_server
+                .test_installation_binary()
+                .as_ref()
+                .and_then(|binary| {
+                    smol::process::Command::new(&binary.path)
+                        .current_dir(&binary.path)
+                        .args(&binary.arguments)
+                        .stdin(Stdio::piped())
+                        .stdout(Stdio::piped())
+                        .stderr(Stdio::inherit())
+                        .kill_on_drop(true)
+                        .spawn()
+                        .ok()
+                });
 
             const PROCESS_TIMEOUT: Duration = Duration::from_secs(5);
             let mut timeout = cx.background().timer(PROCESS_TIMEOUT).fuse();
 
             let mut errored = false;
-            let result = smol::process::Command::new(&test_binary.path)
-                .current_dir(&test_binary.path)
-                .args(test_binary.arguments)
-                .stdin(Stdio::piped())
-                .stdout(Stdio::piped())
-                .stderr(Stdio::inherit())
-                .kill_on_drop(true)
-                .spawn();
-
-            if let Ok(mut process) = result {
+            if let Some(mut process) = process {
                 futures::select! {
                     status = process.status().fuse() => match status {
                         Ok(status) => errored = !status.success(),

crates/zed/src/languages/c.rs 🔗

@@ -109,9 +109,17 @@ impl super::LspAdapter for CLspAdapter {
         .await
         .log_err()
     }
-    
-    fn installation_test_binary(&self, container_dir: PathBuf) -> LanguageServerBinary {
-        unimplemented!();
+
+    async fn installation_test_binary(
+        &self,
+        container_dir: PathBuf,
+    ) -> Option<LanguageServerBinary> {
+        self.cached_server_binary(container_dir)
+            .await
+            .map(|mut binary| {
+                binary.arguments = vec!["--help".into()];
+                binary
+            })
     }
 
     async fn label_for_completion(