Fix lang servers status set to Downloading when checking version (#22292)

This message has confused me many times too: we printed the status as
"Downloading" when we were only checking whether we need to install a
given version of a language server.

This fixes the issue for Node-based language servers where we had the
same check in all implementations.

Closes  #22241

Release Notes:

- Fixed some language servers reporting status as "Downloading..." when
only a version check was being done.
This commit is contained in:
Thorsten Ball 2024-12-20 17:59:10 +01:00 committed by GitHub
parent 8a858fee7c
commit d824baeece
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 235 additions and 92 deletions

View file

@ -385,6 +385,15 @@ pub trait LspAdapter: 'static + Send + Sync {
None None
} }
async fn check_if_version_installed(
&self,
_version: &(dyn 'static + Send + Any),
_container_dir: &PathBuf,
_delegate: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
None
}
async fn fetch_server_binary( async fn fetch_server_binary(
&self, &self,
latest_version: Box<dyn 'static + Send + Any>, latest_version: Box<dyn 'static + Send + Any>,
@ -516,14 +525,23 @@ async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>
.fetch_latest_server_version(delegate.as_ref()) .fetch_latest_server_version(delegate.as_ref())
.await?; .await?;
log::info!("downloading language server {:?}", name.0); if let Some(binary) = adapter
delegate.update_status(adapter.name(), LanguageServerBinaryStatus::Downloading); .check_if_version_installed(latest_version.as_ref(), &container_dir, delegate.as_ref())
let binary = adapter .await
.fetch_server_binary(latest_version, container_dir, delegate.as_ref()) {
.await; log::info!("language server {:?} is already installed", name.0);
delegate.update_status(name.clone(), LanguageServerBinaryStatus::None);
Ok(binary)
} else {
log::info!("downloading language server {:?}", name.0);
delegate.update_status(adapter.name(), LanguageServerBinaryStatus::Downloading);
let binary = adapter
.fetch_server_binary(latest_version, container_dir, delegate.as_ref())
.await;
delegate.update_status(name.clone(), LanguageServerBinaryStatus::None); delegate.update_status(name.clone(), LanguageServerBinaryStatus::None);
binary binary
}
} }
#[derive(Clone, Debug, Default, PartialEq, Eq)] #[derive(Clone, Debug, Default, PartialEq, Eq)]

View file

@ -26,6 +26,7 @@ pub struct CssLspAdapter {
} }
impl CssLspAdapter { impl CssLspAdapter {
const PACKAGE_NAME: &str = "vscode-langservers-extracted";
pub fn new(node: NodeRuntime) -> Self { pub fn new(node: NodeRuntime) -> Self {
CssLspAdapter { node } CssLspAdapter { node }
} }
@ -56,18 +57,13 @@ impl LspAdapter for CssLspAdapter {
) -> Result<LanguageServerBinary> { ) -> Result<LanguageServerBinary> {
let latest_version = latest_version.downcast::<String>().unwrap(); let latest_version = latest_version.downcast::<String>().unwrap();
let server_path = container_dir.join(SERVER_PATH); let server_path = container_dir.join(SERVER_PATH);
let package_name = "vscode-langservers-extracted";
let should_install_language_server = self self.node
.node .npm_install_packages(
.should_install_npm_package(package_name, &server_path, &container_dir, &latest_version) &container_dir,
.await; &[(Self::PACKAGE_NAME, latest_version.as_str())],
)
if should_install_language_server { .await?;
self.node
.npm_install_packages(&container_dir, &[(package_name, latest_version.as_str())])
.await?;
}
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path: self.node.binary_path().await?, path: self.node.binary_path().await?,
@ -76,6 +72,31 @@ impl LspAdapter for CssLspAdapter {
}) })
} }
async fn check_if_version_installed(
&self,
version: &(dyn 'static + Send + Any),
container_dir: &PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
let version = version.downcast_ref::<String>().unwrap();
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, &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),
})
}
}
async fn cached_server_binary( async fn cached_server_binary(
&self, &self,
container_dir: PathBuf, container_dir: PathBuf,

View file

@ -64,6 +64,8 @@ pub struct JsonLspAdapter {
} }
impl JsonLspAdapter { impl JsonLspAdapter {
const PACKAGE_NAME: &str = "vscode-langservers-extracted";
pub fn new(node: NodeRuntime, languages: Arc<LanguageRegistry>) -> Self { pub fn new(node: NodeRuntime, languages: Arc<LanguageRegistry>) -> Self {
Self { Self {
node, node,
@ -142,11 +144,36 @@ impl LspAdapter for JsonLspAdapter {
) -> Result<Box<dyn 'static + Send + Any>> { ) -> Result<Box<dyn 'static + Send + Any>> {
Ok(Box::new( Ok(Box::new(
self.node self.node
.npm_package_latest_version("vscode-langservers-extracted") .npm_package_latest_version(Self::PACKAGE_NAME)
.await?, .await?,
) as Box<_>) ) as Box<_>)
} }
async fn check_if_version_installed(
&self,
version: &(dyn 'static + Send + Any),
container_dir: &PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
let version = version.downcast_ref::<String>().unwrap();
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, &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),
})
}
}
async fn fetch_server_binary( async fn fetch_server_binary(
&self, &self,
latest_version: Box<dyn 'static + Send + Any>, latest_version: Box<dyn 'static + Send + Any>,
@ -155,18 +182,13 @@ impl LspAdapter for JsonLspAdapter {
) -> Result<LanguageServerBinary> { ) -> Result<LanguageServerBinary> {
let latest_version = latest_version.downcast::<String>().unwrap(); let latest_version = latest_version.downcast::<String>().unwrap();
let server_path = container_dir.join(SERVER_PATH); let server_path = container_dir.join(SERVER_PATH);
let package_name = "vscode-langservers-extracted";
let should_install_language_server = self self.node
.node .npm_install_packages(
.should_install_npm_package(package_name, &server_path, &container_dir, &latest_version) &container_dir,
.await; &[(Self::PACKAGE_NAME, latest_version.as_str())],
)
if should_install_language_server { .await?;
self.node
.npm_install_packages(&container_dir, &[(package_name, latest_version.as_str())])
.await?;
}
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path: self.node.binary_path().await?, path: self.node.binary_path().await?,

View file

@ -117,24 +117,12 @@ impl LspAdapter for PythonLspAdapter {
let latest_version = latest_version.downcast::<String>().unwrap(); let latest_version = latest_version.downcast::<String>().unwrap();
let server_path = container_dir.join(SERVER_PATH); let server_path = container_dir.join(SERVER_PATH);
let should_install_language_server = self self.node
.node .npm_install_packages(
.should_install_npm_package(
Self::SERVER_NAME.as_ref(),
&server_path,
&container_dir, &container_dir,
&latest_version, &[(Self::SERVER_NAME.as_ref(), latest_version.as_str())],
) )
.await; .await?;
if should_install_language_server {
self.node
.npm_install_packages(
&container_dir,
&[(Self::SERVER_NAME.as_ref(), latest_version.as_str())],
)
.await?;
}
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path: self.node.binary_path().await?, path: self.node.binary_path().await?,
@ -143,6 +131,36 @@ impl LspAdapter for PythonLspAdapter {
}) })
} }
async fn check_if_version_installed(
&self,
version: &(dyn 'static + Send + Any),
container_dir: &PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
let version = version.downcast_ref::<String>().unwrap();
let server_path = container_dir.join(SERVER_PATH);
let should_install_language_server = self
.node
.should_install_npm_package(
Self::SERVER_NAME.as_ref(),
&server_path,
&container_dir,
&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),
})
}
}
async fn cached_server_binary( async fn cached_server_binary(
&self, &self,
container_dir: PathBuf, container_dir: PathBuf,

View file

@ -34,6 +34,7 @@ pub struct TailwindLspAdapter {
impl TailwindLspAdapter { impl TailwindLspAdapter {
const SERVER_NAME: LanguageServerName = const SERVER_NAME: LanguageServerName =
LanguageServerName::new_static("tailwindcss-language-server"); LanguageServerName::new_static("tailwindcss-language-server");
const PACKAGE_NAME: &str = "@tailwindcss/language-server";
pub fn new(node: NodeRuntime) -> Self { pub fn new(node: NodeRuntime) -> Self {
TailwindLspAdapter { node } TailwindLspAdapter { node }
@ -52,7 +53,7 @@ impl LspAdapter for TailwindLspAdapter {
) -> Result<Box<dyn 'static + Any + Send>> { ) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new( Ok(Box::new(
self.node self.node
.npm_package_latest_version("@tailwindcss/language-server") .npm_package_latest_version(Self::PACKAGE_NAME)
.await?, .await?,
) as Box<_>) ) as Box<_>)
} }
@ -65,18 +66,13 @@ impl LspAdapter for TailwindLspAdapter {
) -> Result<LanguageServerBinary> { ) -> Result<LanguageServerBinary> {
let latest_version = latest_version.downcast::<String>().unwrap(); let latest_version = latest_version.downcast::<String>().unwrap();
let server_path = container_dir.join(SERVER_PATH); let server_path = container_dir.join(SERVER_PATH);
let package_name = "@tailwindcss/language-server";
let should_install_language_server = self self.node
.node .npm_install_packages(
.should_install_npm_package(package_name, &server_path, &container_dir, &latest_version) &container_dir,
.await; &[(Self::PACKAGE_NAME, latest_version.as_str())],
)
if should_install_language_server { .await?;
self.node
.npm_install_packages(&container_dir, &[(package_name, latest_version.as_str())])
.await?;
}
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path: self.node.binary_path().await?, path: self.node.binary_path().await?,
@ -85,6 +81,31 @@ impl LspAdapter for TailwindLspAdapter {
}) })
} }
async fn check_if_version_installed(
&self,
version: &(dyn 'static + Send + Any),
container_dir: &PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
let version = version.downcast_ref::<String>().unwrap();
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, &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),
})
}
}
async fn cached_server_binary( async fn cached_server_binary(
&self, &self,
container_dir: PathBuf, container_dir: PathBuf,

View file

@ -73,6 +73,7 @@ impl TypeScriptLspAdapter {
const NEW_SERVER_PATH: &'static str = "node_modules/typescript-language-server/lib/cli.mjs"; const NEW_SERVER_PATH: &'static str = "node_modules/typescript-language-server/lib/cli.mjs";
const SERVER_NAME: LanguageServerName = const SERVER_NAME: LanguageServerName =
LanguageServerName::new_static("typescript-language-server"); LanguageServerName::new_static("typescript-language-server");
const PACKAGE_NAME: &str = "typescript";
pub fn new(node: NodeRuntime) -> Self { pub fn new(node: NodeRuntime) -> Self {
TypeScriptLspAdapter { node } TypeScriptLspAdapter { node }
} }
@ -114,6 +115,37 @@ impl LspAdapter for TypeScriptLspAdapter {
}) as Box<_>) }) as Box<_>)
} }
async fn check_if_version_installed(
&self,
version: &(dyn 'static + Send + Any),
container_dir: &PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
println!("{:?}", version.type_id());
let version = version.downcast_ref::<TypeScriptVersions>().unwrap();
let server_path = container_dir.join(Self::NEW_SERVER_PATH);
let should_install_language_server = self
.node
.should_install_npm_package(
Self::PACKAGE_NAME,
&server_path,
&container_dir,
version.typescript_version.as_str(),
)
.await;
if should_install_language_server {
None
} else {
Some(LanguageServerBinary {
path: self.node.binary_path().await.ok()?,
env: None,
arguments: typescript_server_binary_arguments(&server_path),
})
}
}
async fn fetch_server_binary( async fn fetch_server_binary(
&self, &self,
latest_version: Box<dyn 'static + Send + Any>, latest_version: Box<dyn 'static + Send + Any>,
@ -122,32 +154,22 @@ impl LspAdapter for TypeScriptLspAdapter {
) -> Result<LanguageServerBinary> { ) -> Result<LanguageServerBinary> {
let latest_version = latest_version.downcast::<TypeScriptVersions>().unwrap(); let latest_version = latest_version.downcast::<TypeScriptVersions>().unwrap();
let server_path = container_dir.join(Self::NEW_SERVER_PATH); let server_path = container_dir.join(Self::NEW_SERVER_PATH);
let package_name = "typescript";
let should_install_language_server = self self.node
.node .npm_install_packages(
.should_install_npm_package(
package_name,
&server_path,
&container_dir, &container_dir,
latest_version.typescript_version.as_str(), &[
(
Self::PACKAGE_NAME,
latest_version.typescript_version.as_str(),
),
(
"typescript-language-server",
latest_version.server_version.as_str(),
),
],
) )
.await; .await?;
if should_install_language_server {
self.node
.npm_install_packages(
&container_dir,
&[
(package_name, latest_version.typescript_version.as_str()),
(
"typescript-language-server",
latest_version.server_version.as_str(),
),
],
)
.await?;
}
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path: self.node.binary_path().await?, path: self.node.binary_path().await?,

View file

@ -31,6 +31,7 @@ pub struct YamlLspAdapter {
impl YamlLspAdapter { impl YamlLspAdapter {
const SERVER_NAME: LanguageServerName = LanguageServerName::new_static("yaml-language-server"); const SERVER_NAME: LanguageServerName = LanguageServerName::new_static("yaml-language-server");
const PACKAGE_NAME: &str = "yaml-language-server";
pub fn new(node: NodeRuntime) -> Self { pub fn new(node: NodeRuntime) -> Self {
YamlLspAdapter { node } YamlLspAdapter { node }
} }
@ -61,18 +62,13 @@ impl LspAdapter for YamlLspAdapter {
) -> Result<LanguageServerBinary> { ) -> Result<LanguageServerBinary> {
let latest_version = latest_version.downcast::<String>().unwrap(); let latest_version = latest_version.downcast::<String>().unwrap();
let server_path = container_dir.join(SERVER_PATH); let server_path = container_dir.join(SERVER_PATH);
let package_name = "yaml-language-server";
let should_install_language_server = self self.node
.node .npm_install_packages(
.should_install_npm_package(package_name, &server_path, &container_dir, &latest_version) &container_dir,
.await; &[(Self::PACKAGE_NAME, latest_version.as_str())],
)
if should_install_language_server { .await?;
self.node
.npm_install_packages(&container_dir, &[(package_name, latest_version.as_str())])
.await?;
}
Ok(LanguageServerBinary { Ok(LanguageServerBinary {
path: self.node.binary_path().await?, path: self.node.binary_path().await?,
@ -81,6 +77,31 @@ impl LspAdapter for YamlLspAdapter {
}) })
} }
async fn check_if_version_installed(
&self,
version: &(dyn 'static + Send + Any),
container_dir: &PathBuf,
_: &dyn LspAdapterDelegate,
) -> Option<LanguageServerBinary> {
let version = version.downcast_ref::<String>().unwrap();
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, &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),
})
}
}
async fn cached_server_binary( async fn cached_server_binary(
&self, &self,
container_dir: PathBuf, container_dir: PathBuf,