Add checks to ensure that explanations have code examples using the error code and also that 'compile_fail' isn't mispelled
This commit is contained in:
parent
2dc5b602ee
commit
5c8f50952b
1 changed files with 74 additions and 15 deletions
|
|
@ -15,21 +15,57 @@ const WHITELIST: &[&str] = &[
|
|||
"E0727", "E0729",
|
||||
];
|
||||
|
||||
// Some error codes don't have any tests apparently...
|
||||
const IGNORE_EXPLANATION_CHECK: &[&str] =
|
||||
&["E0570", "E0601", "E0602", "E0639", "E0729", "E0749", "E0750", "E0751"];
|
||||
|
||||
fn check_error_code_explanation(
|
||||
f: &str,
|
||||
error_codes: &mut HashMap<String, bool>,
|
||||
err_code: String,
|
||||
) {
|
||||
) -> bool {
|
||||
let mut invalid_compile_fail_format = false;
|
||||
let mut found_error_code = false;
|
||||
|
||||
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;
|
||||
if s.starts_with("```") {
|
||||
if s.contains("compile_fail") && s.contains('E') {
|
||||
if !found_error_code {
|
||||
error_codes.insert(err_code.clone(), true);
|
||||
found_error_code = true;
|
||||
}
|
||||
} else if s.contains("compile-fail") {
|
||||
invalid_compile_fail_format = true;
|
||||
}
|
||||
} 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;
|
||||
if !found_error_code {
|
||||
error_codes.get_mut(&err_code).map(|x| *x = true);
|
||||
found_error_code = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
invalid_compile_fail_format
|
||||
}
|
||||
|
||||
fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &String) -> bool {
|
||||
let mut can_be_ignored = false;
|
||||
|
||||
for line in f.lines() {
|
||||
let s = line.trim();
|
||||
if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
|
||||
return true;
|
||||
}
|
||||
if s.starts_with("```") {
|
||||
if s.contains("compile_fail") && s.contains(err_code) {
|
||||
return true;
|
||||
} else if s.contains("(") {
|
||||
// It's very likely that we can't actually make it fail compilation...
|
||||
can_be_ignored = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
can_be_ignored
|
||||
}
|
||||
|
||||
macro_rules! some_or_continue {
|
||||
|
|
@ -41,7 +77,12 @@ macro_rules! some_or_continue {
|
|||
};
|
||||
}
|
||||
|
||||
fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &Path) {
|
||||
fn extract_error_codes(
|
||||
f: &str,
|
||||
error_codes: &mut HashMap<String, bool>,
|
||||
path: &Path,
|
||||
errors: &mut Vec<String>,
|
||||
) {
|
||||
let mut reached_no_explanation = false;
|
||||
|
||||
for line in f.lines() {
|
||||
|
|
@ -55,10 +96,26 @@ fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &
|
|||
// Now we extract the tests from the markdown file!
|
||||
let md = some_or_continue!(s.splitn(2, "include_str!(\"").nth(1));
|
||||
let md_file_name = some_or_continue!(md.splitn(2, "\")").next());
|
||||
let path = some_or_continue!(path.parent()).join(md_file_name);
|
||||
let path = some_or_continue!(path.parent())
|
||||
.join(md_file_name)
|
||||
.canonicalize()
|
||||
.expect("failed to canonicalize error explanation file path");
|
||||
match read_to_string(&path) {
|
||||
Ok(content) => {
|
||||
check_error_code_explanation(&content, error_codes, err_code);
|
||||
if !IGNORE_EXPLANATION_CHECK.contains(&err_code.as_str())
|
||||
&& !check_if_error_code_is_test_in_explanation(&content, &err_code)
|
||||
{
|
||||
errors.push(format!(
|
||||
"`{}` doesn't use its own error code in compile_fail example",
|
||||
path.display(),
|
||||
));
|
||||
}
|
||||
if check_error_code_explanation(&content, error_codes, err_code) {
|
||||
errors.push(format!(
|
||||
"`{}` uses invalid tag `compile-fail` instead of `compile_fail`",
|
||||
path.display(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Couldn't read `{}`: {}", path.display(), e);
|
||||
|
|
@ -94,22 +151,24 @@ fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, boo
|
|||
}
|
||||
|
||||
pub fn check(path: &Path, bad: &mut bool) {
|
||||
let mut errors = Vec::new();
|
||||
println!("Checking which error codes lack tests...");
|
||||
let mut error_codes: HashMap<String, bool> = HashMap::new();
|
||||
super::walk(path, &mut |path| super::filter_dirs(path), &mut |entry, contents| {
|
||||
let file_name = entry.file_name();
|
||||
if file_name == "error_codes.rs" {
|
||||
extract_error_codes(contents, &mut error_codes, entry.path());
|
||||
extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors);
|
||||
} else if entry.path().extension() == Some(OsStr::new("stderr")) {
|
||||
extract_error_codes_from_tests(contents, &mut error_codes);
|
||||
}
|
||||
});
|
||||
println!("Found {} error codes", error_codes.len());
|
||||
if errors.is_empty() {
|
||||
println!("Found {} error codes", error_codes.len());
|
||||
|
||||
let mut errors = Vec::new();
|
||||
for (err_code, nb) in &error_codes {
|
||||
if !*nb && !WHITELIST.contains(&err_code.as_str()) {
|
||||
errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
|
||||
for (err_code, nb) in &error_codes {
|
||||
if !*nb && !WHITELIST.contains(&err_code.as_str()) {
|
||||
errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
|
||||
}
|
||||
}
|
||||
}
|
||||
errors.sort();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue