Detailed changes
@@ -1050,47 +1050,41 @@ async fn heuristic_syntactic_expand(
let node_range = node_start..node_end;
let row_count = node_end.row - node_start.row + 1;
let mut ancestor_range = None;
- cx.background_executor()
- .await_on_background(async {
- // Stop if we've exceeded the row count or reached an outline node. Then, find the interval
- // of node children which contains the query range. For example, this allows just returning
- // the header of a declaration rather than the entire declaration.
- if row_count > max_row_count || outline_range == Some(node_range.clone()) {
- let mut cursor = node.walk();
- let mut included_child_start = None;
- let mut included_child_end = None;
- let mut previous_end = node_start;
- if cursor.goto_first_child() {
- loop {
- let child_node = cursor.node();
- let child_range =
- previous_end..Point::from_ts_point(child_node.end_position());
- if included_child_start.is_none()
- && child_range.contains(&input_range.start)
- {
- included_child_start = Some(child_range.start);
- }
- if child_range.contains(&input_range.end) {
- included_child_end = Some(child_range.end);
- }
- previous_end = child_range.end;
- if !cursor.goto_next_sibling() {
- break;
- }
- }
+ // Stop if we've exceeded the row count or reached an outline node. Then, find the interval
+ // of node children which contains the query range. For example, this allows just returning
+ // the header of a declaration rather than the entire declaration.
+ if row_count > max_row_count || outline_range == Some(node_range.clone()) {
+ let mut cursor = node.walk();
+ let mut included_child_start = None;
+ let mut included_child_end = None;
+ let mut previous_end = node_start;
+ if cursor.goto_first_child() {
+ loop {
+ let child_node = cursor.node();
+ let child_range = previous_end..Point::from_ts_point(child_node.end_position());
+ if included_child_start.is_none() && child_range.contains(&input_range.start) {
+ included_child_start = Some(child_range.start);
}
- let end = included_child_end.unwrap_or(node_range.end);
- if let Some(start) = included_child_start {
- let row_count = end.row - start.row;
- if row_count < max_row_count {
- ancestor_range = Some(Some(RangeInclusive::new(start.row, end.row)));
- return;
- }
+ if child_range.contains(&input_range.end) {
+ included_child_end = Some(child_range.end);
+ }
+ previous_end = child_range.end;
+ if !cursor.goto_next_sibling() {
+ break;
}
- ancestor_range = Some(None);
}
- })
- .await;
+ }
+ let end = included_child_end.unwrap_or(node_range.end);
+ if let Some(start) = included_child_start {
+ let row_count = end.row - start.row;
+ if row_count < max_row_count {
+ ancestor_range = Some(Some(RangeInclusive::new(start.row, end.row)));
+ }
+ }
+ if ancestor_range.is_none() {
+ ancestor_range = Some(None);
+ }
+ }
if let Some(node) = ancestor_range {
return node;
}
@@ -115,60 +115,6 @@ impl BackgroundExecutor {
}
}
- /// Enqueues the given future to be run to completion on a background thread and blocking the current task on it.
- ///
- /// This allows to spawn background work that borrows from its scope. Note that the supplied future will run to
- /// completion before the current task is resumed, even if the current task is slated for cancellation.
- pub async fn await_on_background<R>(&self, future: impl Future<Output = R> + Send) -> R
- where
- R: Send,
- {
- use crate::RunnableMeta;
- use parking_lot::{Condvar, Mutex};
-
- struct NotifyOnDrop<'a>(&'a (Condvar, Mutex<bool>));
-
- impl Drop for NotifyOnDrop<'_> {
- fn drop(&mut self) {
- *self.0.1.lock() = true;
- self.0.0.notify_all();
- }
- }
-
- struct WaitOnDrop<'a>(&'a (Condvar, Mutex<bool>));
-
- impl Drop for WaitOnDrop<'_> {
- fn drop(&mut self) {
- let mut done = self.0.1.lock();
- if !*done {
- self.0.0.wait(&mut done);
- }
- }
- }
-
- let dispatcher = self.dispatcher.clone();
- let location = core::panic::Location::caller();
-
- let pair = &(Condvar::new(), Mutex::new(false));
- let _wait_guard = WaitOnDrop(pair);
-
- let (runnable, task) = unsafe {
- async_task::Builder::new()
- .metadata(RunnableMeta { location })
- .spawn_unchecked(
- move |_| async {
- let _notify_guard = NotifyOnDrop(pair);
- future.await
- },
- move |runnable| {
- dispatcher.dispatch(runnable, Priority::default());
- },
- )
- };
- runnable.schedule();
- task.await
- }
-
/// Scoped lets you start a number of tasks and waits
/// for all of them to complete before returning.
pub async fn scoped<'scope, F>(&self, scheduler: F)
@@ -623,8 +623,8 @@ pub trait LspInstaller {
&self,
_version: &Self::BinaryVersion,
_container_dir: &PathBuf,
- _delegate: &dyn LspAdapterDelegate,
- ) -> impl Send + Future<Output = Option<LanguageServerBinary>> {
+ _delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<Self> {
async { None }
}
@@ -632,8 +632,8 @@ pub trait LspInstaller {
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> impl Send + Future<Output = Result<LanguageServerBinary>>;
+ _delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<Self>;
fn cached_server_binary(
&self,
@@ -686,11 +686,7 @@ where
if let Some(binary) = cx
.background_executor()
- .await_on_background(self.check_if_version_installed(
- &latest_version,
- &container_dir,
- delegate.as_ref(),
- ))
+ .spawn(self.check_if_version_installed(&latest_version, &container_dir, &delegate))
.await
{
log::debug!("language server {:?} is already installed", name.0);
@@ -701,11 +697,7 @@ where
delegate.update_status(name.clone(), BinaryStatus::Downloading);
let binary = cx
.background_executor()
- .await_on_background(self.fetch_server_binary(
- latest_version,
- container_dir,
- delegate.as_ref(),
- ))
+ .spawn(self.fetch_server_binary(latest_version, container_dir, delegate))
.await;
delegate.update_status(name.clone(), BinaryStatus::None);
@@ -1421,13 +1413,15 @@ impl LspInstaller for FakeLspAdapter {
Some(self.language_server_binary.clone())
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
_: (),
_: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- unreachable!();
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ async {
+ unreachable!();
+ }
}
async fn cached_server_binary(
@@ -6,7 +6,7 @@ use lsp::LanguageServerBinary;
use node_runtime::{NodeRuntime, VersionStrategy};
use project::ContextProviderWithTasks;
use semver::Version;
-use std::{path::PathBuf, vec};
+use std::{future::Future, path::PathBuf, sync::Arc, vec};
use task::{TaskTemplate, TaskTemplates, VariableName};
use util::{ResultExt, maybe};
@@ -90,35 +90,41 @@ impl LspInstaller for BashLspAdapter {
})
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Option<lsp::LanguageServerBinary> {
- let server_path = container_dir
- .join("node_modules")
- .join(Self::NODE_MODULE_RELATIVE_SERVER_PATH);
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<lsp::LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
+ let delegate = delegate.clone();
+
+ async move {
+ let server_path = container_dir
+ .join("node_modules")
+ .join(Self::NODE_MODULE_RELATIVE_SERVER_PATH);
- if should_install_language_server {
- None
- } else {
- let env = delegate.shell_env().await;
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: Some(env),
- arguments: vec![server_path.into(), "start".into()],
- })
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ let env = delegate.shell_env().await;
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: Some(env),
+ arguments: vec![server_path.into(), "start".into()],
+ })
+ }
}
}
@@ -133,29 +139,34 @@ impl LspInstaller for BashLspAdapter {
.await
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: std::path::PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<lsp::LanguageServerBinary> {
- let server_path = container_dir
- .join("node_modules")
- .join(Self::NODE_MODULE_RELATIVE_SERVER_PATH);
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<lsp::LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let delegate = delegate.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir
+ .join("node_modules")
+ .join(Self::NODE_MODULE_RELATIVE_SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
- &[(Self::PACKAGE_NAME, &latest_version.to_string())],
+ &[(Self::PACKAGE_NAME, latest_version.as_str())],
)
.await?;
- let env = delegate.shell_env().await;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: Some(env),
- arguments: vec![server_path.into(), "start".into()],
- })
+ let env = delegate.shell_env().await;
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: Some(env),
+ arguments: vec![server_path.into(), "start".into()],
+ })
+ }
}
}
@@ -9,7 +9,7 @@ use lsp::{InitializeParams, LanguageServerBinary, LanguageServerName};
use project::lsp_store::clangd_ext;
use serde_json::json;
use smol::fs;
-use std::{env::consts, path::PathBuf, sync::Arc};
+use std::{env::consts, future::Future, path::PathBuf, sync::Arc};
use util::{ResultExt, fs::remove_matching, maybe, merge_json_value_into};
pub struct CLspAdapter;
@@ -66,82 +66,88 @@ impl LspInstaller for CLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
version: GitHubLspBinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- ensure_arch_compatibility()?;
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
- let GitHubLspBinaryVersion {
- name,
- url,
- digest: expected_digest,
- } = version;
- let version_dir = container_dir.join(format!("clangd_{name}"));
- let binary_path = version_dir
- .join("bin")
- .join(format!("clangd{}", consts::EXE_SUFFIX));
+ async move {
+ ensure_arch_compatibility()?;
- let binary = LanguageServerBinary {
- path: binary_path.clone(),
- env: None,
- arguments: Default::default(),
- };
-
- let metadata_path = version_dir.join("metadata");
- let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
- .await
- .ok();
- if let Some(metadata) = metadata {
- let validity_check = async || {
- delegate
- .try_exec(LanguageServerBinary {
- path: binary_path.clone(),
- arguments: vec!["--version".into()],
- env: None,
- })
- .await
- .inspect_err(|err| {
- log::warn!("Unable to run {binary_path:?} asset, redownloading: {err:#}",)
- })
+ let GitHubLspBinaryVersion {
+ name,
+ url,
+ digest: expected_digest,
+ } = version;
+ let version_dir = container_dir.join(format!("clangd_{name}"));
+ let binary_path = version_dir
+ .join("bin")
+ .join(format!("clangd{}", consts::EXE_SUFFIX));
+
+ let binary = LanguageServerBinary {
+ path: binary_path.clone(),
+ env: None,
+ arguments: Default::default(),
};
- if let (Some(actual_digest), Some(expected_digest)) =
- (&metadata.digest, &expected_digest)
- {
- if actual_digest == expected_digest {
- if validity_check().await.is_ok() {
- return Ok(binary);
+
+ let metadata_path = version_dir.join("metadata");
+ let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
+ .await
+ .ok();
+ if let Some(metadata) = metadata {
+ let validity_check = async || {
+ delegate
+ .try_exec(LanguageServerBinary {
+ path: binary_path.clone(),
+ arguments: vec!["--version".into()],
+ env: None,
+ })
+ .await
+ .inspect_err(|err| {
+ log::warn!(
+ "Unable to run {binary_path:?} asset, redownloading: {err:#}",
+ )
+ })
+ };
+ if let (Some(actual_digest), Some(expected_digest)) =
+ (&metadata.digest, &expected_digest)
+ {
+ if actual_digest == expected_digest {
+ if validity_check().await.is_ok() {
+ return Ok(binary);
+ }
+ } else {
+ log::info!(
+ "SHA-256 mismatch for {binary_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
+ );
}
- } else {
- log::info!(
- "SHA-256 mismatch for {binary_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
- );
+ } else if validity_check().await.is_ok() {
+ return Ok(binary);
}
- } else if validity_check().await.is_ok() {
- return Ok(binary);
}
- }
- download_server_binary(
- &*delegate.http_client(),
- &url,
- expected_digest.as_deref(),
- &container_dir,
- AssetKind::Zip,
- )
- .await?;
- remove_matching(&container_dir, |entry| entry != version_dir).await;
- GithubBinaryMetadata::write_to_file(
- &GithubBinaryMetadata {
- metadata_version: 1,
- digest: expected_digest,
- },
- &metadata_path,
- )
- .await?;
+ download_server_binary(
+ &*delegate.http_client(),
+ &url,
+ expected_digest.as_deref(),
+ &container_dir,
+ AssetKind::Zip,
+ )
+ .await?;
+ remove_matching(&container_dir, |entry| entry != version_dir).await;
+ GithubBinaryMetadata::write_to_file(
+ &GithubBinaryMetadata {
+ metadata_version: 1,
+ digest: expected_digest,
+ },
+ &metadata_path,
+ )
+ .await?;
- Ok(binary)
+ Ok(binary)
+ }
}
async fn cached_server_binary(
@@ -9,6 +9,7 @@ use semver::Version;
use serde_json::json;
use std::{
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
sync::Arc,
};
@@ -64,55 +65,63 @@ impl LspInstaller for CssLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
- let latest_version = latest_version.to_string();
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
&[(Self::PACKAGE_NAME, latest_version.as_str())],
)
.await?;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
- if should_install_language_server {
- None
- } else {
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
}
@@ -17,6 +17,7 @@ use settings::SettingsLocation;
use smol::{fs, stream::StreamExt};
use std::{
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
sync::Arc,
};
@@ -99,60 +100,63 @@ impl LspInstaller for EsLintLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
version: GitHubLspBinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let destination_path = Self::build_destination_path(&container_dir);
- let server_path = destination_path.join(Self::SERVER_PATH);
-
- if fs::metadata(&server_path).await.is_err() {
- remove_matching(&container_dir, |_| true).await;
-
- download_server_binary(
- &*delegate.http_client(),
- &version.url,
- None,
- &destination_path,
- Self::GITHUB_ASSET_KIND,
- )
- .await?;
-
- let mut dir = fs::read_dir(&destination_path).await?;
- let first = dir.next().await.context("missing first file")??;
- let repo_root = destination_path.join("vscode-eslint");
- fs::rename(first.path(), &repo_root).await?;
-
- #[cfg(target_os = "windows")]
- {
- handle_symlink(
- repo_root.join("$shared"),
- repo_root.join("client").join("src").join("shared"),
- )
- .await?;
- handle_symlink(
- repo_root.join("$shared"),
- repo_root.join("server").join("src").join("shared"),
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+ let node = self.node.clone();
+
+ async move {
+ let destination_path = Self::build_destination_path(&container_dir);
+ let server_path = destination_path.join(Self::SERVER_PATH);
+
+ if fs::metadata(&server_path).await.is_err() {
+ remove_matching(&container_dir, |_| true).await;
+
+ download_server_binary(
+ &*delegate.http_client(),
+ &version.url,
+ None,
+ &destination_path,
+ Self::GITHUB_ASSET_KIND,
)
.await?;
- }
- self.node
- .run_npm_subcommand(Some(&repo_root), "install", &[])
- .await?;
+ let mut dir = fs::read_dir(&destination_path).await?;
+ let first = dir.next().await.context("missing first file")??;
+ let repo_root = destination_path.join("vscode-eslint");
+ fs::rename(first.path(), &repo_root).await?;
- self.node
- .run_npm_subcommand(Some(&repo_root), "run-script", &["compile"])
- .await?;
- }
+ #[cfg(target_os = "windows")]
+ {
+ handle_symlink(
+ repo_root.join("$shared"),
+ repo_root.join("client").join("src").join("shared"),
+ )
+ .await?;
+ handle_symlink(
+ repo_root.join("$shared"),
+ repo_root.join("server").join("src").join("shared"),
+ )
+ .await?;
+ }
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: eslint_server_binary_arguments(&server_path),
- })
+ node.run_npm_subcommand(Some(&repo_root), "install", &[])
+ .await?;
+
+ node.run_npm_subcommand(Some(&repo_root), "run-script", &["compile"])
+ .await?;
+ }
+
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: eslint_server_binary_arguments(&server_path),
+ })
+ }
}
async fn cached_server_binary(
@@ -19,6 +19,7 @@ use smol::fs;
use std::{
borrow::Cow,
ffi::{OsStr, OsString},
+ future::Future,
ops::Range,
path::{Path, PathBuf},
process::Output,
@@ -117,75 +118,79 @@ impl LspInstaller for GoLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
version: Option<String>,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let go = delegate.which("go".as_ref()).await.unwrap_or("go".into());
- let go_version_output = util::command::new_command(&go)
- .args(["version"])
- .output()
- .await
- .context("failed to get go version via `go version` command`")?;
- let go_version = parse_version_output(&go_version_output)?;
-
- if let Some(version) = version {
- let binary_path = container_dir.join(format!("gopls_{version}_go_{go_version}"));
- if let Ok(metadata) = fs::metadata(&binary_path).await
- && metadata.is_file()
- {
- remove_matching(&container_dir, |entry| {
- entry != binary_path && entry.file_name() != Some(OsStr::new("gobin"))
- })
- .await;
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+
+ async move {
+ let go = delegate.which("go".as_ref()).await.unwrap_or("go".into());
+ let go_version_output = util::command::new_command(&go)
+ .args(["version"])
+ .output()
+ .await
+ .context("failed to get go version via `go version` command`")?;
+ let go_version = parse_version_output(&go_version_output)?;
+
+ if let Some(version) = version {
+ let binary_path = container_dir.join(format!("gopls_{version}_go_{go_version}"));
+ if let Ok(metadata) = fs::metadata(&binary_path).await
+ && metadata.is_file()
+ {
+ remove_matching(&container_dir, |entry| {
+ entry != binary_path && entry.file_name() != Some(OsStr::new("gobin"))
+ })
+ .await;
- return Ok(LanguageServerBinary {
- path: binary_path.to_path_buf(),
- arguments: server_binary_arguments(),
- env: None,
- });
+ return Ok(LanguageServerBinary {
+ path: binary_path.to_path_buf(),
+ arguments: server_binary_arguments(),
+ env: None,
+ });
+ }
+ } else if let Some(path) = get_cached_server_binary(&container_dir).await {
+ return Ok(path);
}
- } else if let Some(path) = get_cached_server_binary(&container_dir).await {
- return Ok(path);
- }
- let gobin_dir = container_dir.join("gobin");
- fs::create_dir_all(&gobin_dir).await?;
- let install_output = util::command::new_command(go)
- .env("GO111MODULE", "on")
- .env("GOBIN", &gobin_dir)
- .args(["install", "golang.org/x/tools/gopls@latest"])
- .output()
- .await?;
-
- if !install_output.status.success() {
- log::error!(
- "failed to install gopls via `go install`. stdout: {:?}, stderr: {:?}",
- String::from_utf8_lossy(&install_output.stdout),
- String::from_utf8_lossy(&install_output.stderr)
- );
- anyhow::bail!(
- "failed to install gopls with `go install`. Is `go` installed and in the PATH? Check logs for more information."
- );
- }
+ let gobin_dir = container_dir.join("gobin");
+ fs::create_dir_all(&gobin_dir).await?;
+ let install_output = util::command::new_command(go)
+ .env("GO111MODULE", "on")
+ .env("GOBIN", &gobin_dir)
+ .args(["install", "golang.org/x/tools/gopls@latest"])
+ .output()
+ .await?;
+
+ if !install_output.status.success() {
+ log::error!(
+ "failed to install gopls via `go install`. stdout: {:?}, stderr: {:?}",
+ String::from_utf8_lossy(&install_output.stdout),
+ String::from_utf8_lossy(&install_output.stderr)
+ );
+ anyhow::bail!(
+ "failed to install gopls with `go install`. Is `go` installed and in the PATH? Check logs for more information."
+ );
+ }
- let installed_binary_path = gobin_dir.join(BINARY);
- let version_output = util::command::new_command(&installed_binary_path)
- .arg("version")
- .output()
- .await
- .context("failed to run installed gopls binary")?;
- let gopls_version = parse_version_output(&version_output)?;
- let binary_path = container_dir.join(format!("gopls_{gopls_version}_go_{go_version}"));
- fs::rename(&installed_binary_path, &binary_path).await?;
-
- Ok(LanguageServerBinary {
- path: binary_path.to_path_buf(),
- arguments: server_binary_arguments(),
- env: None,
- })
+ let installed_binary_path = gobin_dir.join(BINARY);
+ let version_output = util::command::new_command(&installed_binary_path)
+ .arg("version")
+ .output()
+ .await
+ .context("failed to run installed gopls binary")?;
+ let gopls_version = parse_version_output(&version_output)?;
+ let binary_path = container_dir.join(format!("gopls_{gopls_version}_go_{go_version}"));
+ fs::rename(&installed_binary_path, &binary_path).await?;
+
+ Ok(LanguageServerBinary {
+ path: binary_path.to_path_buf(),
+ arguments: server_binary_arguments(),
+ env: None,
+ })
+ }
}
async fn cached_server_binary(
@@ -24,6 +24,7 @@ use std::{
borrow::Cow,
env::consts,
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
str::FromStr,
sync::Arc,
@@ -176,56 +177,64 @@ impl LspInstaller for JsonLspAdapter {
})
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
-
- if should_install_language_server {
- None
- } else {
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
+
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
- let latest_version = latest_version.to_string();
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
&[(Self::PACKAGE_NAME, latest_version.as_str())],
)
.await?;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
async fn cached_server_binary(
@@ -478,51 +487,55 @@ impl LspInstaller for NodeVersionAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: GitHubLspBinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let version = &latest_version;
- let destination_path = container_dir.join(format!(
- "{}-{}{}",
- Self::SERVER_NAME,
- version.name,
- std::env::consts::EXE_SUFFIX
- ));
- let destination_container_path =
- container_dir.join(format!("{}-{}-tmp", Self::SERVER_NAME, version.name));
- if fs::metadata(&destination_path).await.is_err() {
- let mut response = delegate
- .http_client()
- .get(&version.url, Default::default(), true)
- .await
- .context("downloading release")?;
- if version.url.ends_with(".zip") {
- extract_zip(&destination_container_path, response.body_mut()).await?;
- } else if version.url.ends_with(".tar.gz") {
- let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));
- let archive = Archive::new(decompressed_bytes);
- archive.unpack(&destination_container_path).await?;
- }
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+
+ async move {
+ let version = &latest_version;
+ let destination_path = container_dir.join(format!(
+ "{}-{}{}",
+ Self::SERVER_NAME,
+ version.name,
+ std::env::consts::EXE_SUFFIX
+ ));
+ let destination_container_path =
+ container_dir.join(format!("{}-{}-tmp", Self::SERVER_NAME, version.name));
+ if fs::metadata(&destination_path).await.is_err() {
+ let mut response = delegate
+ .http_client()
+ .get(&version.url, Default::default(), true)
+ .await
+ .context("downloading release")?;
+ if version.url.ends_with(".zip") {
+ extract_zip(&destination_container_path, response.body_mut()).await?;
+ } else if version.url.ends_with(".tar.gz") {
+ let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));
+ let archive = Archive::new(decompressed_bytes);
+ archive.unpack(&destination_container_path).await?;
+ }
- fs::copy(
- destination_container_path.join(format!(
- "{}{}",
- Self::SERVER_NAME,
- std::env::consts::EXE_SUFFIX
- )),
- &destination_path,
- )
- .await?;
- remove_matching(&container_dir, |entry| entry != destination_path).await;
+ fs::copy(
+ destination_container_path.join(format!(
+ "{}{}",
+ Self::SERVER_NAME,
+ std::env::consts::EXE_SUFFIX
+ )),
+ &destination_path,
+ )
+ .await?;
+ remove_matching(&container_dir, |entry| entry != destination_path).await;
+ }
+ Ok(LanguageServerBinary {
+ path: destination_path,
+ env: None,
+ arguments: Default::default(),
+ })
}
- Ok(LanguageServerBinary {
- path: destination_path,
- env: None,
- arguments: Default::default(),
- })
}
async fn cached_server_binary(
@@ -1,5 +1,5 @@
+use anyhow::Result;
use anyhow::{Context as _, ensure};
-use anyhow::{Result, anyhow};
use async_trait::async_trait;
use collections::HashMap;
use futures::future::BoxFuture;
@@ -45,6 +45,7 @@ use std::str::FromStr;
use std::{
borrow::Cow,
fmt::Write,
+ future::Future,
path::{Path, PathBuf},
sync::Arc,
};
@@ -447,92 +448,98 @@ impl LspInstaller for TyLspAdapter {
None
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let GitHubLspBinaryVersion {
- name,
- url,
- digest: expected_digest,
- } = latest_version;
- let destination_path = container_dir.join(format!("ty-{name}"));
-
- async_fs::create_dir_all(&destination_path).await?;
-
- let server_path = match Self::GITHUB_ASSET_KIND {
- AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path
- .join(Self::build_asset_name()?.0)
- .join("ty"),
- AssetKind::Zip => destination_path.clone().join("ty.exe"),
- };
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
- let binary = LanguageServerBinary {
- path: server_path.clone(),
- env: None,
- arguments: vec!["server".into()],
- };
+ async move {
+ let GitHubLspBinaryVersion {
+ name,
+ url,
+ digest: expected_digest,
+ } = latest_version;
+ let destination_path = container_dir.join(format!("ty-{name}"));
- let metadata_path = destination_path.with_extension("metadata");
- let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
- .await
- .ok();
- if let Some(metadata) = metadata {
- let validity_check = async || {
- delegate
- .try_exec(LanguageServerBinary {
- path: server_path.clone(),
- arguments: vec!["--version".into()],
- env: None,
- })
- .await
- .inspect_err(|err| {
- log::warn!("Unable to run {server_path:?} asset, redownloading: {err:#}",)
- })
+ async_fs::create_dir_all(&destination_path).await?;
+
+ let server_path = match Self::GITHUB_ASSET_KIND {
+ AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path
+ .join(Self::build_asset_name()?.0)
+ .join("ty"),
+ AssetKind::Zip => destination_path.clone().join("ty.exe"),
};
- if let (Some(actual_digest), Some(expected_digest)) =
- (&metadata.digest, &expected_digest)
- {
- if actual_digest == expected_digest {
- if validity_check().await.is_ok() {
- return Ok(binary);
+
+ let binary = LanguageServerBinary {
+ path: server_path.clone(),
+ env: None,
+ arguments: vec!["server".into()],
+ };
+
+ let metadata_path = destination_path.with_extension("metadata");
+ let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
+ .await
+ .ok();
+ if let Some(metadata) = metadata {
+ let validity_check = async || {
+ delegate
+ .try_exec(LanguageServerBinary {
+ path: server_path.clone(),
+ arguments: vec!["--version".into()],
+ env: None,
+ })
+ .await
+ .inspect_err(|err| {
+ log::warn!(
+ "Unable to run {server_path:?} asset, redownloading: {err:#}",
+ )
+ })
+ };
+ if let (Some(actual_digest), Some(expected_digest)) =
+ (&metadata.digest, &expected_digest)
+ {
+ if actual_digest == expected_digest {
+ if validity_check().await.is_ok() {
+ return Ok(binary);
+ }
+ } else {
+ log::info!(
+ "SHA-256 mismatch for {destination_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
+ );
}
- } else {
- log::info!(
- "SHA-256 mismatch for {destination_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
- );
+ } else if validity_check().await.is_ok() {
+ return Ok(binary);
}
- } else if validity_check().await.is_ok() {
- return Ok(binary);
}
- }
- download_server_binary(
- &*delegate.http_client(),
- &url,
- expected_digest.as_deref(),
- &destination_path,
- Self::GITHUB_ASSET_KIND,
- )
- .await?;
- make_file_executable(&server_path).await?;
- remove_matching(&container_dir, |path| path != destination_path).await;
- GithubBinaryMetadata::write_to_file(
- &GithubBinaryMetadata {
- metadata_version: 1,
- digest: expected_digest,
- },
- &metadata_path,
- )
- .await?;
+ download_server_binary(
+ &*delegate.http_client(),
+ &url,
+ expected_digest.as_deref(),
+ &destination_path,
+ Self::GITHUB_ASSET_KIND,
+ )
+ .await?;
+ make_file_executable(&server_path).await?;
+ remove_matching(&container_dir, |path| path != destination_path).await;
+ GithubBinaryMetadata::write_to_file(
+ &GithubBinaryMetadata {
+ metadata_version: 1,
+ digest: expected_digest,
+ },
+ &metadata_path,
+ )
+ .await?;
- Ok(LanguageServerBinary {
- path: server_path,
- env: None,
- arguments: vec!["server".into()],
- })
+ Ok(LanguageServerBinary {
+ path: server_path,
+ env: None,
+ arguments: vec!["server".into()],
+ })
+ }
}
async fn cached_server_binary(
@@ -777,57 +784,67 @@ impl LspInstaller for PyrightLspAdapter {
}
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(Self::SERVER_PATH);
- let latest_version = latest_version.to_string();
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+ let node = self.node.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir.join(Self::SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
&[(Self::SERVER_NAME.as_ref(), latest_version.as_str())],
)
.await?;
- let env = delegate.shell_env().await;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: Some(env),
- arguments: vec![server_path.into(), "--stdio".into()],
- })
+ let env = delegate.shell_env().await;
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: Some(env),
+ arguments: vec![server_path.into(), "--stdio".into()],
+ })
+ }
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(Self::SERVER_PATH);
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::SERVER_NAME.as_ref(),
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
-
- if should_install_language_server {
- None
- } else {
- let env = delegate.shell_env().await;
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: Some(env),
- arguments: vec![server_path.into(), "--stdio".into()],
- })
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
+
+ async move {
+ let server_path = container_dir.join(Self::SERVER_PATH);
+
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::SERVER_NAME.as_ref(),
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ let env = delegate.shell_env().await;
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: Some(env),
+ arguments: vec![server_path.into(), "--stdio".into()],
+ })
+ }
}
}
@@ -1949,46 +1966,50 @@ impl LspInstaller for PyLspAdapter {
Ok(())
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
_: (),
_: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let venv = self.base_venv(delegate).await.map_err(|e| anyhow!(e))?;
- let pip_path = venv.join(BINARY_DIR).join("pip3");
- ensure!(
- util::command::new_command(pip_path.as_path())
- .arg("install")
- .arg("python-lsp-server[all]")
- .arg("--upgrade")
- .output()
- .await?
- .status
- .success(),
- "python-lsp-server[all] installation failed"
- );
- ensure!(
- util::command::new_command(pip_path)
- .arg("install")
- .arg("pylsp-mypy")
- .arg("--upgrade")
- .output()
- .await?
- .status
- .success(),
- "pylsp-mypy installation failed"
- );
- let pylsp = venv.join(BINARY_DIR).join("pylsp");
- ensure!(
- delegate.which(pylsp.as_os_str()).await.is_some(),
- "pylsp installation was incomplete"
- );
- Ok(LanguageServerBinary {
- path: pylsp,
- env: None,
- arguments: vec![],
- })
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+
+ async move {
+ let venv = Self::ensure_venv(delegate.as_ref()).await?;
+ let pip_path = venv.join(BINARY_DIR).join("pip3");
+ ensure!(
+ util::command::new_command(pip_path.as_path())
+ .arg("install")
+ .arg("python-lsp-server[all]")
+ .arg("--upgrade")
+ .output()
+ .await?
+ .status
+ .success(),
+ "python-lsp-server[all] installation failed"
+ );
+ ensure!(
+ util::command::new_command(pip_path)
+ .arg("install")
+ .arg("pylsp-mypy")
+ .arg("--upgrade")
+ .output()
+ .await?
+ .status
+ .success(),
+ "pylsp-mypy installation failed"
+ );
+ let pylsp = venv.join(BINARY_DIR).join("pylsp");
+ ensure!(
+ delegate.which(pylsp.as_os_str()).await.is_some(),
+ "pylsp installation was incomplete"
+ );
+ Ok(LanguageServerBinary {
+ path: pylsp,
+ env: None,
+ arguments: vec![],
+ })
+ }
}
async fn cached_server_binary(
@@ -2229,57 +2250,67 @@ impl LspInstaller for BasedPyrightLspAdapter {
}
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(Self::SERVER_PATH);
- let latest_version = latest_version.to_string();
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+ let node = self.node.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir.join(Self::SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
&[(Self::SERVER_NAME.as_ref(), latest_version.as_str())],
)
.await?;
- let env = delegate.shell_env().await;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: Some(env),
- arguments: vec![server_path.into(), "--stdio".into()],
- })
+ let env = delegate.shell_env().await;
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: Some(env),
+ arguments: vec![server_path.into(), "--stdio".into()],
+ })
+ }
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(Self::SERVER_PATH);
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::SERVER_NAME.as_ref(),
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
-
- if should_install_language_server {
- None
- } else {
- let env = delegate.shell_env().await;
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: Some(env),
- arguments: vec![server_path.into(), "--stdio".into()],
- })
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
+
+ async move {
+ let server_path = container_dir.join(Self::SERVER_PATH);
+
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::SERVER_NAME.as_ref(),
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ let env = delegate.shell_env().await;
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: Some(env),
+ arguments: vec![server_path.into(), "--stdio".into()],
+ })
+ }
}
}
@@ -2566,89 +2597,95 @@ impl LspInstaller for RuffLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: GitHubLspBinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let GitHubLspBinaryVersion {
- name,
- url,
- digest: expected_digest,
- } = latest_version;
- let destination_path = container_dir.join(format!("ruff-{name}"));
- let server_path = match Self::GITHUB_ASSET_KIND {
- AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path
- .join(Self::build_asset_name()?.0)
- .join("ruff"),
- AssetKind::Zip => destination_path.clone().join("ruff.exe"),
- };
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
- let binary = LanguageServerBinary {
- path: server_path.clone(),
- env: None,
- arguments: vec!["server".into()],
- };
+ async move {
+ let GitHubLspBinaryVersion {
+ name,
+ url,
+ digest: expected_digest,
+ } = latest_version;
+ let destination_path = container_dir.join(format!("ruff-{name}"));
+ let server_path = match Self::GITHUB_ASSET_KIND {
+ AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path
+ .join(Self::build_asset_name()?.0)
+ .join("ruff"),
+ AssetKind::Zip => destination_path.clone().join("ruff.exe"),
+ };
- let metadata_path = destination_path.with_extension("metadata");
- let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
- .await
- .ok();
- if let Some(metadata) = metadata {
- let validity_check = async || {
- delegate
- .try_exec(LanguageServerBinary {
- path: server_path.clone(),
- arguments: vec!["--version".into()],
- env: None,
- })
- .await
- .inspect_err(|err| {
- log::warn!("Unable to run {server_path:?} asset, redownloading: {err:#}",)
- })
+ let binary = LanguageServerBinary {
+ path: server_path.clone(),
+ env: None,
+ arguments: vec!["server".into()],
};
- if let (Some(actual_digest), Some(expected_digest)) =
- (&metadata.digest, &expected_digest)
- {
- if actual_digest == expected_digest {
- if validity_check().await.is_ok() {
- return Ok(binary);
+
+ let metadata_path = destination_path.with_extension("metadata");
+ let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
+ .await
+ .ok();
+ if let Some(metadata) = metadata {
+ let validity_check = async || {
+ delegate
+ .try_exec(LanguageServerBinary {
+ path: server_path.clone(),
+ arguments: vec!["--version".into()],
+ env: None,
+ })
+ .await
+ .inspect_err(|err| {
+ log::warn!(
+ "Unable to run {server_path:?} asset, redownloading: {err:#}",
+ )
+ })
+ };
+ if let (Some(actual_digest), Some(expected_digest)) =
+ (&metadata.digest, &expected_digest)
+ {
+ if actual_digest == expected_digest {
+ if validity_check().await.is_ok() {
+ return Ok(binary);
+ }
+ } else {
+ log::info!(
+ "SHA-256 mismatch for {destination_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
+ );
}
- } else {
- log::info!(
- "SHA-256 mismatch for {destination_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
- );
+ } else if validity_check().await.is_ok() {
+ return Ok(binary);
}
- } else if validity_check().await.is_ok() {
- return Ok(binary);
}
- }
- download_server_binary(
- &*delegate.http_client(),
- &url,
- expected_digest.as_deref(),
- &destination_path,
- Self::GITHUB_ASSET_KIND,
- )
- .await?;
- make_file_executable(&server_path).await?;
- remove_matching(&container_dir, |path| path != destination_path).await;
- GithubBinaryMetadata::write_to_file(
- &GithubBinaryMetadata {
- metadata_version: 1,
- digest: expected_digest,
- },
- &metadata_path,
- )
- .await?;
+ download_server_binary(
+ &*delegate.http_client(),
+ &url,
+ expected_digest.as_deref(),
+ &destination_path,
+ Self::GITHUB_ASSET_KIND,
+ )
+ .await?;
+ make_file_executable(&server_path).await?;
+ remove_matching(&container_dir, |path| path != destination_path).await;
+ GithubBinaryMetadata::write_to_file(
+ &GithubBinaryMetadata {
+ metadata_version: 1,
+ digest: expected_digest,
+ },
+ &metadata_path,
+ )
+ .await?;
- Ok(LanguageServerBinary {
- path: server_path,
- env: None,
- arguments: vec!["server".into()],
- })
+ Ok(LanguageServerBinary {
+ path: server_path,
+ env: None,
+ arguments: vec!["server".into()],
+ })
+ }
}
async fn cached_server_binary(
@@ -19,6 +19,7 @@ use smallvec::SmallVec;
use smol::fs::{self};
use std::cmp::Reverse;
use std::fmt::Display;
+use std::future::Future;
use std::ops::Range;
use std::{
borrow::Cow,
@@ -729,87 +730,93 @@ impl LspInstaller for RustLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
version: GitHubLspBinaryVersion,
container_dir: PathBuf,
- delegate: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let GitHubLspBinaryVersion {
- name,
- url,
- digest: expected_digest,
- } = version;
- let destination_path = container_dir.join(format!("rust-analyzer-{name}"));
- let server_path = match Self::GITHUB_ASSET_KIND {
- AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path.clone(), // Tar and gzip extract in place.
- AssetKind::Zip => destination_path.clone().join("rust-analyzer.exe"), // zip contains a .exe
- };
+ delegate: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let delegate = delegate.clone();
- let binary = LanguageServerBinary {
- path: server_path.clone(),
- env: None,
- arguments: Default::default(),
- };
+ async move {
+ let GitHubLspBinaryVersion {
+ name,
+ url,
+ digest: expected_digest,
+ } = version;
+ let destination_path = container_dir.join(format!("rust-analyzer-{name}"));
+ let server_path = match Self::GITHUB_ASSET_KIND {
+ AssetKind::TarGz | AssetKind::TarBz2 | AssetKind::Gz => destination_path.clone(), // Tar and gzip extract in place.
+ AssetKind::Zip => destination_path.clone().join("rust-analyzer.exe"), // zip contains a .exe
+ };
- let metadata_path = destination_path.with_extension("metadata");
- let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
- .await
- .ok();
- if let Some(metadata) = metadata {
- let validity_check = async || {
- delegate
- .try_exec(LanguageServerBinary {
- path: server_path.clone(),
- arguments: vec!["--version".into()],
- env: None,
- })
- .await
- .inspect_err(|err| {
- log::warn!("Unable to run {server_path:?} asset, redownloading: {err:#}",)
- })
+ let binary = LanguageServerBinary {
+ path: server_path.clone(),
+ env: None,
+ arguments: Default::default(),
};
- if let (Some(actual_digest), Some(expected_digest)) =
- (&metadata.digest, &expected_digest)
- {
- if actual_digest == expected_digest {
- if validity_check().await.is_ok() {
- return Ok(binary);
+
+ let metadata_path = destination_path.with_extension("metadata");
+ let metadata = GithubBinaryMetadata::read_from_file(&metadata_path)
+ .await
+ .ok();
+ if let Some(metadata) = metadata {
+ let validity_check = async || {
+ delegate
+ .try_exec(LanguageServerBinary {
+ path: server_path.clone(),
+ arguments: vec!["--version".into()],
+ env: None,
+ })
+ .await
+ .inspect_err(|err| {
+ log::warn!(
+ "Unable to run {server_path:?} asset, redownloading: {err:#}",
+ )
+ })
+ };
+ if let (Some(actual_digest), Some(expected_digest)) =
+ (&metadata.digest, &expected_digest)
+ {
+ if actual_digest == expected_digest {
+ if validity_check().await.is_ok() {
+ return Ok(binary);
+ }
+ } else {
+ log::info!(
+ "SHA-256 mismatch for {destination_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
+ );
}
- } else {
- log::info!(
- "SHA-256 mismatch for {destination_path:?} asset, downloading new asset. Expected: {expected_digest}, Got: {actual_digest}"
- );
+ } else if validity_check().await.is_ok() {
+ return Ok(binary);
}
- } else if validity_check().await.is_ok() {
- return Ok(binary);
}
- }
- download_server_binary(
- &*delegate.http_client(),
- &url,
- expected_digest.as_deref(),
- &destination_path,
- Self::GITHUB_ASSET_KIND,
- )
- .await?;
- make_file_executable(&server_path).await?;
- remove_matching(&container_dir, |path| path != destination_path).await;
- GithubBinaryMetadata::write_to_file(
- &GithubBinaryMetadata {
- metadata_version: 1,
- digest: expected_digest,
- },
- &metadata_path,
- )
- .await?;
+ download_server_binary(
+ &*delegate.http_client(),
+ &url,
+ expected_digest.as_deref(),
+ &destination_path,
+ Self::GITHUB_ASSET_KIND,
+ )
+ .await?;
+ make_file_executable(&server_path).await?;
+ remove_matching(&container_dir, |path| path != destination_path).await;
+ GithubBinaryMetadata::write_to_file(
+ &GithubBinaryMetadata {
+ metadata_version: 1,
+ digest: expected_digest,
+ },
+ &metadata_path,
+ )
+ .await?;
- Ok(LanguageServerBinary {
- path: server_path,
- env: None,
- arguments: Default::default(),
- })
+ Ok(LanguageServerBinary {
+ path: server_path,
+ env: None,
+ arguments: Default::default(),
+ })
+ }
}
async fn cached_server_binary(
@@ -10,6 +10,7 @@ use semver::Version;
use serde_json::{Value, json};
use std::{
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
sync::Arc,
};
@@ -69,55 +70,63 @@ impl LspInstaller for TailwindLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
- let latest_version = latest_version.to_string();
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
&[(Self::PACKAGE_NAME, latest_version.as_str())],
)
.await?;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
-
- if should_install_language_server {
- None
- } else {
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
+
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
}
@@ -9,6 +9,7 @@ use semver::Version;
use serde_json::json;
use std::{
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
sync::Arc,
};
@@ -65,55 +66,63 @@ impl LspInstaller for TailwindCssLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
- let latest_version = latest_version.to_string();
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
&[(Self::PACKAGE_NAME, latest_version.as_str())],
)
.await?;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
-
- if should_install_language_server {
- None
- } else {
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
+
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
}
@@ -18,6 +18,7 @@ use smol::lock::RwLock;
use std::{
borrow::Cow,
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
sync::{Arc, LazyLock},
};
@@ -669,76 +670,80 @@ impl LspInstaller for TypeScriptLspAdapter {
})
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(Self::NEW_SERVER_PATH);
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let typescript_version = version.typescript_version.clone();
+ let server_version = version.server_version.clone();
+ let container_dir = container_dir.clone();
+
+ async move {
+ let server_path = container_dir.join(Self::NEW_SERVER_PATH);
+
+ if node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&typescript_version),
+ )
+ .await
+ {
+ return None;
+ }
- if self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(&version.typescript_version),
- )
- .await
- {
- return None;
- }
+ if node
+ .should_install_npm_package(
+ Self::SERVER_PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&server_version),
+ )
+ .await
+ {
+ return None;
+ }
- if self
- .node
- .should_install_npm_package(
- Self::SERVER_PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(&version.server_version),
- )
- .await
- {
- return None;
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: None,
+ arguments: typescript_server_binary_arguments(&server_path),
+ })
}
-
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: None,
- arguments: typescript_server_binary_arguments(&server_path),
- })
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(Self::NEW_SERVER_PATH);
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+
+ async move {
+ let server_path = container_dir.join(Self::NEW_SERVER_PATH);
+ let typescript_version = latest_version.typescript_version.to_string();
+ let server_version = latest_version.server_version.to_string();
- self.node
- .npm_install_packages(
+ node.npm_install_packages(
&container_dir,
&[
- (
- Self::PACKAGE_NAME,
- &latest_version.typescript_version.to_string(),
- ),
- (
- Self::SERVER_PACKAGE_NAME,
- &latest_version.server_version.to_string(),
- ),
+ (Self::PACKAGE_NAME, typescript_version.as_str()),
+ (Self::SERVER_PACKAGE_NAME, server_version.as_str()),
],
)
.await?;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: typescript_server_binary_arguments(&server_path),
- })
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: typescript_server_binary_arguments(&server_path),
+ })
+ }
}
async fn cached_server_binary(
@@ -15,6 +15,7 @@ use serde_json::json;
use settings::update_settings_file;
use std::{
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
sync::{Arc, LazyLock},
};
@@ -123,54 +124,56 @@ impl LspInstaller for VtslsLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(Self::SERVER_PATH);
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+
+ async move {
+ let server_path = container_dir.join(Self::SERVER_PATH);
+
+ let typescript_version = latest_version.typescript_version.to_string();
+ let server_version = latest_version.server_version.to_string();
+
+ let mut packages_to_install = Vec::new();
+
+ if node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&latest_version.server_version),
+ )
+ .await
+ {
+ packages_to_install.push((Self::PACKAGE_NAME, server_version.as_str()));
+ }
- let typescript_version = latest_version.typescript_version.to_string();
- let server_version = latest_version.server_version.to_string();
+ if node
+ .should_install_npm_package(
+ Self::TYPESCRIPT_PACKAGE_NAME,
+ &container_dir.join(Self::TYPESCRIPT_TSDK_PATH),
+ &container_dir,
+ VersionStrategy::Latest(&latest_version.typescript_version),
+ )
+ .await
+ {
+ packages_to_install
+ .push((Self::TYPESCRIPT_PACKAGE_NAME, typescript_version.as_str()));
+ }
- let mut packages_to_install = Vec::new();
+ node.npm_install_packages(&container_dir, &packages_to_install)
+ .await?;
- if self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- &container_dir,
- VersionStrategy::Latest(&latest_version.server_version),
- )
- .await
- {
- packages_to_install.push((Self::PACKAGE_NAME, server_version.as_str()));
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: typescript_server_binary_arguments(&server_path),
+ })
}
-
- if self
- .node
- .should_install_npm_package(
- Self::TYPESCRIPT_PACKAGE_NAME,
- &container_dir.join(Self::TYPESCRIPT_TSDK_PATH),
- &container_dir,
- VersionStrategy::Latest(&latest_version.typescript_version),
- )
- .await
- {
- packages_to_install.push((Self::TYPESCRIPT_PACKAGE_NAME, typescript_version.as_str()));
- }
-
- self.node
- .npm_install_packages(&container_dir, &packages_to_install)
- .await?;
-
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: typescript_server_binary_arguments(&server_path),
- })
}
async fn cached_server_binary(
@@ -12,6 +12,7 @@ use serde_json::Value;
use settings::{Settings, SettingsLocation};
use std::{
ffi::OsString,
+ future::Future,
path::{Path, PathBuf},
sync::Arc,
};
@@ -65,54 +66,63 @@ impl LspInstaller for YamlLspAdapter {
})
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
latest_version: Self::BinaryVersion,
container_dir: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
- self.node
- .npm_install_packages(
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+ let latest_version = latest_version.to_string();
+
+ node.npm_install_packages(
&container_dir,
- &[(Self::PACKAGE_NAME, &latest_version.to_string())],
+ &[(Self::PACKAGE_NAME, latest_version.as_str())],
)
.await?;
- Ok(LanguageServerBinary {
- path: self.node.binary_path().await?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ Ok(LanguageServerBinary {
+ path: node.binary_path().await?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
- async fn check_if_version_installed(
+ fn check_if_version_installed(
&self,
version: &Self::BinaryVersion,
container_dir: &PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Option<LanguageServerBinary> {
- let server_path = container_dir.join(SERVER_PATH);
-
- let should_install_language_server = self
- .node
- .should_install_npm_package(
- Self::PACKAGE_NAME,
- &server_path,
- container_dir,
- VersionStrategy::Latest(version),
- )
- .await;
-
- if should_install_language_server {
- None
- } else {
- Some(LanguageServerBinary {
- path: self.node.binary_path().await.ok()?,
- env: None,
- arguments: server_binary_arguments(&server_path),
- })
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Option<LanguageServerBinary>> + use<> {
+ let node = self.node.clone();
+ let version = version.clone();
+ let container_dir = container_dir.clone();
+
+ async move {
+ let server_path = container_dir.join(SERVER_PATH);
+
+ let should_install_language_server = node
+ .should_install_npm_package(
+ Self::PACKAGE_NAME,
+ &server_path,
+ &container_dir,
+ VersionStrategy::Latest(&version),
+ )
+ .await;
+
+ if should_install_language_server {
+ None
+ } else {
+ Some(LanguageServerBinary {
+ path: node.binary_path().await.ok()?,
+ env: None,
+ arguments: server_binary_arguments(&server_path),
+ })
+ }
}
}
@@ -14349,13 +14349,13 @@ impl LspInstaller for SshLspAdapter {
anyhow::bail!("SshLspAdapter does not support fetch_latest_server_version")
}
- async fn fetch_server_binary(
+ fn fetch_server_binary(
&self,
_: (),
_: PathBuf,
- _: &dyn LspAdapterDelegate,
- ) -> Result<LanguageServerBinary> {
- anyhow::bail!("SshLspAdapter does not support fetch_server_binary")
+ _: &Arc<dyn LspAdapterDelegate>,
+ ) -> impl Send + Future<Output = Result<LanguageServerBinary>> + use<> {
+ async { anyhow::bail!("SshLspAdapter does not support fetch_server_binary") }
}
}