Use rust-analyzer from path if possible (#12418)

Release Notes:

- Added support for looking up the `rust-analyzer` binary in `$PATH`. This allows using such tools as `asdf` and nix to configure per-folder rust installations. To enable this behavior, use the `path_lookup` key when configuring the `rust-analyzer` `binary`: `{"lsp": {"rust-analyzer": {"binary": {"path_lookup": true }}}}`.
This commit is contained in:
Stanislav Alekseev 2024-06-07 07:56:38 +03:00 committed by GitHub
parent 48581167b7
commit 07dbd2bce8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 83 additions and 51 deletions

View File

@ -35,12 +35,12 @@ impl super::LspAdapter for CLspAdapter {
.and_then(|s| s.binary.clone())
});
if let Ok(Some(BinarySettings {
path: Some(path),
arguments,
})) = configured_binary
{
Some(LanguageServerBinary {
match configured_binary {
Ok(Some(BinarySettings {
path: Some(path),
arguments,
..
})) => Some(LanguageServerBinary {
path: path.into(),
arguments: arguments
.unwrap_or_default()
@ -48,15 +48,20 @@ impl super::LspAdapter for CLspAdapter {
.map(|arg| arg.into())
.collect(),
env: None,
})
} else {
let env = delegate.shell_env().await;
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;
Some(LanguageServerBinary {
path,
arguments: vec![],
env: Some(env),
})
}),
Ok(Some(BinarySettings {
path_lookup: Some(false),
..
})) => None,
_ => {
let env = delegate.shell_env().await;
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;
Some(LanguageServerBinary {
path,
arguments: vec![],
env: Some(env),
})
}
}
}

View File

@ -78,12 +78,12 @@ impl super::LspAdapter for GoLspAdapter {
.and_then(|s| s.binary.clone())
});
if let Ok(Some(BinarySettings {
path: Some(path),
arguments,
})) = configured_binary
{
Some(LanguageServerBinary {
match configured_binary {
Ok(Some(BinarySettings {
path: Some(path),
arguments,
..
})) => Some(LanguageServerBinary {
path: path.into(),
arguments: arguments
.unwrap_or_default()
@ -91,15 +91,20 @@ impl super::LspAdapter for GoLspAdapter {
.map(|arg| arg.into())
.collect(),
env: None,
})
} else {
let env = delegate.shell_env().await;
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;
Some(LanguageServerBinary {
path,
arguments: server_binary_arguments(),
env: Some(env),
})
}),
Ok(Some(BinarySettings {
path_lookup: Some(false),
..
})) => None,
_ => {
let env = delegate.shell_env().await;
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;
Some(LanguageServerBinary {
path,
arguments: server_binary_arguments(),
env: Some(env),
})
}
}
}

View File

@ -7,7 +7,7 @@ use http::github::{latest_github_release, GitHubLspBinaryVersion};
pub use language::*;
use lazy_static::lazy_static;
use lsp::LanguageServerBinary;
use project::project_settings::ProjectSettings;
use project::project_settings::{BinarySettings, ProjectSettings};
use regex::Regex;
use settings::Settings;
use smol::fs::{self, File};
@ -35,29 +35,50 @@ impl LspAdapter for RustLspAdapter {
async fn check_if_user_installed(
&self,
_delegate: &dyn LspAdapterDelegate,
delegate: &dyn LspAdapterDelegate,
cx: &AsyncAppContext,
) -> Option<LanguageServerBinary> {
let binary = cx
.update(|cx| {
ProjectSettings::get_global(cx)
.lsp
.get(Self::SERVER_NAME)
.and_then(|s| s.binary.clone())
})
.ok()??;
let configured_binary = cx.update(|cx| {
ProjectSettings::get_global(cx)
.lsp
.get(Self::SERVER_NAME)
.and_then(|s| s.binary.clone())
});
let path = binary.path?;
Some(LanguageServerBinary {
path: path.into(),
arguments: binary
.arguments
.unwrap_or_default()
.iter()
.map(|arg| arg.into())
.collect(),
env: None,
})
match configured_binary {
Ok(Some(BinarySettings {
path,
arguments,
path_lookup,
})) => {
let (path, env) = match (path, path_lookup) {
(Some(path), lookup) => {
if lookup.is_some() {
log::warn!(
"Both `path` and `path_lookup` are set, ignoring `path_lookup`"
);
}
(Some(path.into()), None)
}
(None, Some(true)) => {
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;
let env = delegate.shell_env().await;
(Some(path), Some(env))
}
(None, Some(false)) | (None, None) => (None, None),
};
path.map(|path| LanguageServerBinary {
path,
arguments: arguments
.unwrap_or_default()
.iter()
.map(|arg| arg.into())
.collect(),
env,
})
}
_ => None,
}
}
async fn fetch_latest_server_version(

View File

@ -94,6 +94,7 @@ const fn true_value() -> bool {
pub struct BinarySettings {
pub path: Option<String>,
pub arguments: Option<Vec<String>>,
pub path_lookup: Option<bool>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]