1 #![feature(rustc_private)]
3 extern crate rustc_driver;
4 extern crate rustc_span;
6 use crate::error_codes::error_codes;
10 use std::fs::{create_dir_all, File};
13 use std::path::PathBuf;
15 use rustc_span::edition::DEFAULT_EDITION;
17 use rustdoc::html::markdown::{ErrorCodes, HeadingOffset, IdMap, Markdown, Playground};
19 macro_rules! register_diagnostics {
20 ($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
21 pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
22 let mut errors: Vec<(&str, Option<&str>)> = vec![
23 $((stringify!($error_code), Some($message)),)+
24 $((stringify!($undocumented), None),)+
32 #[path = "../../../compiler/rustc_error_codes/src/error_codes.rs"]
42 fn from(format: &str, resource_suffix: &str) -> OutputFormat {
43 match &*format.to_lowercase() {
44 "html" => OutputFormat::HTML(HTMLFormatter(resource_suffix.to_owned())),
45 "markdown" => OutputFormat::Markdown,
46 s => OutputFormat::Unknown(s.to_owned()),
51 struct HTMLFormatter(String);
54 fn create_error_code_file(
59 ) -> Result<(), Box<dyn Error>> {
60 let mut output_file = File::create(parent_dir.join(err_code).with_extension("html"))?;
62 self.header(&mut output_file, "../")?;
63 self.title(&mut output_file, &format!("Error code {}", err_code))?;
65 let mut id_map = IdMap::new();
67 Playground { crate_name: None, url: String::from("https://play.rust-lang.org/") };
75 error_codes: ErrorCodes::Yes,
76 edition: DEFAULT_EDITION,
77 playground: &Some(playground),
78 heading_offset: HeadingOffset::H1,
85 <a style='text-align: center;display: block;width: 100%;' \
86 href='../error-index.html'>Back to list of error codes</a>\
90 self.footer(&mut output_file)
93 fn header(&self, output: &mut dyn Write, extra: &str) -> Result<(), Box<dyn Error>> {
99 <title>Rust Compiler Error Index</title>
100 <meta charset="utf-8">
101 <!-- Include rust.css after light.css so its rules take priority. -->
102 <link rel="stylesheet" type="text/css" href="{extra}rustdoc{suffix}.css"/>
103 <link rel="stylesheet" type="text/css" href="{extra}light{suffix}.css"/>
104 <link rel="stylesheet" type="text/css" href="{extra}rust.css"/>
106 .error-undescribed {{
118 fn title(&self, output: &mut dyn Write, title: &str) -> Result<(), Box<dyn Error>> {
119 write!(output, "<h1>{}</h1>\n", title)?;
123 fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
124 write!(output, "</body></html>")?;
129 /// Output an HTML page for the errors in `err_map` to `output_path`.
130 fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
131 let mut output_file = File::create(output_path)?;
133 write!(output_file, "# Rust Compiler Error Index\n")?;
135 for (err_code, description) in error_codes().iter() {
137 Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
145 fn render_html(output_path: &Path, formatter: HTMLFormatter) -> Result<(), Box<dyn Error>> {
146 let mut output_file = File::create(output_path)?;
148 let error_codes_dir = "error_codes";
150 let parent = output_path.parent().expect("There should have a parent").join(error_codes_dir);
152 if !parent.exists() {
153 create_dir_all(&parent)?;
156 formatter.header(&mut output_file, "")?;
157 formatter.title(&mut output_file, "Rust Compiler Error Index")?;
161 "<p>This page lists all the error codes emitted by the Rust compiler. If you want a full \
162 explanation on an error code, click on it.</p>\
165 for (err_code, explanation) in error_codes().iter() {
166 if let Some(explanation) = explanation {
169 "<li><a href='./{0}/{1}.html'>{1}</a></li>",
170 error_codes_dir, err_code
172 formatter.create_error_code_file(err_code, explanation, &parent)?;
174 write!(output_file, "<li>{}</li>", err_code)?;
177 write!(output_file, "</ul>")?;
178 formatter.footer(&mut output_file)
181 fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
183 OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
184 OutputFormat::HTML(h) => render_html(dst, h),
185 OutputFormat::Markdown => render_markdown(dst),
189 fn parse_args() -> (OutputFormat, PathBuf) {
190 let mut args = env::args().skip(1);
191 let format = args.next();
192 let dst = args.next();
193 let resource_suffix = args.next().unwrap_or_else(String::new);
195 .map(|a| OutputFormat::from(&a, &resource_suffix))
196 .unwrap_or(OutputFormat::from("html", &resource_suffix));
197 let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
198 OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"),
199 OutputFormat::Markdown => PathBuf::from("doc/error-index.md"),
200 OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
206 rustc_driver::init_env_logger("RUST_LOG");
207 let (format, dst) = parse_args();
209 rustc_span::create_default_session_globals_then(move || main_with_result(format, &dst));
210 if let Err(e) = result {
211 panic!("{}", e.to_string());