Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update tidy check for error codes testing #66574

Merged
merged 1 commit into from
Nov 23, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 49 additions & 19 deletions src/tools/tidy/src/error_codes_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::read_to_string;
use std::io::Read;
use std::path::Path;

// A few of those error codes can't be tested but all the others can and *should* be tested!
Expand Down Expand Up @@ -50,41 +52,69 @@ const WHITELIST: &[&str] = &[
"E0729",
];

fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>) {
fn check_error_code_explanation(
f: &str,
error_codes: &mut HashMap<String, bool>,
err_code: String,
) {
for line in f.lines() {
let s = line.trim();
if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
error_codes.insert(err_code, true);
return;
} else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
error_codes.get_mut(&err_code).map(|x| *x = true);
return;
}
}
}

macro_rules! some_or_continue {
($e:expr) => (
match $e {
Some(e) => e,
None => continue,
}
);
}

fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &Path) {
let mut reached_no_explanation = false;
let mut last_error_code = None;

for line in f.lines() {
let s = line.trim();
if s.starts_with('E') && s.ends_with(": r##\"") {
if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") {
if let Some(err_code) = s.splitn(2, ':').next() {
let err_code = err_code.to_owned();
last_error_code = Some(err_code.clone());
if !error_codes.contains_key(&err_code) {
error_codes.insert(err_code, false);
error_codes.insert(err_code.clone(), false);
}
}
} else if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
if let Some(err_code) = s.splitn(2, 'E').skip(1).next() {
if let Some(err_code) = err_code.splitn(2, ',').next() {
let nb = error_codes.entry(format!("E{}", err_code)).or_insert(false);
*nb = true;
// Now we extract the tests from the markdown file!
let md = some_or_continue!(s.splitn(2, "include_str!(\"").skip(1).next());
let md_file_name = some_or_continue!(md.splitn(2, "\")").next());
let path = some_or_continue!(path.parent()).join(md_file_name);
match read_to_string(&path) {
Ok(content) => {
check_error_code_explanation(
&content,
error_codes,
err_code,
);
}
Err(e) => {
eprintln!("Couldn't read `{}`: {}", path.display(), e);
}
}
}
} else if s == ";" {
reached_no_explanation = true;
} else if reached_no_explanation && s.starts_with('E') {
if let Some(err_code) = s.splitn(2, ',').next() {
let err_code = err_code.to_owned();
if !error_codes.contains_key(&err_code) { // this check should *never* fail!
error_codes.insert(err_code, false);
}
}
} else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
if let Some(last) = last_error_code {
error_codes.get_mut(&last).map(|x| *x = true);
}
last_error_code = None;
} else if s == ";" {
reached_no_explanation = true;
}
}
}
Expand All @@ -111,7 +141,7 @@ pub fn check(path: &Path, bad: &mut bool) {
&mut |entry, contents| {
let file_name = entry.file_name();
if file_name == "error_codes.rs" {
extract_error_codes(contents, &mut error_codes);
extract_error_codes(contents, &mut error_codes, entry.path());
} else if entry.path().extension() == Some(OsStr::new("stderr")) {
extract_error_codes_from_tests(contents, &mut error_codes);
}
Expand Down