From 0527f027e8eb5000d3725d3ceb6156e36aeb7b7a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 28 May 2025 22:34:08 +0200 Subject: [PATCH] Add `eslint` as part of tidy run --- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 2 + src/tools/tidy/src/rustdoc_js.rs | 91 ++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 src/tools/tidy/src/rustdoc_js.rs diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index ca45f8bb84ba..e8a12d563358 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -82,6 +82,7 @@ pub mod mir_opt_tests; pub mod pal; pub mod rustdoc_css_themes; pub mod rustdoc_gui_tests; +pub mod rustdoc_js; pub mod rustdoc_templates; pub mod style; pub mod target_policy; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 48122129b017..671d796dba95 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -35,6 +35,7 @@ fn main() { let library_path = root_path.join("library"); let compiler_path = root_path.join("compiler"); let librustdoc_path = src_path.join("librustdoc"); + let tools_path = src_path.join("tools"); let crashes_path = tests_path.join("crashes"); let args: Vec = env::args().skip(1).collect(); @@ -108,6 +109,7 @@ fn main() { check!(rustdoc_gui_tests, &tests_path); check!(rustdoc_css_themes, &librustdoc_path); check!(rustdoc_templates, &librustdoc_path); + check!(rustdoc_js, &librustdoc_path, &tools_path); check!(known_bug, &crashes_path); check!(unknown_revision, &tests_path); diff --git a/src/tools/tidy/src/rustdoc_js.rs b/src/tools/tidy/src/rustdoc_js.rs new file mode 100644 index 000000000000..73a654f51e6d --- /dev/null +++ b/src/tools/tidy/src/rustdoc_js.rs @@ -0,0 +1,91 @@ +//! Tidy check to ensure that rustdoc templates didn't forget a `{# #}` to strip extra whitespace +//! characters. + +use std::ffi::OsStr; +use std::path::{Path, PathBuf}; +use std::process::Command; + +use ignore::DirEntry; + +use crate::walk::walk_no_read; + +fn run_eslint(args: &[PathBuf], config_folder: PathBuf, bad: &mut bool) { + let mut child = match Command::new("npx") + .arg("eslint") + .arg("-c") + .arg(config_folder.join(".eslintrc.js")) + .args(args) + .spawn() + { + Ok(child) => child, + Err(error) => { + *bad = true; + eprintln!("failed to run eslint: {error:?}"); + return; + } + }; + match child.wait() { + Ok(exit_status) => { + if exit_status.success() { + return; + } + eprintln!("eslint command failed"); + } + Err(error) => eprintln!("eslint command failed: {error:?}"), + } + *bad = true; +} + +fn get_eslint_version_inner(global: bool) -> Option { + let mut command = Command::new("npm"); + command.arg("list").arg("--parseable").arg("--long").arg("--depth=0"); + if global { + command.arg("--global"); + } + let output = command.output().ok()?; + let lines = String::from_utf8_lossy(&output.stdout); + lines.lines().find_map(|l| l.split(':').nth(1)?.strip_prefix("eslint@")).map(|v| v.to_owned()) +} + +fn get_eslint_version() -> Option { + get_eslint_version_inner(false).or_else(|| get_eslint_version_inner(true)) +} + +const ESLINT_VERSION: &str = "8.6.0"; + +pub fn check(librustdoc_path: &Path, tools_path: &Path, bad: &mut bool) { + match get_eslint_version() { + Some(version) => { + if version != ESLINT_VERSION { + *bad = true; + eprintln!( + "⚠️ Installed version of eslint (`{version}`) is different than the \ + one used in the CI (`{ESLINT_VERSION}`)", + ); + eprintln!( + "You can install this version using `npm update eslint` or by using \ + `npm install eslint@{ESLINT_VERSION}`", + ); + return; + } + } + None => { + eprintln!("`eslint` doesn't seem to be installed. Skipping tidy check for JS files."); + eprintln!("You can install it using `npm install eslint@{ESLINT_VERSION}`"); + return; + } + } + let mut files_to_check = Vec::new(); + walk_no_read( + &[&librustdoc_path.join("html/static/js")], + |path, is_dir| is_dir || !path.extension().is_some_and(|ext| ext == OsStr::new("js")), + &mut |path: &DirEntry| { + files_to_check.push(path.path().into()); + }, + ); + println!("Running eslint on rustdoc JS files"); + run_eslint(&files_to_check, librustdoc_path.join("html/static"), bad); + + run_eslint(&[tools_path.join("rustdoc-js/tester.js")], tools_path.join("rustdoc-js"), bad); + run_eslint(&[tools_path.join("rustdoc-gui/tester.js")], tools_path.join("rustdoc-gui"), bad); +}