From df2d025a07461b991ca6f51c6577b177dd77613f Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Fri, 22 Mar 2024 17:19:23 +0100 Subject: [PATCH] Update to vscode-eslint 2.4.4 & support flat config file extensions (#9708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This upgrades to vscode-eslint 2.4.4 to support flat configs, in multiple configuration files, ending in `.js`, `.cjs`, `.mjs`. We changed the code to not use the GitHub release because we actually don't need the artifacts of the release, we just need the source code, which we compile anyway. Fixes #7271. Release Notes: - Added support for ESLint flat config files. ([#7271](https://github.com/zed-industries/zed/issues/7271)). Co-authored-by: Kristján Oddsson --- crates/languages/src/typescript.rs | 28 ++++++------ crates/util/src/github.rs | 69 ++++++------------------------ 2 files changed, 27 insertions(+), 70 deletions(-) diff --git a/crates/languages/src/typescript.rs b/crates/languages/src/typescript.rs index b05a370a6cff8093f556c7c32c174a47a96e8c25..d8315de64e3f7f77c790e167da51fcf1dd6ea362 100644 --- a/crates/languages/src/typescript.rs +++ b/crates/languages/src/typescript.rs @@ -20,7 +20,7 @@ use std::{ use util::{ async_maybe, fs::remove_matching, - github::{github_release_with_tag, GitHubLspBinaryVersion}, + github::{build_tarball_url, GitHubLspBinaryVersion}, ResultExt, }; @@ -216,9 +216,14 @@ pub struct EsLintLspAdapter { } impl EsLintLspAdapter { + const CURRENT_VERSION: &'static str = "release/2.4.4"; + const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js"; const SERVER_NAME: &'static str = "eslint"; + const FLAT_CONFIG_FILE_NAMES: &'static [&'static str] = + &["eslint.config.js", "eslint.config.mjs", "eslint.config.cjs"]; + pub fn new(node: Arc) -> Self { EsLintLspAdapter { node } } @@ -255,6 +260,9 @@ impl LspAdapter for EsLintLspAdapter { } let node_path = eslint_user_settings.get("nodePath").unwrap_or(&Value::Null); + let use_flat_config = Self::FLAT_CONFIG_FILE_NAMES + .iter() + .any(|file| workspace_root.join(file).is_file()); json!({ "": { @@ -271,7 +279,7 @@ impl LspAdapter for EsLintLspAdapter { "problems": {}, "codeActionOnSave": code_action_on_save, "experimental": { - "useFlatConfig": workspace_root.join("eslint.config.js").is_file(), + "useFlatConfig": use_flat_config, }, } }) @@ -283,19 +291,13 @@ impl LspAdapter for EsLintLspAdapter { async fn fetch_latest_server_version( &self, - delegate: &dyn LspAdapterDelegate, + _delegate: &dyn LspAdapterDelegate, ) -> Result> { - // We're using this hardcoded release tag, because ESLint's API changed with - // >= 2.3 and we haven't upgraded yet. - let release = github_release_with_tag( - "microsoft/vscode-eslint", - "release/2.2.20-Insider", - delegate.http_client(), - ) - .await?; + let url = build_tarball_url("microsoft/vscode-eslint", Self::CURRENT_VERSION)?; + Ok(Box::new(GitHubLspBinaryVersion { - name: release.tag_name, - url: release.tarball_url, + name: Self::CURRENT_VERSION.into(), + url, })) } diff --git a/crates/util/src/github.rs b/crates/util/src/github.rs index 76891e1bd17217f715b2a77c1c42d5a87c9e9fbf..f6d768d0665d3fba94e63caa8ad3cac3384dbd03 100644 --- a/crates/util/src/github.rs +++ b/crates/util/src/github.rs @@ -76,78 +76,33 @@ pub async fn latest_github_release( .ok_or(anyhow!("Failed to find a release")) } -pub async fn github_release_with_tag( - repo_name_with_owner: &str, - tag: &str, - http: Arc, -) -> Result { - let url = build_tagged_release_url(repo_name_with_owner, tag)?; - let mut response = http - .get(&url, Default::default(), true) - .await - .with_context(|| format!("error fetching release {} of {}", tag, repo_name_with_owner))?; - - let mut body = Vec::new(); - response - .body_mut() - .read_to_end(&mut body) - .await - .with_context(|| { - format!( - "error reading response body for release {} of {}", - tag, repo_name_with_owner - ) - })?; - - if response.status().is_client_error() { - let text = String::from_utf8_lossy(body.as_slice()); - bail!( - "status error {}, response: {text:?}", - response.status().as_u16() - ); - } - - match serde_json::from_slice::(body.as_slice()) { - Ok(release) => Ok(release), - - Err(err) => { - log::error!("Error deserializing: {:?}", err); - log::error!( - "GitHub API response text: {:?}", - String::from_utf8_lossy(body.as_slice()) - ); - Err(anyhow!( - "error deserializing release {} of {}", - tag, - repo_name_with_owner - )) - } - } -} - -fn build_tagged_release_url(repo_name_with_owner: &str, tag: &str) -> Result { +pub fn build_tarball_url(repo_name_with_owner: &str, tag: &str) -> Result { let mut url = Url::parse(&format!( - "https://api.github.com/repos/{repo_name_with_owner}/releases/tags" + "https://github.com/{repo_name_with_owner}/archive/refs/tags", ))?; // We're pushing this here, because tags may contain `/` and other characters // that need to be escaped. + let tarball_filename = format!("{}.tar.gz", tag); url.path_segments_mut() .map_err(|_| anyhow!("cannot modify url path segments"))? - .push(tag); + .push(&tarball_filename); Ok(url.to_string()) } #[cfg(test)] mod tests { - use super::build_tagged_release_url; + use crate::github::build_tarball_url; #[test] - fn test_build_tagged_release_url() { - let tag = "release/2.2.20-Insider"; + fn test_build_tarball_url() { + let tag = "release/2.3.5"; let repo_name_with_owner = "microsoft/vscode-eslint"; - let have = build_tagged_release_url(repo_name_with_owner, tag).unwrap(); + let have = build_tarball_url(repo_name_with_owner, tag).unwrap(); - assert_eq!(have, "https://api.github.com/repos/microsoft/vscode-eslint/releases/tags/release%2F2.2.20-Insider"); + assert_eq!( + have, + "https://github.com/microsoft/vscode-eslint/archive/refs/tags/release%2F2.3.5.tar.gz" + ); } }