|
20 | 20 | use std::ffi::OsStr;
|
21 | 21 | use std::path::{Path, PathBuf};
|
22 | 22 | use std::process::Command;
|
| 23 | +use std::str::FromStr; |
23 | 24 | use std::{fmt, fs, io};
|
24 | 25 |
|
25 | 26 | const MIN_PY_REV: (u32, u32) = (3, 9);
|
@@ -61,17 +62,32 @@ fn check_impl(
|
61 | 62 |
|
62 | 63 | // Split comma-separated args up
|
63 | 64 | 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| (ExtraCheckArg::from_str(s), s)) |
| 70 | + .filter_map(|(res, src)| match res { |
| 71 | + Ok(x) => Some(x), |
| 72 | + Err(err) => { |
| 73 | + eprintln!("warning: bad extra check argument {src:?}: {err:?}"); |
| 74 | + None |
| 75 | + } |
| 76 | + }) |
| 77 | + .collect(), |
65 | 78 | None => vec![],
|
66 | 79 | };
|
67 | 80 |
|
68 |
| - let python_all = lint_args.contains(&"py"); |
69 |
| - let python_lint = lint_args.contains(&"py:lint") || python_all; |
70 |
| - let python_fmt = lint_args.contains(&"py:fmt") || python_all; |
71 |
| - let shell_all = lint_args.contains(&"shell"); |
72 |
| - let shell_lint = lint_args.contains(&"shell:lint") || shell_all; |
73 |
| - let cpp_all = lint_args.contains(&"cpp"); |
74 |
| - let cpp_fmt = lint_args.contains(&"cpp:fmt") || cpp_all; |
| 81 | + macro_rules! extra_check { |
| 82 | + ($lang:ident, $kind:ident) => { |
| 83 | + lint_args.iter().any(|arg| arg.matches(ExtraCheckLang::$lang, ExtraCheckKind::$kind)) |
| 84 | + }; |
| 85 | + } |
| 86 | + |
| 87 | + let python_lint = extra_check!(Py, Lint); |
| 88 | + let python_fmt = extra_check!(Py, Fmt); |
| 89 | + let shell_lint = extra_check!(Shell, Lint); |
| 90 | + let cpp_fmt = extra_check!(Cpp, Fmt); |
75 | 91 |
|
76 | 92 | let mut py_path = None;
|
77 | 93 |
|
@@ -579,3 +595,81 @@ impl From<io::Error> for Error {
|
579 | 595 | Self::Io(value)
|
580 | 596 | }
|
581 | 597 | }
|
| 598 | + |
| 599 | +#[derive(Debug)] |
| 600 | +enum ExtraCheckParseError { |
| 601 | + #[allow(dead_code, reason = "shown through Debug")] |
| 602 | + UnknownKind(String), |
| 603 | + #[allow(dead_code)] |
| 604 | + UnknownLang(String), |
| 605 | + /// Too many `:` |
| 606 | + TooManyParts, |
| 607 | + /// Tried to parse the empty string |
| 608 | + Empty, |
| 609 | +} |
| 610 | + |
| 611 | +struct ExtraCheckArg { |
| 612 | + lang: ExtraCheckLang, |
| 613 | + /// None = run all extra checks for the given lang |
| 614 | + kind: Option<ExtraCheckKind>, |
| 615 | +} |
| 616 | + |
| 617 | +impl ExtraCheckArg { |
| 618 | + fn matches(&self, lang: ExtraCheckLang, kind: ExtraCheckKind) -> bool { |
| 619 | + self.lang == lang && self.kind.map(|k| k == kind).unwrap_or(true) |
| 620 | + } |
| 621 | +} |
| 622 | + |
| 623 | +impl FromStr for ExtraCheckArg { |
| 624 | + type Err = ExtraCheckParseError; |
| 625 | + |
| 626 | + fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 627 | + let mut parts = s.split(':'); |
| 628 | + let Some(first) = parts.next() else { |
| 629 | + return Err(ExtraCheckParseError::Empty); |
| 630 | + }; |
| 631 | + let second = parts.next(); |
| 632 | + if parts.next().is_some() { |
| 633 | + return Err(ExtraCheckParseError::TooManyParts); |
| 634 | + } |
| 635 | + Ok(Self { lang: first.parse()?, kind: second.map(|s| s.parse()).transpose()? }) |
| 636 | + } |
| 637 | +} |
| 638 | + |
| 639 | +#[derive(PartialEq, Copy, Clone)] |
| 640 | +enum ExtraCheckLang { |
| 641 | + Py, |
| 642 | + Shell, |
| 643 | + Cpp, |
| 644 | +} |
| 645 | + |
| 646 | +impl FromStr for ExtraCheckLang { |
| 647 | + type Err = ExtraCheckParseError; |
| 648 | + |
| 649 | + fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 650 | + Ok(match s { |
| 651 | + "py" => Self::Py, |
| 652 | + "shell" => Self::Shell, |
| 653 | + "cpp" => Self::Cpp, |
| 654 | + _ => return Err(ExtraCheckParseError::UnknownLang(s.to_string())), |
| 655 | + }) |
| 656 | + } |
| 657 | +} |
| 658 | + |
| 659 | +#[derive(PartialEq, Copy, Clone)] |
| 660 | +enum ExtraCheckKind { |
| 661 | + Lint, |
| 662 | + Fmt, |
| 663 | +} |
| 664 | + |
| 665 | +impl FromStr for ExtraCheckKind { |
| 666 | + type Err = ExtraCheckParseError; |
| 667 | + |
| 668 | + fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 669 | + Ok(match s { |
| 670 | + "lint" => Self::Lint, |
| 671 | + "fmt" => Self::Fmt, |
| 672 | + _ => return Err(ExtraCheckParseError::UnknownKind(s.to_string())), |
| 673 | + }) |
| 674 | + } |
| 675 | +} |
0 commit comments