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