pylsp: Prefer version from user venv (#21069)

Closes #ISSUE

Release Notes:

- pylsp will now use version installed in user venv, if one is
available.
This commit is contained in:
Piotr Osiewicz 2024-11-25 00:54:47 +01:00 committed by GitHub
parent 20bffaf93f
commit e85848a695
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 37 additions and 23 deletions

View file

@ -201,13 +201,14 @@ impl CachedLspAdapter {
pub async fn get_language_server_command( pub async fn get_language_server_command(
self: Arc<Self>, self: Arc<Self>,
delegate: Arc<dyn LspAdapterDelegate>, delegate: Arc<dyn LspAdapterDelegate>,
toolchains: Arc<dyn LanguageToolchainStore>,
binary_options: LanguageServerBinaryOptions, binary_options: LanguageServerBinaryOptions,
cx: &mut AsyncAppContext, cx: &mut AsyncAppContext,
) -> Result<LanguageServerBinary> { ) -> Result<LanguageServerBinary> {
let cached_binary = self.cached_binary.lock().await; let cached_binary = self.cached_binary.lock().await;
self.adapter self.adapter
.clone() .clone()
.get_language_server_command(delegate, binary_options, cached_binary, cx) .get_language_server_command(delegate, toolchains, binary_options, cached_binary, cx)
.await .await
} }
@ -281,6 +282,7 @@ pub trait LspAdapter: 'static + Send + Sync {
fn get_language_server_command<'a>( fn get_language_server_command<'a>(
self: Arc<Self>, self: Arc<Self>,
delegate: Arc<dyn LspAdapterDelegate>, delegate: Arc<dyn LspAdapterDelegate>,
toolchains: Arc<dyn LanguageToolchainStore>,
binary_options: LanguageServerBinaryOptions, binary_options: LanguageServerBinaryOptions,
mut cached_binary: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>, mut cached_binary: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
cx: &'a mut AsyncAppContext, cx: &'a mut AsyncAppContext,
@ -298,7 +300,7 @@ pub trait LspAdapter: 'static + Send + Sync {
// because we don't want to download and overwrite our global one // because we don't want to download and overwrite our global one
// for each worktree we might have open. // for each worktree we might have open.
if binary_options.allow_path_lookup { if binary_options.allow_path_lookup {
if let Some(binary) = self.check_if_user_installed(delegate.as_ref(), cx).await { if let Some(binary) = self.check_if_user_installed(delegate.as_ref(), toolchains, cx).await {
log::info!( log::info!(
"found user-installed language server for {}. path: {:?}, arguments: {:?}", "found user-installed language server for {}. path: {:?}, arguments: {:?}",
self.name().0, self.name().0,
@ -357,6 +359,7 @@ pub trait LspAdapter: 'static + Send + Sync {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
_: &dyn LspAdapterDelegate, _: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
None None
@ -1665,6 +1668,7 @@ impl LspAdapter for FakeLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
_: &dyn LspAdapterDelegate, _: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
Some(self.language_server_binary.clone()) Some(self.language_server_binary.clone())
@ -1673,6 +1677,7 @@ impl LspAdapter for FakeLspAdapter {
fn get_language_server_command<'a>( fn get_language_server_command<'a>(
self: Arc<Self>, self: Arc<Self>,
_: Arc<dyn LspAdapterDelegate>, _: Arc<dyn LspAdapterDelegate>,
_: Arc<dyn LanguageToolchainStore>,
_: LanguageServerBinaryOptions, _: LanguageServerBinaryOptions,
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>, _: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
_: &'a mut AsyncAppContext, _: &'a mut AsyncAppContext,

View file

@ -115,6 +115,7 @@ impl LspAdapter for ExtensionLspAdapter {
fn get_language_server_command<'a>( fn get_language_server_command<'a>(
self: Arc<Self>, self: Arc<Self>,
delegate: Arc<dyn LspAdapterDelegate>, delegate: Arc<dyn LspAdapterDelegate>,
_: Arc<dyn LanguageToolchainStore>,
_: LanguageServerBinaryOptions, _: LanguageServerBinaryOptions,
_: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>, _: futures::lock::MutexGuard<'a, Option<LanguageServerBinary>>,
_: &'a mut AsyncAppContext, _: &'a mut AsyncAppContext,

View file

@ -24,6 +24,7 @@ impl super::LspAdapter for CLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
delegate: &dyn LspAdapterDelegate, delegate: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?; let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;

View file

@ -67,6 +67,7 @@ impl super::LspAdapter for GoLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
delegate: &dyn LspAdapterDelegate, delegate: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
let path = delegate.which(Self::SERVER_NAME.as_ref()).await?; let path = delegate.which(Self::SERVER_NAME.as_ref()).await?;

View file

@ -79,6 +79,7 @@ impl LspAdapter for PythonLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
delegate: &dyn LspAdapterDelegate, delegate: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
let node = delegate.which("node".as_ref()).await?; let node = delegate.which("node".as_ref()).await?;
@ -753,33 +754,29 @@ impl LspAdapter for PyLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
_: &dyn LspAdapterDelegate, delegate: &dyn LspAdapterDelegate,
_: &AsyncAppContext, toolchains: Arc<dyn LanguageToolchainStore>,
cx: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
// We don't support user-provided pylsp, as global packages are discouraged in Python ecosystem. let venv = toolchains
None .active_toolchain(
delegate.worktree_id(),
LanguageName::new("Python"),
&mut cx.clone(),
)
.await?;
let pylsp_path = Path::new(venv.path.as_ref()).parent()?.join("pylsp");
pylsp_path.exists().then(|| LanguageServerBinary {
path: venv.path.to_string().into(),
arguments: vec![pylsp_path.into()],
env: None,
})
} }
async fn fetch_latest_server_version( async fn fetch_latest_server_version(
&self, &self,
_: &dyn LspAdapterDelegate, _: &dyn LspAdapterDelegate,
) -> Result<Box<dyn 'static + Any + Send>> { ) -> Result<Box<dyn 'static + Any + Send>> {
// let uri = "https://pypi.org/pypi/python-lsp-server/json";
// let mut root_manifest = delegate
// .http_client()
// .get(&uri, Default::default(), true)
// .await?;
// let mut body = Vec::new();
// root_manifest.body_mut().read_to_end(&mut body).await?;
// let as_str = String::from_utf8(body)?;
// let json = serde_json::Value::from_str(&as_str)?;
// let latest_version = json
// .get("info")
// .and_then(|info| info.get("version"))
// .and_then(|version| version.as_str().map(ToOwned::to_owned))
// .ok_or_else(|| {
// anyhow!("PyPI response did not contain version info for python-language-server")
// })?;
Ok(Box::new(()) as Box<_>) Ok(Box::new(()) as Box<_>)
} }

View file

@ -76,6 +76,7 @@ impl LspAdapter for RustLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
delegate: &dyn LspAdapterDelegate, delegate: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
let path = delegate.which("rust-analyzer".as_ref()).await?; let path = delegate.which("rust-analyzer".as_ref()).await?;

View file

@ -77,6 +77,7 @@ impl LspAdapter for VtslsLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
delegate: &dyn LspAdapterDelegate, delegate: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
let env = delegate.shell_env().await; let env = delegate.shell_env().await;

View file

@ -5523,10 +5523,16 @@ impl LspStore {
.unwrap_or_default(), .unwrap_or_default(),
allow_binary_download, allow_binary_download,
}; };
let toolchains = self.toolchain_store(cx);
cx.spawn(|_, mut cx| async move { cx.spawn(|_, mut cx| async move {
let binary_result = adapter let binary_result = adapter
.clone() .clone()
.get_language_server_command(delegate.clone(), lsp_binary_options, &mut cx) .get_language_server_command(
delegate.clone(),
toolchains,
lsp_binary_options,
&mut cx,
)
.await; .await;
delegate.update_status(adapter.name.clone(), LanguageServerBinaryStatus::None); delegate.update_status(adapter.name.clone(), LanguageServerBinaryStatus::None);
@ -7783,6 +7789,7 @@ impl LspAdapter for SshLspAdapter {
async fn check_if_user_installed( async fn check_if_user_installed(
&self, &self,
_: &dyn LspAdapterDelegate, _: &dyn LspAdapterDelegate,
_: Arc<dyn LanguageToolchainStore>,
_: &AsyncAppContext, _: &AsyncAppContext,
) -> Option<LanguageServerBinary> { ) -> Option<LanguageServerBinary> {
Some(self.binary.clone()) Some(self.binary.clone())