mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-22 12:43:18 +00:00
116 lines
3.7 KiB
Rust
116 lines
3.7 KiB
Rust
#![warn(rust_2018_idioms, unused_lifetimes)]
|
|
|
|
use std::ffi::OsStr;
|
|
use std::path::PathBuf;
|
|
use std::sync::LazyLock;
|
|
|
|
use regex::RegexSet;
|
|
|
|
#[derive(Debug)]
|
|
struct Message {
|
|
path: PathBuf,
|
|
bad_lines: Vec<String>,
|
|
}
|
|
|
|
impl Message {
|
|
fn new(path: PathBuf) -> Self {
|
|
// we don't want the first letter after "error: ", "help: " ... to be capitalized
|
|
// also no punctuation (except for "?" ?) at the end of a line
|
|
// Prefer "try" over "try this".
|
|
static REGEX_SET: LazyLock<RegexSet> = LazyLock::new(|| {
|
|
RegexSet::new([
|
|
"error: [A-Z]",
|
|
"help: [A-Z]",
|
|
"warning: [A-Z]",
|
|
"note: [A-Z]",
|
|
"try: [A-Z]",
|
|
"error: .*[.!]$",
|
|
"help: .*[.!]$",
|
|
"warning: .*[.!]$",
|
|
"note: .*[.!]$",
|
|
"try: .*[.!]$",
|
|
"try this",
|
|
])
|
|
.unwrap()
|
|
});
|
|
|
|
// sometimes the first character is capitalized and it is legal (like in "C-like enum variants") or
|
|
// we want to ask a question ending in "?"
|
|
static EXCEPTIONS_SET: LazyLock<RegexSet> = LazyLock::new(|| {
|
|
RegexSet::new([
|
|
r"\.\.\.$",
|
|
".*C-like enum variant discriminant is not portable to 32-bit targets",
|
|
".*Intel x86 assembly syntax used",
|
|
".*AT&T x86 assembly syntax used",
|
|
"note: Clippy version: .*",
|
|
"the compiler unexpectedly panicked. this is a bug.",
|
|
])
|
|
.unwrap()
|
|
});
|
|
|
|
let content: String = std::fs::read_to_string(&path).unwrap();
|
|
|
|
let bad_lines = content
|
|
.lines()
|
|
.filter(|line| REGEX_SET.matches(line).matched_any())
|
|
// ignore exceptions
|
|
.filter(|line| !EXCEPTIONS_SET.matches(line).matched_any())
|
|
.map(ToOwned::to_owned)
|
|
.collect::<Vec<String>>();
|
|
|
|
Message { path, bad_lines }
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn lint_message_convention() {
|
|
// disable the test inside the rustc test suite
|
|
if option_env!("RUSTC_TEST_SUITE").is_some() {
|
|
return;
|
|
}
|
|
|
|
// make sure that lint messages:
|
|
// * are not capitalized
|
|
// * don't have punctuation at the end of the last sentence
|
|
|
|
// these directories have interesting tests
|
|
let test_dirs = ["ui", "ui-cargo", "ui-internal", "ui-toml"]
|
|
.iter()
|
|
.map(PathBuf::from)
|
|
.map(|p| {
|
|
let base = PathBuf::from("tests");
|
|
base.join(p)
|
|
});
|
|
|
|
// gather all .stderr files
|
|
let tests = test_dirs
|
|
.flat_map(|dir| {
|
|
std::fs::read_dir(dir)
|
|
.expect("failed to read dir")
|
|
.map(|direntry| direntry.unwrap().path())
|
|
})
|
|
.filter(|file| matches!(file.extension().map(OsStr::to_str), Some(Some("stderr"))));
|
|
|
|
// get all files that have any "bad lines" in them
|
|
let bad_tests: Vec<Message> = tests
|
|
.map(Message::new)
|
|
.filter(|message| !message.bad_lines.is_empty())
|
|
.collect();
|
|
|
|
for message in &bad_tests {
|
|
eprintln!(
|
|
"error: the test '{}' contained the following nonconforming lines :",
|
|
message.path.display()
|
|
);
|
|
message.bad_lines.iter().for_each(|line| eprintln!("{line}"));
|
|
eprintln!("\n\n");
|
|
}
|
|
|
|
eprintln!(
|
|
"\n\n\nLint message should not start with a capital letter and should not have punctuation at the end of the message unless multiple sentences are needed."
|
|
);
|
|
eprintln!("Check out the rustc-dev-guide for more information:");
|
|
eprintln!("https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-structure\n\n\n");
|
|
|
|
assert!(bad_tests.is_empty());
|
|
}
|