about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-28 22:34:08 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2025-05-28 22:37:08 +0200
commit0527f027e8eb5000d3725d3ceb6156e36aeb7b7a (patch)
tree1d912a509f85a03415c0c3f99cbe99f8b0cd6a2f
parentcb678b94c332548e3c3cefc22637929004c975d6 (diff)
downloadrust-0527f027e8eb5000d3725d3ceb6156e36aeb7b7a.tar.gz
rust-0527f027e8eb5000d3725d3ceb6156e36aeb7b7a.zip
Add `eslint` as part of tidy run
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/rustdoc_js.rs91
3 files changed, 94 insertions, 0 deletions
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index ca45f8bb84b..e8a12d56335 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 48122129b01..671d796dba9 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<String> = 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 00000000000..73a654f51e6
--- /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<String> {
+    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<String> {
+    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);
+}