mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
Remove server_args
from LspAdapter
Prepare to remove concept of a runtime from greater server startup code, which is important for future language server extensibility Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
parent
ed442cfc8c
commit
1a2e509e35
@ -83,12 +83,17 @@ pub enum ServerExecutionKind {
|
||||
Node,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct LanguageServerBinary {
|
||||
pub path: PathBuf,
|
||||
pub arguments: Vec<String>,
|
||||
}
|
||||
|
||||
/// Represents a Language Server, with certain cached sync properties.
|
||||
/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
|
||||
/// once at startup, and caches the results.
|
||||
pub struct CachedLspAdapter {
|
||||
pub name: LanguageServerName,
|
||||
pub server_args: Vec<String>,
|
||||
pub initialization_options: Option<Value>,
|
||||
pub disk_based_diagnostic_sources: Vec<String>,
|
||||
pub disk_based_diagnostics_progress_token: Option<String>,
|
||||
@ -99,7 +104,6 @@ pub struct CachedLspAdapter {
|
||||
impl CachedLspAdapter {
|
||||
pub async fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
|
||||
let name = adapter.name().await;
|
||||
let server_args = adapter.server_args().await;
|
||||
let initialization_options = adapter.initialization_options().await;
|
||||
let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources().await;
|
||||
let disk_based_diagnostics_progress_token =
|
||||
@ -108,7 +112,6 @@ impl CachedLspAdapter {
|
||||
|
||||
Arc::new(CachedLspAdapter {
|
||||
name,
|
||||
server_args,
|
||||
initialization_options,
|
||||
disk_based_diagnostic_sources,
|
||||
disk_based_diagnostics_progress_token,
|
||||
@ -129,13 +132,16 @@ impl CachedLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
self.adapter
|
||||
.fetch_server_binary(version, http, container_dir)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
pub async fn cached_server_binary(
|
||||
&self,
|
||||
container_dir: PathBuf,
|
||||
) -> Option<LanguageServerBinary> {
|
||||
self.adapter.cached_server_binary(container_dir).await
|
||||
}
|
||||
|
||||
@ -190,9 +196,9 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf>;
|
||||
) -> Result<LanguageServerBinary>;
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf>;
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary>;
|
||||
|
||||
async fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
|
||||
|
||||
@ -215,10 +221,6 @@ pub trait LspAdapter: 'static + Send + Sync {
|
||||
None
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
async fn initialization_options(&self) -> Option<Value> {
|
||||
None
|
||||
}
|
||||
@ -497,7 +499,7 @@ pub struct LanguageRegistry {
|
||||
lsp_binary_paths: Mutex<
|
||||
HashMap<
|
||||
LanguageServerName,
|
||||
Shared<BoxFuture<'static, Result<PathBuf, Arc<anyhow::Error>>>>,
|
||||
Shared<BoxFuture<'static, Result<LanguageServerBinary, Arc<anyhow::Error>>>>,
|
||||
>,
|
||||
>,
|
||||
executor: Option<Arc<Background>>,
|
||||
@ -810,12 +812,12 @@ impl LanguageRegistry {
|
||||
login_shell_env_loaded.await;
|
||||
let node_path = node_path.await;
|
||||
|
||||
let server_binary_path = this
|
||||
let server_binary = this
|
||||
.lsp_binary_paths
|
||||
.lock()
|
||||
.entry(adapter.name.clone())
|
||||
.or_insert_with(|| {
|
||||
get_server_binary_path(
|
||||
get_server_binary(
|
||||
adapter.clone(),
|
||||
language.clone(),
|
||||
http_client,
|
||||
@ -829,8 +831,9 @@ impl LanguageRegistry {
|
||||
.clone()
|
||||
.map_err(|e| anyhow!(e));
|
||||
|
||||
let server_binary_path = server_binary_path.await?;
|
||||
let server_name = server_binary_path
|
||||
let server_binary = server_binary.await?;
|
||||
let server_name = server_binary
|
||||
.path
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy().to_string());
|
||||
|
||||
@ -839,16 +842,15 @@ impl LanguageRegistry {
|
||||
let node_path = node_path
|
||||
.ok_or(anyhow!("Missing Node path for Node based language server"))?;
|
||||
let node_binary = node_path.join("bin/node");
|
||||
dbg!(&node_binary);
|
||||
let mut command = smol::process::Command::new(node_binary);
|
||||
command.arg(dbg!(server_binary_path));
|
||||
command.arg(dbg!(server_binary.path));
|
||||
command
|
||||
}
|
||||
|
||||
ServerExecutionKind::Launch => smol::process::Command::new(server_binary_path),
|
||||
ServerExecutionKind::Launch => smol::process::Command::new(server_binary.path),
|
||||
};
|
||||
|
||||
command.args(&adapter.server_args);
|
||||
command.args(dbg!(&server_binary.arguments));
|
||||
let server = lsp::LanguageServer::new(server_id, server_name, command, &root_path, cx)?;
|
||||
|
||||
Ok(server)
|
||||
@ -880,13 +882,13 @@ impl Default for LanguageRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
async fn get_server_binary_path(
|
||||
async fn get_server_binary(
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
language: Arc<Language>,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
download_dir: Arc<Path>,
|
||||
statuses: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let container_dir = download_dir.join(adapter.name.0.as_ref());
|
||||
if !container_dir.exists() {
|
||||
smol::fs::create_dir_all(&container_dir)
|
||||
@ -894,7 +896,7 @@ async fn get_server_binary_path(
|
||||
.context("failed to create container directory")?;
|
||||
}
|
||||
|
||||
let path = fetch_latest_server_binary_path(
|
||||
let binary = fetch_latest_server_binary(
|
||||
adapter.clone(),
|
||||
language.clone(),
|
||||
http_client,
|
||||
@ -902,12 +904,12 @@ async fn get_server_binary_path(
|
||||
statuses.clone(),
|
||||
)
|
||||
.await;
|
||||
if let Err(error) = path.as_ref() {
|
||||
if let Some(cached_path) = adapter.cached_server_binary(container_dir).await {
|
||||
if let Err(error) = binary.as_ref() {
|
||||
if let Some(cached) = adapter.cached_server_binary(container_dir).await {
|
||||
statuses
|
||||
.broadcast((language.clone(), LanguageServerBinaryStatus::Cached))
|
||||
.await?;
|
||||
return Ok(cached_path);
|
||||
return Ok(cached);
|
||||
} else {
|
||||
statuses
|
||||
.broadcast((
|
||||
@ -919,16 +921,16 @@ async fn get_server_binary_path(
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
path
|
||||
binary
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_binary_path(
|
||||
async fn fetch_latest_server_binary(
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
language: Arc<Language>,
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
container_dir: &Path,
|
||||
lsp_binary_statuses_tx: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let container_dir: Arc<Path> = container_dir.into();
|
||||
lsp_binary_statuses_tx
|
||||
.broadcast((
|
||||
@ -942,13 +944,13 @@ async fn fetch_latest_server_binary_path(
|
||||
lsp_binary_statuses_tx
|
||||
.broadcast((language.clone(), LanguageServerBinaryStatus::Downloading))
|
||||
.await?;
|
||||
let path = adapter
|
||||
let binary = adapter
|
||||
.fetch_server_binary(version_info, http_client, container_dir.to_path_buf())
|
||||
.await?;
|
||||
lsp_binary_statuses_tx
|
||||
.broadcast((language.clone(), LanguageServerBinaryStatus::Downloaded))
|
||||
.await?;
|
||||
Ok(path)
|
||||
Ok(binary)
|
||||
}
|
||||
|
||||
impl Language {
|
||||
@ -1485,11 +1487,11 @@ impl LspAdapter for Arc<FakeLspAdapter> {
|
||||
_: Box<dyn 'static + Send + Any>,
|
||||
_: Arc<dyn HttpClient>,
|
||||
_: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, _: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ impl super::LspAdapter for CLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
|
||||
let zip_path = container_dir.join(format!("clangd_{}.zip", version.name));
|
||||
let version_dir = container_dir.join(format!("clangd_{}", version.name));
|
||||
@ -85,10 +85,13 @@ impl super::LspAdapter for CLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(binary_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
arguments: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last_clangd_dir = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
@ -101,7 +104,10 @@ impl super::LspAdapter for CLspAdapter {
|
||||
let clangd_dir = last_clangd_dir.ok_or_else(|| anyhow!("no cached binary"))?;
|
||||
let clangd_bin = clangd_dir.join("bin/clangd");
|
||||
if clangd_bin.exists() {
|
||||
Ok(clangd_bin)
|
||||
Ok(LanguageServerBinary {
|
||||
path: clangd_bin,
|
||||
arguments: vec![],
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"missing clangd binary in directory {:?}",
|
||||
|
@ -44,7 +44,7 @@ impl LspAdapter for ElixirLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
|
||||
let zip_path = container_dir.join(format!("elixir-ls_{}.zip", version.name));
|
||||
let version_dir = container_dir.join(format!("elixir-ls_{}", version.name));
|
||||
@ -98,17 +98,24 @@ impl LspAdapter for ElixirLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(binary_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
arguments: vec![],
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
while let Some(entry) = entries.next().await {
|
||||
last = Some(entry?.path());
|
||||
}
|
||||
last.ok_or_else(|| anyhow!("no cached binary"))
|
||||
last.map(|path| LanguageServerBinary {
|
||||
path,
|
||||
arguments: vec![],
|
||||
})
|
||||
.ok_or_else(|| anyhow!("no cached binary"))
|
||||
})()
|
||||
.await
|
||||
.log_err()
|
||||
|
@ -10,6 +10,10 @@ use smol::{fs, process};
|
||||
use std::{any::Any, ops::Range, path::PathBuf, str, sync::Arc};
|
||||
use util::ResultExt;
|
||||
|
||||
fn server_binary_arguments() -> Vec<String> {
|
||||
vec!["-mode=stdio".into()]
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct GoLspAdapter;
|
||||
|
||||
@ -27,10 +31,6 @@ impl super::LspAdapter for GoLspAdapter {
|
||||
ServerExecutionKind::Launch
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec!["-mode=stdio".into()]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
http: Arc<dyn HttpClient>,
|
||||
@ -51,7 +51,7 @@ impl super::LspAdapter for GoLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
_: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<Option<String>>().unwrap();
|
||||
let this = *self;
|
||||
|
||||
@ -72,7 +72,10 @@ impl super::LspAdapter for GoLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(binary_path.to_path_buf());
|
||||
return Ok(LanguageServerBinary {
|
||||
path: binary_path.to_path_buf(),
|
||||
arguments: server_binary_arguments(),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if let Some(path) = this.cached_server_binary(container_dir.clone()).await {
|
||||
@ -106,10 +109,13 @@ impl super::LspAdapter for GoLspAdapter {
|
||||
let binary_path = container_dir.join(&format!("gopls_{version}"));
|
||||
fs::rename(&installed_binary_path, &binary_path).await?;
|
||||
|
||||
Ok(binary_path.to_path_buf())
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path.to_path_buf(),
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last_binary_path = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
@ -126,7 +132,10 @@ impl super::LspAdapter for GoLspAdapter {
|
||||
}
|
||||
|
||||
if let Some(path) = last_binary_path {
|
||||
Ok(path)
|
||||
Ok(LanguageServerBinary {
|
||||
path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("no cached binary"))
|
||||
}
|
||||
|
@ -3,12 +3,16 @@ use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use client::http::HttpClient;
|
||||
use futures::StreamExt;
|
||||
use language::{LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use language::{LanguageServerBinary, LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use serde_json::json;
|
||||
use smol::fs;
|
||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||
use util::ResultExt;
|
||||
|
||||
fn server_binary_arguments() -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
pub struct HtmlLspAdapter;
|
||||
|
||||
impl HtmlLspAdapter {
|
||||
@ -26,10 +30,6 @@ impl LspAdapter for HtmlLspAdapter {
|
||||
ServerExecutionKind::Node
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
http: Arc<dyn HttpClient>,
|
||||
@ -45,7 +45,7 @@ impl LspAdapter for HtmlLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<String>().unwrap();
|
||||
let version_dir = container_dir.join(version.as_str());
|
||||
fs::create_dir_all(&version_dir)
|
||||
@ -73,10 +73,13 @@ impl LspAdapter for HtmlLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(binary_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last_version_dir = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
@ -89,7 +92,10 @@ impl LspAdapter for HtmlLspAdapter {
|
||||
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)
|
||||
Ok(LanguageServerBinary {
|
||||
path: bin_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"missing executable in directory {:?}",
|
||||
|
@ -48,8 +48,8 @@ pub async fn ensure_node_installation_dir(http: Arc<dyn HttpClient>) -> Result<P
|
||||
let arch = "arm64";
|
||||
|
||||
let folder_name = format!("node-{version}-darwin-{arch}");
|
||||
let node_containing_dir = dbg!(util::paths::SUPPORT_DIR.join("node"));
|
||||
let node_dir = dbg!(node_containing_dir.join(folder_name));
|
||||
let node_containing_dir = util::paths::SUPPORT_DIR.join("node");
|
||||
let node_dir = node_containing_dir.join(folder_name);
|
||||
let node_binary = node_dir.join("bin/node");
|
||||
|
||||
if fs::metadata(&node_binary).await.is_err() {
|
||||
@ -59,7 +59,6 @@ pub async fn ensure_node_installation_dir(http: Arc<dyn HttpClient>) -> Result<P
|
||||
.context("error creating node containing dir")?;
|
||||
|
||||
let url = format!("https://nodejs.org/dist/{version}/node-{version}-darwin-{arch}.tar.gz");
|
||||
dbg!(&url);
|
||||
let mut response = http
|
||||
.get(&url, Default::default(), true)
|
||||
.await
|
||||
@ -71,8 +70,7 @@ pub async fn ensure_node_installation_dir(http: Arc<dyn HttpClient>) -> Result<P
|
||||
eprintln!("unpacked");
|
||||
}
|
||||
|
||||
eprintln!("returning");
|
||||
Ok(dbg!(node_dir))
|
||||
Ok(node_dir)
|
||||
}
|
||||
|
||||
pub async fn npm_package_latest_version(http: Arc<dyn HttpClient>, name: &str) -> Result<String> {
|
||||
|
@ -6,7 +6,9 @@ use client::http::HttpClient;
|
||||
use collections::HashMap;
|
||||
use futures::{future::BoxFuture, io::BufReader, FutureExt, StreamExt};
|
||||
use gpui::MutableAppContext;
|
||||
use language::{LanguageRegistry, LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use language::{
|
||||
LanguageRegistry, LanguageServerBinary, LanguageServerName, LspAdapter, ServerExecutionKind,
|
||||
};
|
||||
use serde_json::json;
|
||||
use settings::{keymap_file_json_schema, settings_file_json_schema};
|
||||
use smol::fs::{self, File};
|
||||
@ -20,6 +22,10 @@ use std::{
|
||||
use theme::ThemeRegistry;
|
||||
use util::{paths, ResultExt, StaffMode};
|
||||
|
||||
fn server_binary_arguments() -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
pub struct JsonLspAdapter {
|
||||
languages: Arc<LanguageRegistry>,
|
||||
themes: Arc<ThemeRegistry>,
|
||||
@ -41,10 +47,6 @@ impl LspAdapter for JsonLspAdapter {
|
||||
ServerExecutionKind::Node
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
http: Arc<dyn HttpClient>,
|
||||
@ -68,7 +70,7 @@ impl LspAdapter for JsonLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
|
||||
let destination_path = container_dir.join(format!(
|
||||
"json-language-server-{}-{}",
|
||||
@ -102,17 +104,23 @@ impl LspAdapter for JsonLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(destination_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: destination_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
while let Some(entry) = entries.next().await {
|
||||
last = Some(entry?.path());
|
||||
}
|
||||
last.ok_or_else(|| anyhow!("no cached binary"))
|
||||
anyhow::Ok(LanguageServerBinary {
|
||||
path: last.ok_or_else(|| anyhow!("no cached binary"))?,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
})()
|
||||
.await
|
||||
.log_err()
|
||||
|
@ -4,7 +4,7 @@ use client::http::HttpClient;
|
||||
use collections::HashMap;
|
||||
use futures::lock::Mutex;
|
||||
use gpui::executor::Background;
|
||||
use language::{LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use language::{LanguageServerBinary, LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use plugin_runtime::{Plugin, PluginBinary, PluginBuilder, WasiFn};
|
||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||
use util::ResultExt;
|
||||
@ -33,10 +33,9 @@ pub async fn new_json(executor: Arc<Background>) -> Result<PluginLspAdapter> {
|
||||
pub struct PluginLspAdapter {
|
||||
name: WasiFn<(), String>,
|
||||
server_execution_kind: WasiFn<(), ServerExecutionKind>,
|
||||
server_args: WasiFn<(), Vec<String>>,
|
||||
fetch_latest_server_version: WasiFn<(), Option<String>>,
|
||||
fetch_server_binary: WasiFn<(PathBuf, String), Result<PathBuf, String>>,
|
||||
cached_server_binary: WasiFn<PathBuf, Option<PathBuf>>,
|
||||
fetch_server_binary: WasiFn<(PathBuf, String), Result<LanguageServerBinary, String>>,
|
||||
cached_server_binary: WasiFn<PathBuf, Option<LanguageServerBinary>>,
|
||||
initialization_options: WasiFn<(), String>,
|
||||
language_ids: WasiFn<(), Vec<(String, String)>>,
|
||||
executor: Arc<Background>,
|
||||
@ -49,7 +48,6 @@ impl PluginLspAdapter {
|
||||
Ok(Self {
|
||||
name: plugin.function("name")?,
|
||||
server_execution_kind: plugin.function("server_execution_kind")?,
|
||||
server_args: plugin.function("server_args")?,
|
||||
fetch_latest_server_version: plugin.function("fetch_latest_server_version")?,
|
||||
fetch_server_binary: plugin.function("fetch_server_binary")?,
|
||||
cached_server_binary: plugin.function("cached_server_binary")?,
|
||||
@ -83,15 +81,6 @@ impl LspAdapter for PluginLspAdapter {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn server_args<'a>(&'a self) -> Vec<String> {
|
||||
self.runtime
|
||||
.lock()
|
||||
.await
|
||||
.call(&self.server_args, ())
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
_: Arc<dyn HttpClient>,
|
||||
@ -116,7 +105,7 @@ impl LspAdapter for PluginLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
_: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = *version.downcast::<String>().unwrap();
|
||||
let runtime = self.runtime.clone();
|
||||
let function = self.fetch_server_binary;
|
||||
@ -124,7 +113,7 @@ impl LspAdapter for PluginLspAdapter {
|
||||
.spawn(async move {
|
||||
let mut runtime = runtime.lock().await;
|
||||
let handle = runtime.attach_path(&container_dir)?;
|
||||
let result: Result<PathBuf, String> =
|
||||
let result: Result<LanguageServerBinary, String> =
|
||||
runtime.call(&function, (container_dir, version)).await?;
|
||||
runtime.remove_resource(handle)?;
|
||||
result.map_err(|e| anyhow!("{}", e))
|
||||
@ -132,7 +121,7 @@ impl LspAdapter for PluginLspAdapter {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
let runtime = self.runtime.clone();
|
||||
let function = self.cached_server_binary;
|
||||
|
||||
@ -140,7 +129,8 @@ impl LspAdapter for PluginLspAdapter {
|
||||
.spawn(async move {
|
||||
let mut runtime = runtime.lock().await;
|
||||
let handle = runtime.attach_path(&container_dir).ok()?;
|
||||
let result: Option<PathBuf> = runtime.call(&function, container_dir).await.ok()?;
|
||||
let result: Option<LanguageServerBinary> =
|
||||
runtime.call(&function, container_dir).await.ok()?;
|
||||
runtime.remove_resource(handle).ok()?;
|
||||
result
|
||||
})
|
||||
|
@ -6,7 +6,7 @@ use async_tar::Archive;
|
||||
use async_trait::async_trait;
|
||||
use client::http::HttpClient;
|
||||
use futures::{io::BufReader, StreamExt};
|
||||
use language::{LanguageServerName, ServerExecutionKind};
|
||||
use language::{LanguageServerBinary, LanguageServerName, ServerExecutionKind};
|
||||
use smol::fs;
|
||||
use util::{async_iife, ResultExt};
|
||||
|
||||
@ -15,6 +15,13 @@ use super::installation::{latest_github_release, GitHubLspBinaryVersion};
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct LuaLspAdapter;
|
||||
|
||||
fn server_binary_arguments() -> Vec<String> {
|
||||
vec![
|
||||
"--logpath=~/lua-language-server.log".into(),
|
||||
"--loglevel=trace".into(),
|
||||
]
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl super::LspAdapter for LuaLspAdapter {
|
||||
async fn name(&self) -> LanguageServerName {
|
||||
@ -25,13 +32,6 @@ impl super::LspAdapter for LuaLspAdapter {
|
||||
ServerExecutionKind::Launch
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec![
|
||||
"--logpath=~/lua-language-server.log".into(),
|
||||
"--loglevel=trace".into(),
|
||||
]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
http: Arc<dyn HttpClient>,
|
||||
@ -61,7 +61,7 @@ impl super::LspAdapter for LuaLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
|
||||
|
||||
let binary_path = container_dir.join("bin/lua-language-server");
|
||||
@ -81,10 +81,13 @@ impl super::LspAdapter for LuaLspAdapter {
|
||||
<fs::Permissions as fs::unix::PermissionsExt>::from_mode(0o755),
|
||||
)
|
||||
.await?;
|
||||
Ok(binary_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
async_iife!({
|
||||
let mut last_binary_path = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
@ -101,7 +104,10 @@ impl super::LspAdapter for LuaLspAdapter {
|
||||
}
|
||||
|
||||
if let Some(path) = last_binary_path {
|
||||
Ok(path)
|
||||
Ok(LanguageServerBinary {
|
||||
path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!("no cached binary"))
|
||||
}
|
||||
|
@ -3,13 +3,17 @@ use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use client::http::HttpClient;
|
||||
use futures::StreamExt;
|
||||
use language::{LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use language::{LanguageServerBinary, LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use smol::fs;
|
||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||
use util::ResultExt;
|
||||
|
||||
pub struct PythonLspAdapter;
|
||||
|
||||
fn server_binary_arguments() -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
impl PythonLspAdapter {
|
||||
const BIN_PATH: &'static str = "node_modules/pyright/langserver.index.js";
|
||||
}
|
||||
@ -24,10 +28,6 @@ impl LspAdapter for PythonLspAdapter {
|
||||
ServerExecutionKind::Node
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
http: Arc<dyn HttpClient>,
|
||||
@ -40,7 +40,7 @@ impl LspAdapter for PythonLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<String>().unwrap();
|
||||
let version_dir = container_dir.join(version.as_str());
|
||||
fs::create_dir_all(&version_dir)
|
||||
@ -63,10 +63,13 @@ impl LspAdapter for PythonLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(binary_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last_version_dir = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
@ -79,7 +82,10 @@ impl LspAdapter for PythonLspAdapter {
|
||||
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)
|
||||
Ok(LanguageServerBinary {
|
||||
path: bin_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"missing executable in directory {:?}",
|
||||
|
@ -1,7 +1,7 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use client::http::HttpClient;
|
||||
use language::{LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use language::{LanguageServerBinary, LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||
|
||||
pub struct RubyLanguageServer;
|
||||
@ -16,10 +16,6 @@ impl LspAdapter for RubyLanguageServer {
|
||||
ServerExecutionKind::Launch
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec!["stdio".into()]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
_: Arc<dyn HttpClient>,
|
||||
@ -32,12 +28,15 @@ impl LspAdapter for RubyLanguageServer {
|
||||
_version: Box<dyn 'static + Send + Any>,
|
||||
_: Arc<dyn HttpClient>,
|
||||
_container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
Err(anyhow!("solargraph must be installed manually"))
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, _container_dir: PathBuf) -> Option<PathBuf> {
|
||||
Some("solargraph".into())
|
||||
async fn cached_server_binary(&self, _container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
Some(LanguageServerBinary {
|
||||
path: "solargraph".into(),
|
||||
arguments: vec!["stdio".into()],
|
||||
})
|
||||
}
|
||||
|
||||
async fn label_for_completion(
|
||||
|
@ -46,7 +46,7 @@ impl LspAdapter for RustLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
|
||||
let destination_path = container_dir.join(format!("rust-analyzer-{}", version.name));
|
||||
|
||||
@ -76,17 +76,23 @@ impl LspAdapter for RustLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(destination_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: destination_path,
|
||||
arguments: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
while let Some(entry) = entries.next().await {
|
||||
last = Some(entry?.path());
|
||||
}
|
||||
last.ok_or_else(|| anyhow!("no cached binary"))
|
||||
anyhow::Ok(LanguageServerBinary {
|
||||
path: last.ok_or_else(|| anyhow!("no cached binary"))?,
|
||||
arguments: Default::default(),
|
||||
})
|
||||
})()
|
||||
.await
|
||||
.log_err()
|
||||
|
@ -3,12 +3,19 @@ use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use client::http::HttpClient;
|
||||
use futures::StreamExt;
|
||||
use language::{LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use language::{LanguageServerBinary, LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use serde_json::json;
|
||||
use smol::fs;
|
||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||
use util::ResultExt;
|
||||
|
||||
fn server_binary_arguments() -> Vec<String> {
|
||||
["--stdio", "--tsserver-path", "node_modules/typescript/lib"]
|
||||
.into_iter()
|
||||
.map(Into::into)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub struct TypeScriptLspAdapter;
|
||||
|
||||
impl TypeScriptLspAdapter {
|
||||
@ -31,13 +38,6 @@ impl LspAdapter for TypeScriptLspAdapter {
|
||||
ServerExecutionKind::Node
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
["--stdio", "--tsserver-path", "node_modules/typescript/lib"]
|
||||
.into_iter()
|
||||
.map(str::to_string)
|
||||
.collect()
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
http: Arc<dyn HttpClient>,
|
||||
@ -53,7 +53,7 @@ impl LspAdapter for TypeScriptLspAdapter {
|
||||
versions: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let versions = versions.downcast::<Versions>().unwrap();
|
||||
let version_dir = container_dir.join(&format!(
|
||||
"typescript-{}:server-{}",
|
||||
@ -90,10 +90,13 @@ impl LspAdapter for TypeScriptLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(binary_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last_version_dir = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
@ -107,9 +110,15 @@ impl LspAdapter for TypeScriptLspAdapter {
|
||||
let old_bin_path = last_version_dir.join(Self::OLD_BIN_PATH);
|
||||
let new_bin_path = last_version_dir.join(Self::NEW_BIN_PATH);
|
||||
if new_bin_path.exists() {
|
||||
Ok(new_bin_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: new_bin_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
} else if old_bin_path.exists() {
|
||||
Ok(old_bin_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: old_bin_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"missing executable in directory {:?}",
|
||||
|
@ -3,7 +3,7 @@ use async_trait::async_trait;
|
||||
use client::http::HttpClient;
|
||||
use futures::{future::BoxFuture, FutureExt, StreamExt};
|
||||
use gpui::MutableAppContext;
|
||||
use language::{LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use language::{LanguageServerBinary, LanguageServerName, LspAdapter, ServerExecutionKind};
|
||||
use serde_json::Value;
|
||||
use settings::Settings;
|
||||
use smol::fs;
|
||||
@ -12,6 +12,10 @@ use util::ResultExt;
|
||||
|
||||
use super::installation::{npm_install_packages, npm_package_latest_version};
|
||||
|
||||
fn server_binary_arguments() -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
pub struct YamlLspAdapter;
|
||||
|
||||
impl YamlLspAdapter {
|
||||
@ -28,10 +32,6 @@ impl LspAdapter for YamlLspAdapter {
|
||||
ServerExecutionKind::Node
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec!["--stdio".into()]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
http: Arc<dyn HttpClient>,
|
||||
@ -44,7 +44,7 @@ impl LspAdapter for YamlLspAdapter {
|
||||
version: Box<dyn 'static + Send + Any>,
|
||||
http: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = version.downcast::<String>().unwrap();
|
||||
let version_dir = container_dir.join(version.as_str());
|
||||
fs::create_dir_all(&version_dir)
|
||||
@ -72,10 +72,13 @@ impl LspAdapter for YamlLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(binary_path)
|
||||
Ok(LanguageServerBinary {
|
||||
path: binary_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last_version_dir = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
@ -88,7 +91,10 @@ impl LspAdapter for YamlLspAdapter {
|
||||
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)
|
||||
Ok(LanguageServerBinary {
|
||||
path: bin_path,
|
||||
arguments: server_binary_arguments(),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"missing executable in directory {:?}",
|
||||
|
Loading…
Reference in New Issue
Block a user