From dddeb66e2a4a086466367a5ebd5019cc704652fc Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 13 Jul 2022 13:56:39 -0700 Subject: [PATCH] Temporarily remove JSON plugin + restore native JSON LspAdapter --- crates/zed/src/languages.rs | 9 +- crates/zed/src/languages/json.rs | 106 ++++++++++++++++++++ crates/zed/src/languages/language_plugin.rs | 27 +---- 3 files changed, 111 insertions(+), 31 deletions(-) create mode 100644 crates/zed/src/languages/json.rs diff --git a/crates/zed/src/languages.rs b/crates/zed/src/languages.rs index e1cc1d61c2..82f5701f7f 100644 --- a/crates/zed/src/languages.rs +++ b/crates/zed/src/languages.rs @@ -2,11 +2,11 @@ use gpui::executor::Background; pub use language::*; use rust_embed::RustEmbed; use std::{borrow::Cow, str, sync::Arc}; -use util::ResultExt; mod c; mod go; mod installation; +mod json; mod language_plugin; mod python; mod rust; @@ -17,7 +17,7 @@ mod typescript; #[exclude = "*.rs"] struct LanguageDir; -pub async fn init(languages: Arc, executor: Arc) { +pub async fn init(languages: Arc, _executor: Arc) { for (name, grammar, lsp_adapter) in [ ( "c", @@ -37,10 +37,7 @@ pub async fn init(languages: Arc, executor: Arc) { ( "json", tree_sitter_json::language(), - match language_plugin::new_json(executor).await.log_err() { - Some(lang) => Some(CachedLspAdapter::new(lang).await), - None => None, - }, + Some(CachedLspAdapter::new(json::JsonLspAdapter).await), ), ( "markdown", diff --git a/crates/zed/src/languages/json.rs b/crates/zed/src/languages/json.rs new file mode 100644 index 0000000000..7b6569d336 --- /dev/null +++ b/crates/zed/src/languages/json.rs @@ -0,0 +1,106 @@ +use super::installation::{npm_install_packages, npm_package_latest_version}; +use anyhow::{anyhow, Context, Result}; +use async_trait::async_trait; +use client::http::HttpClient; +use collections::HashMap; +use futures::StreamExt; +use language::{LanguageServerName, LspAdapter}; +use serde_json::json; +use smol::fs; +use std::{any::Any, path::PathBuf, sync::Arc}; +use util::ResultExt; + +pub struct JsonLspAdapter; + +impl JsonLspAdapter { + const BIN_PATH: &'static str = + "node_modules/vscode-json-languageserver/bin/vscode-json-languageserver"; +} + +#[async_trait] +impl LspAdapter for JsonLspAdapter { + async fn name(&self) -> LanguageServerName { + LanguageServerName("vscode-json-languageserver".into()) + } + + async fn server_args(&self) -> Vec { + vec!["--stdio".into()] + } + + async fn fetch_latest_server_version( + &self, + _: Arc, + ) -> Result> { + Ok(Box::new(npm_package_latest_version("vscode-json-languageserver").await?) as Box<_>) + } + + async fn fetch_server_binary( + &self, + version: Box, + _: Arc, + container_dir: PathBuf, + ) -> Result { + let version = version.downcast::().unwrap(); + let version_dir = container_dir.join(version.as_str()); + fs::create_dir_all(&version_dir) + .await + .context("failed to create version directory")?; + let binary_path = version_dir.join(Self::BIN_PATH); + + if fs::metadata(&binary_path).await.is_err() { + npm_install_packages( + [("vscode-json-languageserver", version.as_str())], + &version_dir, + ) + .await?; + + 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(); + } + } + } + } + } + + Ok(binary_path) + } + + async fn cached_server_binary(&self, container_dir: PathBuf) -> Option { + (|| async move { + let mut last_version_dir = None; + let mut entries = fs::read_dir(&container_dir).await?; + while let Some(entry) = entries.next().await { + let entry = entry?; + if entry.file_type().await?.is_dir() { + last_version_dir = Some(entry.path()); + } + } + let last_version_dir = last_version_dir.ok_or_else(|| anyhow!("no cached binary"))?; + let bin_path = last_version_dir.join(Self::BIN_PATH); + if bin_path.exists() { + Ok(bin_path) + } else { + Err(anyhow!( + "missing executable in directory {:?}", + last_version_dir + )) + } + })() + .await + .log_err() + } + + async fn initialization_options(&self) -> Option { + Some(json!({ + "provideFormatter": true + })) + } + + async fn language_ids(&self) -> HashMap { + [("JSON".into(), "jsonc".into())].into_iter().collect() + } +} diff --git a/crates/zed/src/languages/language_plugin.rs b/crates/zed/src/languages/language_plugin.rs index 6f4bdab78e..0f8d503adc 100644 --- a/crates/zed/src/languages/language_plugin.rs +++ b/crates/zed/src/languages/language_plugin.rs @@ -5,34 +5,10 @@ use collections::HashMap; use futures::lock::Mutex; use gpui::executor::Background; use language::{LanguageServerName, LspAdapter}; -use plugin_runtime::{Plugin, PluginBinary, PluginBuilder, PluginYield, WasiFn}; +use plugin_runtime::{Plugin, WasiFn}; use std::{any::Any, path::PathBuf, sync::Arc}; use util::ResultExt; -pub async fn new_json(executor: Arc) -> Result { - let executor_ref = executor.clone(); - let plugin = - PluginBuilder::new_epoch_with_default_ctx(PluginYield::default_epoch(), move |future| { - executor_ref.spawn(future).detach() - })? - .host_function_async("command", |command: String| async move { - let mut args = command.split(' '); - let command = args.next().unwrap(); - smol::process::Command::new(command) - .args(args) - .output() - .await - .log_err() - .map(|output| output.stdout) - })? - .init(PluginBinary::Precompiled(include_bytes!( - "../../../../plugins/bin/json_language.wasm.pre" - ))) - .await?; - - PluginLspAdapter::new(plugin, executor).await -} - pub struct PluginLspAdapter { name: WasiFn<(), String>, server_args: WasiFn<(), Vec>, @@ -46,6 +22,7 @@ pub struct PluginLspAdapter { } impl PluginLspAdapter { + #[allow(unused)] pub async fn new(mut plugin: Plugin, executor: Arc) -> Result { Ok(Self { name: plugin.function("name")?,