]> git.lizzy.rs Git - rust.git/blob - src/tools/tidy/src/errors.rs
Use the new Entry::or_default method where possible.
[rust.git] / src / tools / tidy / src / errors.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Tidy check to verify the validity of long error diagnostic codes.
12 //!
13 //! This ensures that error codes are used at most once and also prints out some
14 //! statistics about the error codes.
15
16 use std::collections::HashMap;
17 use std::fs::File;
18 use std::io::prelude::*;
19 use std::path::Path;
20
21 pub fn check(path: &Path, bad: &mut bool) {
22     let mut contents = String::new();
23     let mut map: HashMap<_, Vec<_>> = HashMap::new();
24     super::walk(path,
25                 &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
26                 &mut |file| {
27         let filename = file.file_name().unwrap().to_string_lossy();
28         if filename != "diagnostics.rs" && filename != "diagnostic_list.rs" {
29             return
30         }
31
32         contents.truncate(0);
33         t!(t!(File::open(file)).read_to_string(&mut contents));
34
35         // In the register_long_diagnostics! macro, entries look like this:
36         //
37         // EXXXX: r##"
38         // <Long diagnostic message>
39         // "##,
40         //
41         // and these long messages often have error codes themselves inside
42         // them, but we don't want to report duplicates in these cases. This
43         // variable keeps track of whether we're currently inside one of these
44         // long diagnostic messages.
45         let mut inside_long_diag = false;
46         for (num, line) in contents.lines().enumerate() {
47             if inside_long_diag {
48                 inside_long_diag = !line.contains("\"##");
49                 continue
50             }
51
52             let mut search = line;
53             while let Some(i) = search.find("E") {
54                 search = &search[i + 1..];
55                 let code = if search.len() > 4 {
56                     search[..4].parse::<u32>()
57                 } else {
58                     continue
59                 };
60                 let code = match code {
61                     Ok(n) => n,
62                     Err(..) => continue,
63                 };
64                 map.entry(code).or_default()
65                    .push((file.to_owned(), num + 1, line.to_owned()));
66                 break
67             }
68
69             inside_long_diag = line.contains("r##\"");
70         }
71     });
72
73     let mut max = 0;
74     for (&code, entries) in map.iter() {
75         if code > max {
76             max = code;
77         }
78         if entries.len() == 1 {
79             continue
80         }
81
82         tidy_error!(bad, "duplicate error code: {}", code);
83         for &(ref file, line_num, ref line) in entries.iter() {
84             tidy_error!(bad, "{}:{}: {}", file.display(), line_num, line);
85         }
86     }
87
88     if !*bad {
89         println!("* {} error codes", map.len());
90         println!("* highest error code: E{:04}", max);
91     }
92 }