Skip to content

Commit e6d537a

Browse files
committed
tidy: refactor --extra-checks parsing
1 parent c83e217 commit e6d537a

File tree

1 file changed

+111
-14
lines changed

1 file changed

+111
-14
lines changed

src/tools/tidy/src/ext_tool_checks.rs

Lines changed: 111 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use std::ffi::OsStr;
2121
use std::path::{Path, PathBuf};
2222
use std::process::Command;
23+
use std::str::FromStr;
2324
use std::{fmt, fs, io};
2425

2526
const MIN_PY_REV: (u32, u32) = (3, 9);
@@ -61,25 +62,38 @@ fn check_impl(
6162

6263
// Split comma-separated args up
6364
let lint_args = match extra_checks {
64-
Some(s) => s.strip_prefix("--extra-checks=").unwrap().split(',').collect(),
65+
Some(s) => s
66+
.strip_prefix("--extra-checks=")
67+
.unwrap()
68+
.split(',')
69+
.map(|s| {
70+
if s == "spellcheck:fix" {
71+
eprintln!("warning: `spellcheck:fix` is no longer valid, use `--extra=check=spellcheck --bless`");
72+
}
73+
(ExtraCheckArg::from_str(s), s)
74+
})
75+
.filter_map(|(res, src)| match res {
76+
Ok(x) => Some(x),
77+
Err(err) => {
78+
eprintln!("warning: bad extra check argument {src:?}: {err:?}");
79+
None
80+
}
81+
})
82+
.collect(),
6583
None => vec![],
6684
};
6785

68-
if lint_args.contains(&"spellcheck:fix") {
69-
return Err(Error::Generic(
70-
"`spellcheck:fix` is no longer valid, use `--extra=check=spellcheck --bless`"
71-
.to_string(),
72-
));
86+
macro_rules! extra_check {
87+
($lang:ident, $kind:ident) => {
88+
lint_args.iter().any(|arg| arg.matches(ExtraCheckLang::$lang, ExtraCheckKind::$kind))
89+
};
7390
}
7491

75-
let python_all = lint_args.contains(&"py");
76-
let python_lint = lint_args.contains(&"py:lint") || python_all;
77-
let python_fmt = lint_args.contains(&"py:fmt") || python_all;
78-
let shell_all = lint_args.contains(&"shell");
79-
let shell_lint = lint_args.contains(&"shell:lint") || shell_all;
80-
let cpp_all = lint_args.contains(&"cpp");
81-
let cpp_fmt = lint_args.contains(&"cpp:fmt") || cpp_all;
82-
let spellcheck = lint_args.contains(&"spellcheck");
92+
let python_lint = extra_check!(Py, Lint);
93+
let python_fmt = extra_check!(Py, Fmt);
94+
let shell_lint = extra_check!(Shell, Lint);
95+
let cpp_fmt = extra_check!(Cpp, Fmt);
96+
let spellcheck = extra_check!(Spellcheck, None);
8397

8498
let mut py_path = None;
8599

@@ -638,3 +652,86 @@ impl From<io::Error> for Error {
638652
Self::Io(value)
639653
}
640654
}
655+
656+
#[derive(Debug)]
657+
enum ExtraCheckParseError {
658+
#[allow(dead_code, reason = "shown through Debug")]
659+
UnknownKind(String),
660+
#[allow(dead_code)]
661+
UnknownLang(String),
662+
/// Too many `:`
663+
TooManyParts,
664+
/// Tried to parse the empty string
665+
Empty,
666+
}
667+
668+
struct ExtraCheckArg {
669+
lang: ExtraCheckLang,
670+
/// None = run all extra checks for the given lang
671+
kind: Option<ExtraCheckKind>,
672+
}
673+
674+
impl ExtraCheckArg {
675+
fn matches(&self, lang: ExtraCheckLang, kind: ExtraCheckKind) -> bool {
676+
self.lang == lang && self.kind.map(|k| k == kind).unwrap_or(true)
677+
}
678+
}
679+
680+
impl FromStr for ExtraCheckArg {
681+
type Err = ExtraCheckParseError;
682+
683+
fn from_str(s: &str) -> Result<Self, Self::Err> {
684+
let mut parts = s.split(':');
685+
let Some(first) = parts.next() else {
686+
return Err(ExtraCheckParseError::Empty);
687+
};
688+
let second = parts.next();
689+
if parts.next().is_some() {
690+
return Err(ExtraCheckParseError::TooManyParts);
691+
}
692+
Ok(Self { lang: first.parse()?, kind: second.map(|s| s.parse()).transpose()? })
693+
}
694+
}
695+
696+
#[derive(PartialEq, Copy, Clone)]
697+
enum ExtraCheckLang {
698+
Py,
699+
Shell,
700+
Cpp,
701+
Spellcheck,
702+
}
703+
704+
impl FromStr for ExtraCheckLang {
705+
type Err = ExtraCheckParseError;
706+
707+
fn from_str(s: &str) -> Result<Self, Self::Err> {
708+
Ok(match s {
709+
"py" => Self::Py,
710+
"shell" => Self::Shell,
711+
"cpp" => Self::Cpp,
712+
"spellcheck" => Self::Spellcheck,
713+
_ => return Err(ExtraCheckParseError::UnknownLang(s.to_string())),
714+
})
715+
}
716+
}
717+
718+
#[derive(PartialEq, Copy, Clone)]
719+
enum ExtraCheckKind {
720+
Lint,
721+
Fmt,
722+
/// Never parsed, but used as a placeholder for
723+
/// langs that never have a specific kind.
724+
None,
725+
}
726+
727+
impl FromStr for ExtraCheckKind {
728+
type Err = ExtraCheckParseError;
729+
730+
fn from_str(s: &str) -> Result<Self, Self::Err> {
731+
Ok(match s {
732+
"lint" => Self::Lint,
733+
"fmt" => Self::Fmt,
734+
_ => return Err(ExtraCheckParseError::UnknownKind(s.to_string())),
735+
})
736+
}
737+
}

0 commit comments

Comments
 (0)