Rollup merge of #108482 - Ezrashaw:force-error-docs, r=GuillaumeGomez

statically guarantee that current error codes are documented

Closes #61137 (that's right!)

Pretty simple refactor (often just a change from `Result<Option<&str>>` to `Result<&str>`)

r? `@GuillaumeGomez` (could you specially look at 53044158ef? I believe you wrote that in the first place, just want to make sure you're happy with the change)
This commit is contained in:
Matthias Krüger 2023-02-26 12:05:00 +01:00 committed by GitHub
commit edd27cf4ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 36 additions and 87 deletions

View file

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
mdbook = { version = "0.4", default-features = false, features = ["search"] }
rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
[[bin]]
name = "error_index_generator"

View file

@ -2,9 +2,6 @@
extern crate rustc_driver;
// We use the function we generate from `register_diagnostics!`.
use crate::error_codes::error_codes;
use std::env;
use std::error::Error;
use std::fs::{self, File};
@ -17,22 +14,6 @@ use std::str::FromStr;
use mdbook::book::{parse_summary, BookItem, Chapter};
use mdbook::{Config, MDBook};
macro_rules! register_diagnostics {
($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
let mut errors: Vec<(&str, Option<&str>)> = vec![
$((stringify!($error_code), Some($message)),)+
$((stringify!($undocumented), None),)*
];
errors.sort();
errors
}
}
}
#[path = "../../../compiler/rustc_error_codes/src/error_codes.rs"]
mod error_codes;
enum OutputFormat {
HTML,
Markdown,
@ -55,11 +36,8 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
write!(output_file, "# Rust Compiler Error Index\n")?;
for (err_code, description) in error_codes().iter() {
match description {
Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
None => {}
}
for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
write!(output_file, "## {}\n{}\n", err_code, description)?
}
Ok(())
@ -105,27 +83,23 @@ This page lists all the error codes emitted by the Rust compiler.
"
);
let err_codes = error_codes();
let err_codes = rustc_error_codes::DIAGNOSTICS;
let mut chapters = Vec::with_capacity(err_codes.len());
for (err_code, explanation) in err_codes.iter() {
if let Some(explanation) = explanation {
introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
let content = add_rust_attribute_on_codeblock(explanation);
chapters.push(BookItem::Chapter(Chapter {
name: err_code.to_string(),
content: format!("# Error code {}\n\n{}\n", err_code, content),
number: None,
sub_items: Vec::new(),
// We generate it into the `error_codes` folder.
path: Some(PathBuf::from(&format!("{}.html", err_code))),
source_path: None,
parent_names: Vec::new(),
}));
} else {
introduction.push_str(&format!(" * {}\n", err_code));
}
let content = add_rust_attribute_on_codeblock(explanation);
chapters.push(BookItem::Chapter(Chapter {
name: err_code.to_string(),
content: format!("# Error code {}\n\n{}\n", err_code, content),
number: None,
sub_items: Vec::new(),
// We generate it into the `error_codes` folder.
path: Some(PathBuf::from(&format!("{}.html", err_code))),
source_path: None,
parent_names: Vec::new(),
}));
}
let mut config = Config::from_str(include_str!("book_config.toml"))?;

View file

@ -45,7 +45,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
let mut errors = Vec::new();
// Stage 1: create list
let error_codes = extract_error_codes(root_path, &mut errors, verbose);
let error_codes = extract_error_codes(root_path, &mut errors);
println!("Found {} error codes", error_codes.len());
println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
@ -65,18 +65,17 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
}
/// Stage 1: Parses a list of error codes from `error_codes.rs`.
fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool) -> Vec<String> {
fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String> {
let path = root_path.join(Path::new(ERROR_CODES_PATH));
let file =
fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
let mut error_codes = Vec::new();
let mut reached_undocumented_codes = false;
for line in file.lines() {
let line = line.trim();
if !reached_undocumented_codes && line.starts_with('E') {
if line.starts_with('E') {
let split_line = line.split_once(':');
// Extract the error code from the line, emitting a fatal error if it is not in a correct format.
@ -111,23 +110,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool
}
error_codes.push(err_code);
} else if reached_undocumented_codes && line.starts_with('E') {
let err_code = match line.split_once(',') {
None => line,
Some((err_code, _)) => err_code,
}
.to_string();
verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code);
if error_codes.contains(&err_code) {
errors.push(format!("Found duplicate error code: `{}`", err_code));
}
error_codes.push(err_code);
} else if line == ";" {
// Once we reach the undocumented error codes, adapt to different syntax.
reached_undocumented_codes = true;
}
}