]> git.lizzy.rs Git - rust.git/blob - tests/lint_message_convention.rs
Auto merge of #10149 - jyn514:duplicate-sysroot, r=flip1995
[rust.git] / tests / lint_message_convention.rs
1 #![feature(once_cell)]
2 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
3 #![warn(rust_2018_idioms, unused_lifetimes)]
4
5 use std::ffi::OsStr;
6 use std::path::PathBuf;
7 use std::sync::LazyLock;
8
9 use regex::RegexSet;
10
11 #[derive(Debug)]
12 struct Message {
13     path: PathBuf,
14     bad_lines: Vec<String>,
15 }
16
17 impl Message {
18     fn new(path: PathBuf) -> Self {
19         // we don't want the first letter after "error: ", "help: " ... to be capitalized
20         // also no punctuation (except for "?" ?) at the end of a line
21         static REGEX_SET: LazyLock<RegexSet> = LazyLock::new(|| {
22             RegexSet::new([
23                 r"error: [A-Z]",
24                 r"help: [A-Z]",
25                 r"warning: [A-Z]",
26                 r"note: [A-Z]",
27                 r"try this: [A-Z]",
28                 r"error: .*[.!]$",
29                 r"help: .*[.!]$",
30                 r"warning: .*[.!]$",
31                 r"note: .*[.!]$",
32                 r"try this: .*[.!]$",
33             ])
34             .unwrap()
35         });
36
37         // sometimes the first character is capitalized and it is legal (like in "C-like enum variants") or
38         // we want to ask a question ending in "?"
39         static EXCEPTIONS_SET: LazyLock<RegexSet> = LazyLock::new(|| {
40             RegexSet::new([
41                 r"\.\.\.$",
42                 r".*C-like enum variant discriminant is not portable to 32-bit targets",
43                 r".*Intel x86 assembly syntax used",
44                 r".*AT&T x86 assembly syntax used",
45                 r"note: Clippy version: .*",
46                 r"the compiler unexpectedly panicked. this is a bug.",
47             ])
48             .unwrap()
49         });
50
51         let content: String = std::fs::read_to_string(&path).unwrap();
52
53         let bad_lines = content
54             .lines()
55             .filter(|line| REGEX_SET.matches(line).matched_any())
56             // ignore exceptions
57             .filter(|line| !EXCEPTIONS_SET.matches(line).matched_any())
58             .map(ToOwned::to_owned)
59             .collect::<Vec<String>>();
60
61         Message { path, bad_lines }
62     }
63 }
64
65 #[test]
66 fn lint_message_convention() {
67     // disable the test inside the rustc test suite
68     if option_env!("RUSTC_TEST_SUITE").is_some() {
69         return;
70     }
71
72     // make sure that lint messages:
73     // * are not capitalized
74     // * don't have punctuation at the end of the last sentence
75
76     // these directories have interesting tests
77     let test_dirs = ["ui", "ui-cargo", "ui-internal", "ui-toml"]
78         .iter()
79         .map(PathBuf::from)
80         .map(|p| {
81             let base = PathBuf::from("tests");
82             base.join(p)
83         });
84
85     // gather all .stderr files
86     let tests = test_dirs
87         .flat_map(|dir| {
88             std::fs::read_dir(dir)
89                 .expect("failed to read dir")
90                 .map(|direntry| direntry.unwrap().path())
91         })
92         .filter(|file| matches!(file.extension().map(OsStr::to_str), Some(Some("stderr"))));
93
94     // get all files that have any "bad lines" in them
95     let bad_tests: Vec<Message> = tests
96         .map(Message::new)
97         .filter(|message| !message.bad_lines.is_empty())
98         .collect();
99
100     for message in &bad_tests {
101         eprintln!(
102             "error: the test '{}' contained the following nonconforming lines :",
103             message.path.display()
104         );
105         message.bad_lines.iter().for_each(|line| eprintln!("{line}"));
106         eprintln!("\n\n");
107     }
108
109     eprintln!(
110         "\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."
111     );
112     eprintln!("Check out the rustc-dev-guide for more information:");
113     eprintln!("https://rustc-dev-guide.rust-lang.org/diagnostics.html#diagnostic-structure\n\n\n");
114
115     assert!(bad_tests.is_empty());
116 }