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