11//! Checks that all error codes have at least one test to prevent having error
22//! codes that are silently not thrown by the compiler anymore.
33
4- use std::collections::HashMap;
4+ use std::collections::{ HashMap, HashSet} ;
55use std::ffi::OsStr;
66use std::fs::read_to_string;
77use std::path::Path;
@@ -205,6 +205,7 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
205205 let mut found_explanations = 0;
206206 let mut found_tests = 0;
207207 let mut error_codes: HashMap<String, ErrorCodeStatus> = HashMap::new();
208+ let mut explanations: HashSet<String> = HashSet::new();
208209 // We want error codes which match the following cases:
209210 //
210211 // * foo(a, E0111, a)
@@ -218,17 +219,27 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
218219 for path in paths {
219220 super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| {
220221 let file_name = entry.file_name();
222+ let entry_path = entry.path();
223+
221224 if file_name == "error_codes.rs" {
222225 extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors);
223226 found_explanations += 1;
224- } else if entry.path() .extension() == Some(OsStr::new("stderr")) {
227+ } else if entry_path .extension() == Some(OsStr::new("stderr")) {
225228 extract_error_codes_from_tests(contents, &mut error_codes);
226229 found_tests += 1;
227- } else if entry.path() .extension() == Some(OsStr::new("rs")) {
230+ } else if entry_path .extension() == Some(OsStr::new("rs")) {
228231 let path = entry.path().to_string_lossy();
229232 if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) {
230233 extract_error_codes_from_source(contents, &mut error_codes, ®ex);
231234 }
235+ } else if entry_path
236+ .parent()
237+ .and_then(|p| p.file_name())
238+ .map(|p| p == "error_codes")
239+ .unwrap_or(false)
240+ && entry_path.extension() == Some(OsStr::new("md"))
241+ {
242+ explanations.insert(file_name.to_str().unwrap().replace(".md", ""));
232243 }
233244 });
234245 }
@@ -240,6 +251,10 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
240251 eprintln!("No error code was found in compilation errors!");
241252 *bad = true;
242253 }
254+ if explanations.is_empty() {
255+ eprintln!("No error code explanation was found!");
256+ *bad = true;
257+ }
243258 if errors.is_empty() {
244259 println!("Found {} error codes", error_codes.len());
245260
@@ -282,11 +297,21 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
282297 }
283298 }
284299 }
300+ if errors.is_empty() {
301+ for explanation in explanations {
302+ if !error_codes.contains_key(&explanation) {
303+ errors.push(format!(
304+ "{} error code explanation should be listed in `error_codes.rs`",
305+ explanation
306+ ));
307+ }
308+ }
309+ }
285310 errors.sort();
286311 for err in &errors {
287312 eprintln!("{}", err);
288313 }
289- println!("Found {} error codes with no tests ", errors.len());
314+ println!("Found {} error(s) in error codes ", errors.len());
290315 if !errors.is_empty() {
291316 *bad = true;
292317 }
0 commit comments