tidy/extra_checks/
rustdoc_js.rs1use std::ffi::OsStr;
4use std::io;
5use std::path::{Path, PathBuf};
6use std::process::{Child, Command};
7
8use build_helper::npm;
9use ignore::DirEntry;
10
11use crate::walk::walk_no_read;
12
13fn node_module_bin(outdir: &Path, name: &str) -> PathBuf {
14 outdir.join("node_modules/.bin").join(name)
15}
16
17fn spawn_cmd(cmd: &mut Command) -> Result<Child, io::Error> {
18 cmd.spawn().map_err(|err| {
19 eprintln!("unable to run {cmd:?} due to {err:?}");
20 err
21 })
22}
23
24pub(super) fn has_tool(outdir: &Path, name: &str) -> bool {
25 let bin_path = node_module_bin(outdir, name);
26 Command::new(bin_path).arg("--version").status().is_ok()
27}
28
29pub(super) fn npm_install(root_path: &Path, outdir: &Path, npm: &Path) -> Result<(), super::Error> {
31 npm::install(root_path, outdir, npm)?;
32 Ok(())
33}
34
35fn rustdoc_js_files(librustdoc_path: &Path) -> Vec<PathBuf> {
36 let mut files = Vec::new();
37 walk_no_read(
38 &[&librustdoc_path.join("html/static/js")],
39 |path, is_dir| is_dir || path.extension().is_none_or(|ext| ext != OsStr::new("js")),
40 &mut |path: &DirEntry| {
41 files.push(path.path().into());
42 },
43 );
44 return files;
45}
46
47fn run_eslint(
48 outdir: &Path,
49 args: &[PathBuf],
50 config_folder: PathBuf,
51 bless: bool,
52) -> Result<(), super::Error> {
53 let mut cmd = Command::new(node_module_bin(outdir, "eslint"));
54 if bless {
55 cmd.arg("--fix");
56 }
57 cmd.arg("-c").arg(config_folder.join(".eslintrc.js")).args(args);
58 let mut child = spawn_cmd(&mut cmd)?;
59 match child.wait() {
60 Ok(exit_status) => {
61 if exit_status.success() {
62 return Ok(());
63 }
64 Err(super::Error::FailedCheck("eslint"))
65 }
66 Err(error) => Err(super::Error::Generic(format!("eslint command failed: {error:?}"))),
67 }
68}
69
70pub(super) fn lint(
71 outdir: &Path,
72 librustdoc_path: &Path,
73 tools_path: &Path,
74 bless: bool,
75) -> Result<(), super::Error> {
76 let files_to_check = rustdoc_js_files(librustdoc_path);
77 println!("Running eslint on rustdoc JS files");
78 run_eslint(outdir, &files_to_check, librustdoc_path.join("html/static"), bless)?;
79
80 run_eslint(
81 outdir,
82 &[tools_path.join("rustdoc-js/tester.js")],
83 tools_path.join("rustdoc-js"),
84 bless,
85 )?;
86 Ok(())
87}
88
89pub(super) fn typecheck(outdir: &Path, librustdoc_path: &Path) -> Result<(), super::Error> {
90 let mut child = spawn_cmd(
92 Command::new(node_module_bin(outdir, "tsc"))
93 .arg("-p")
94 .arg(librustdoc_path.join("html/static/js/tsconfig.json")),
95 )?;
96 match child.wait() {
97 Ok(exit_status) => {
98 if exit_status.success() {
99 return Ok(());
100 }
101 Err(super::Error::FailedCheck("tsc"))
102 }
103 Err(error) => Err(super::Error::Generic(format!("tsc command failed: {error:?}"))),
104 }
105}
106
107pub(super) fn es_check(outdir: &Path, librustdoc_path: &Path) -> Result<(), super::Error> {
108 let files_to_check = rustdoc_js_files(librustdoc_path);
109 let mut cmd = Command::new(node_module_bin(outdir, "es-check"));
110 cmd.arg("es2019");
111 for f in files_to_check {
112 cmd.arg(f);
113 }
114 match spawn_cmd(&mut cmd)?.wait() {
115 Ok(exit_status) => {
116 if exit_status.success() {
117 return Ok(());
118 }
119 Err(super::Error::FailedCheck("es-check"))
120 }
121 Err(error) => Err(super::Error::Generic(format!("es-check command failed: {error:?}"))),
122 }
123}