1 //! Tidy check to verify the validity of long error diagnostic codes.
3 //! This ensures that error codes are used at most once and also prints out some
4 //! statistics about the error codes.
6 use crate::walk::{filter_dirs, walk};
7 use std::collections::HashMap;
10 pub fn check(path: &Path, bad: &mut bool) {
11 let mut map: HashMap<_, Vec<_>> = HashMap::new();
14 &mut |path| filter_dirs(path) || path.ends_with("src/test"),
15 &mut |entry, contents| {
16 let file = entry.path();
17 let filename = file.file_name().unwrap().to_string_lossy();
18 if filename != "error_codes.rs" {
22 // In the `register_long_diagnostics!` macro, entries look like this:
26 // <Long diagnostic message>
30 // and these long messages often have error codes themselves inside
31 // them, but we don't want to report duplicates in these cases. This
32 // variable keeps track of whether we're currently inside one of these
33 // long diagnostic messages.
34 let mut inside_long_diag = false;
35 for (num, line) in contents.lines().enumerate() {
37 inside_long_diag = !line.contains("\"##");
41 let mut search = line;
42 while let Some(i) = search.find('E') {
43 search = &search[i + 1..];
44 let code = if search.len() > 4 { search[..4].parse::<u32>() } else { continue };
45 let code = match code {
49 map.entry(code).or_default().push((file.to_owned(), num + 1, line.to_owned()));
53 inside_long_diag = line.contains("r##\"");
59 for (&code, entries) in map.iter() {
63 if entries.len() == 1 {
67 tidy_error!(bad, "duplicate error code: {}", code);
68 for &(ref file, line_num, ref line) in entries.iter() {
69 tidy_error!(bad, "{}:{}: {}", file.display(), line_num, line);
74 println!("* {} error codes", map.len());
75 println!("* highest error code: E{:04}", max);