]> git.proxmox.com Git - rustc.git/blame_incremental - src/tools/error_index_generator/main.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / error_index_generator / main.rs
... / ...
CommitLineData
1#![feature(rustc_private)]
2
3extern crate rustc_driver;
4extern crate rustc_log;
5extern crate rustc_session;
6
7extern crate rustc_errors;
8use rustc_errors::codes::DIAGNOSTICS;
9
10use std::env;
11use std::error::Error;
12use std::fs::{self, File};
13use std::io::Write;
14use std::path::Path;
15use std::path::PathBuf;
16use std::str::FromStr;
17
18use mdbook::book::{parse_summary, BookItem, Chapter};
19use mdbook::{Config, MDBook};
20
21enum OutputFormat {
22 HTML,
23 Markdown,
24 Unknown(String),
25}
26
27impl OutputFormat {
28 fn from(format: &str) -> OutputFormat {
29 match &*format.to_lowercase() {
30 "html" => OutputFormat::HTML,
31 "markdown" => OutputFormat::Markdown,
32 s => OutputFormat::Unknown(s.to_owned()),
33 }
34 }
35}
36
37/// Output an HTML page for the errors in `err_map` to `output_path`.
38fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
39 let mut output_file = File::create(output_path)?;
40
41 write!(output_file, "# Rust Compiler Error Index\n")?;
42
43 for (err_code, description) in DIAGNOSTICS.iter() {
44 write!(output_file, "## {}\n{}\n", err_code, description)?
45 }
46
47 Ok(())
48}
49
50// By default, mdbook doesn't consider code blocks as Rust ones contrary to rustdoc so we have
51// to manually add `rust` attribute whenever needed.
52fn add_rust_attribute_on_codeblock(explanation: &str) -> String {
53 // Very hacky way to add the rust attribute on all code blocks.
54 let mut skip = true;
55 explanation.split("\n```").fold(String::new(), |mut acc, part| {
56 if !acc.is_empty() {
57 acc.push_str("\n```");
58 }
59 if !skip {
60 if let Some(attrs) = part.split('\n').next() {
61 if !attrs.contains("rust")
62 && (attrs.is_empty()
63 || attrs.contains("compile_fail")
64 || attrs.contains("ignore")
65 || attrs.contains("edition"))
66 {
67 if !attrs.is_empty() {
68 acc.push_str("rust,");
69 } else {
70 acc.push_str("rust");
71 }
72 }
73 }
74 }
75 skip = !skip;
76 acc.push_str(part);
77 acc
78 })
79}
80
81fn render_html(output_path: &Path) -> Result<(), Box<dyn Error>> {
82 let mut introduction = format!(
83 "# Rust error codes index
84
85This page lists all the error codes emitted by the Rust compiler.
86
87"
88 );
89
90 let err_codes = DIAGNOSTICS;
91 let mut chapters = Vec::with_capacity(err_codes.len());
92
93 for (err_code, explanation) in err_codes.iter() {
94 introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
95
96 let content = add_rust_attribute_on_codeblock(explanation);
97 chapters.push(BookItem::Chapter(Chapter {
98 name: err_code.to_string(),
99 content: format!("# Error code {}\n\n{}\n", err_code, content),
100 number: None,
101 sub_items: Vec::new(),
102 // We generate it into the `error_codes` folder.
103 path: Some(PathBuf::from(&format!("{}.html", err_code))),
104 source_path: None,
105 parent_names: Vec::new(),
106 }));
107 }
108
109 let mut config = Config::from_str(include_str!("book_config.toml"))?;
110 config.build.build_dir = output_path.join("error_codes").to_path_buf();
111 let mut book = MDBook::load_with_config_and_summary(
112 env!("CARGO_MANIFEST_DIR"),
113 config,
114 parse_summary("")?,
115 )?;
116 let chapter = Chapter {
117 name: "Rust error codes index".to_owned(),
118 content: introduction,
119 number: None,
120 sub_items: chapters,
121 // Very important: this file is named as `error-index.html` and not `index.html`!
122 path: Some(PathBuf::from("error-index.html")),
123 source_path: None,
124 parent_names: Vec::new(),
125 };
126 book.book.sections.push(BookItem::Chapter(chapter));
127 book.build()?;
128
129 // The error-index used to be generated manually (without mdbook), and the
130 // index was located at the top level. Now that it is generated with
131 // mdbook, error-index.html has moved to error_codes/error-index.html.
132 // This adds a redirect so that old links go to the new location.
133 //
134 // We can't put this content into another file, otherwise `mdbook` will also put it into the
135 // output directory, making a duplicate.
136 fs::write(
137 output_path.join("error-index.html"),
138 r#"<!DOCTYPE html>
139<html>
140 <head>
141 <title>Rust error codes index - Error codes index</title>
142 <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
143 <meta name="description" content="Book listing all Rust error codes">
144 <script src="error_codes/redirect.js"></script>
145 </head>
146 <body>
147 <div>If you are not automatically redirected to the error code index, please <a id="index-link" href="./error_codes/error-index.html">here</a>.
148 </body>
149</html>"#,
150 )?;
151
152 Ok(())
153}
154
155fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
156 match format {
157 OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
158 OutputFormat::HTML => render_html(dst),
159 OutputFormat::Markdown => render_markdown(dst),
160 }
161}
162
163fn parse_args() -> (OutputFormat, PathBuf) {
164 let mut args = env::args().skip(1);
165 let format = args.next();
166 let dst = args.next();
167 let format = format.map(|a| OutputFormat::from(&a)).unwrap_or(OutputFormat::from("html"));
168 let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
169 OutputFormat::HTML => PathBuf::from("doc"),
170 OutputFormat::Markdown => PathBuf::from("doc/error-index.md"),
171 OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
172 });
173 (format, dst)
174}
175
176fn main() {
177 let handler =
178 rustc_session::EarlyDiagCtxt::new(rustc_session::config::ErrorOutputType::default());
179 rustc_driver::init_logger(&handler, rustc_log::LoggerConfig::from_env("RUST_LOG"));
180 let (format, dst) = parse_args();
181 let result = main_with_result(format, &dst);
182 if let Err(e) = result {
183 panic!("{:?}", e);
184 }
185}