First pass of plugin side of things complete

Isaac Clayton created

Change summary

crates/zed/src/languages/language_plugin.rs | 50 ++++++++-------
plugins/Cargo.lock                          | 14 ++++
plugins/json_language/Cargo.toml            |  2 
plugins/json_language/src/lib.rs            | 72 ++++++++++++----------
4 files changed, 80 insertions(+), 58 deletions(-)

Detailed changes

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

@@ -1,11 +1,11 @@
 use super::installation::{npm_install_packages, npm_package_latest_version};
 use anyhow::{anyhow, Context, Result};
 use client::http::HttpClient;
+use futures::lock::Mutex;
 use futures::{future::BoxFuture, FutureExt, StreamExt};
 use gpui::executor::{self, Background};
 use isahc::http::version;
 use language::{LanguageServerName, LspAdapter};
-use parking_lot::{Mutex, RwLock};
 use plugin_runtime::{Wasi, WasiPlugin};
 use serde_json::json;
 use std::fs;
@@ -43,7 +43,7 @@ macro_rules! call_block {
     ($self:ident, $name:expr, $arg:expr) => {
         $self
             .executor
-            .block(async { $self.runtime.lock().call($name, $arg).await })
+            .block(async { $self.runtime.lock().await.call($name, $arg).await })
     };
 }
 
@@ -61,14 +61,13 @@ impl LspAdapter for PluginLspAdapter {
         &self,
         _: Arc<dyn HttpClient>,
     ) -> BoxFuture<'static, Result<Box<dyn 'static + Send + Any>>> {
-        let versions: Result<Option<String>> = call_block!(self, "fetch_latest_server_version", ());
+        // let versions: Result<Option<String>> = call_block!(self, "fetch_latest_server_version", ());
+        let runtime = self.runtime.clone();
         async move {
-            // let versions: Result<Option<String>> = self
-            //     .runtime
-            //     .lock()
-            //     .call::<_, Option<String>>("fetch_latest_server_version", ())
-            //     .await;
-
+            let mut runtime = runtime.lock().await;
+            let versions: Result<Option<String>> = runtime
+                .call::<_, Option<String>>("fetch_latest_server_version", ())
+                .await;
             versions
                 .map_err(|e| anyhow!("{}", e))?
                 .ok_or_else(|| anyhow!("Could not fetch latest server version"))
@@ -84,29 +83,34 @@ impl LspAdapter for PluginLspAdapter {
         container_dir: PathBuf,
     ) -> BoxFuture<'static, Result<PathBuf>> {
         let version = version.downcast::<String>().unwrap();
-        let mut runtime = self.runtime.lock();
-        let result = (|| {
+        let runtime = self.runtime.clone();
+
+        async move {
+            let mut runtime = runtime.lock().await;
             let handle = runtime.attach_path(&container_dir)?;
-            let result: Option<PathBuf> =
-                call_block!(self, "fetch_server_binary", (container_dir, version))?;
+            let result: Option<PathBuf> = runtime
+                .call("fetch_server_binary", (container_dir, version))
+                .await?;
             runtime.remove_resource(handle)?;
             result.ok_or_else(|| anyhow!("Could not load cached server binary"))
-        })();
-
-        async move { result }.boxed()
+        }
+        .boxed()
     }
 
     fn cached_server_binary(&self, container_dir: PathBuf) -> BoxFuture<'static, Option<PathBuf>> {
-        let mut runtime = self.runtime.lock();
-        let result: Option<PathBuf> = (|| {
+        let runtime = self.runtime.clone();
+
+        async move {
+            let mut runtime = runtime.lock().await;
             let handle = runtime.attach_path(&container_dir).ok()?;
-            let result: Option<PathBuf> =
-                call_block!(self, "cached_server_binary", container_dir).ok()?;
+            let result: Option<PathBuf> = runtime
+                .call("cached_server_binary", container_dir)
+                .await
+                .ok()?;
             runtime.remove_resource(handle).ok()?;
             result
-        })();
-
-        async move { result }.boxed()
+        }
+        .boxed()
     }
 
     fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}

plugins/Cargo.lock 🔗

@@ -75,6 +75,20 @@ name = "serde"
 version = "1.0.137"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.137"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
 
 [[package]]
 name = "serde_json"

plugins/json_language/Cargo.toml 🔗

@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 plugin = { path = "../../crates/plugin" }
-serde = "1.0"
+serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 
 [lib]

plugins/json_language/src/lib.rs 🔗

@@ -1,10 +1,13 @@
 use plugin::prelude::*;
+use serde::Deserialize;
 use serde_json::json;
 use std::fs;
 use std::path::PathBuf;
 
 // #[import]
-// fn command(string: String) -> Option<String>;
+fn command(string: &str) -> Option<String> {
+    todo!()
+}
 
 // TODO: some sort of macro to generate ABI bindings
 extern "C" {
@@ -48,45 +51,46 @@ pub fn fetch_latest_server_version() -> Option<String> {
         versions: Vec<String>,
     }
 
+    // TODO: command returns error code
     let output = command("npm info vscode-json-languageserver --json")?;
-    if !output.status.success() {
-        return None;
-    }
+    // if !output.is_ok() {
+    //     return None;
+    // }
 
-    let mut info: NpmInfo = serde_json::from_slice(&output.stdout)?;
+    let mut info: NpmInfo = serde_json::from_str(&output).ok()?;
     info.versions.pop()
 }
 
-// #[bind]
-// pub fn fetch_server_binary(container_dir: PathBuf, version: String) -> Option<PathBuf> {
-//     let version_dir = container_dir.join(version.as_str());
-//     fs::create_dir_all(&version_dir)
-//         .or_or_else(|| "failed to create version directory".to_string())?;
-//     let binary_path = version_dir.join(Self::BIN_PATH);
-
-//     if fs::metadata(&binary_path).await.is_err() {
-//         let output = command(format!(
-//             "npm install vscode-json-languageserver@{}",
-//             version
-//         ));
-//         if !output.status.success() {
-//             Err(anyhow!("failed to install vscode-json-languageserver"))?;
-//         }
-
-//         if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() {
-//             while let Some(entry) = entries.next().await {
-//                 if let Some(entry) = entry.log_err() {
-//                     let entry_path = entry.path();
-//                     if entry_path.as_path() != version_dir {
-//                         fs::remove_dir_all(&entry_path).await.log_err();
-//                     }
-//                 }
-//             }
-//         }
-//     }
+#[bind]
+pub fn fetch_server_binary(container_dir: PathBuf, version: String) -> Result<PathBuf, String> {
+    let version_dir = container_dir.join(version.as_str());
+    fs::create_dir_all(&version_dir)
+        .map_err(|_| "failed to create version directory".to_string())?;
+    let binary_path = version_dir.join(BIN_PATH);
+
+    if fs::metadata(&binary_path).is_err() {
+        let output = command(&format!(
+            "npm install vscode-json-languageserver@{}",
+            version
+        ));
+        if output.is_none() {
+            return Err("failed to install vscode-json-languageserver".to_string());
+        }
 
-//     Ok(binary_path)
-// }
+        if let Some(mut entries) = fs::read_dir(&container_dir).ok() {
+            while let Some(entry) = entries.next() {
+                if let Some(entry) = entry.ok() {
+                    let entry_path = entry.path();
+                    if entry_path.as_path() != version_dir {
+                        fs::remove_dir_all(&entry_path).ok();
+                    }
+                }
+            }
+        }
+    }
+
+    Ok(binary_path)
+}
 
 #[bind]
 pub fn cached_server_binary(container_dir: PathBuf) -> Option<PathBuf> {