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)
95 output: &mut dyn Write,
98 ) -> Result<(), Box<dyn Error>> {
104 <title>Rust Compiler Error Index</title>
105 <meta charset="utf-8">
106 <!-- Include rust.css after light.css so its rules take priority. -->
107 <link rel="stylesheet" type="text/css" href="{extra_path}rustdoc{suffix}.css"/>
108 <link rel="stylesheet" type="text/css" href="{extra_path}light{suffix}.css"/>
109 <link rel="stylesheet" type="text/css" href="{extra_path}rust.css"/>
111 .error-undescribed {{
123 fn title(&self, output: &mut dyn Write, title: &str) -> Result<(), Box<dyn Error>> {
124 write!(output, "<h1>{}</h1>\n", title)?;
128 fn footer(&self, output: &mut dyn Write) -> Result<(), Box<dyn Error>> {
129 write!(output, "</body></html>")?;
134 /// Output an HTML page for the errors in `err_map` to `output_path`.
135 fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
136 let mut output_file = File::create(output_path)?;
138 write!(output_file, "# Rust Compiler Error Index\n")?;
140 for (err_code, description) in error_codes().iter() {
142 Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
150 fn render_html(output_path: &Path, formatter: HTMLFormatter) -> Result<(), Box<dyn Error>> {
151 let mut output_file = File::create(output_path)?;
153 let error_codes_dir = "error_codes";
155 let parent = output_path.parent().expect("There should have a parent").join(error_codes_dir);
157 if !parent.exists() {
158 create_dir_all(&parent)?;
165 r#"<script>(function() {{
166 if (window.location.hash) {{
167 let code = window.location.hash.replace(/^#/, '');
168 // We have to make sure this pattern matches to avoid inadvertently creating an
170 if (/^E[0-9]+$/.test(code)) {{
171 window.location = './{error_codes_dir}/' + code + '.html';
177 formatter.title(&mut output_file, "Rust Compiler Error Index")?;
181 "<p>This page lists all the error codes emitted by the Rust compiler. If you want a full \
182 explanation on an error code, click on it.</p>\
185 for (err_code, explanation) in error_codes().iter() {
186 if let Some(explanation) = explanation {
189 "<li><a href='./{0}/{1}.html'>{1}</a></li>",
190 error_codes_dir, err_code
192 formatter.create_error_code_file(err_code, explanation, &parent)?;
194 write!(output_file, "<li>{}</li>", err_code)?;
197 write!(output_file, "</ul>")?;
198 formatter.footer(&mut output_file)
201 fn main_with_result(format: OutputFormat, dst: &Path) -> Result<(), Box<dyn Error>> {
203 OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
204 OutputFormat::HTML(h) => render_html(dst, h),
205 OutputFormat::Markdown => render_markdown(dst),
209 fn parse_args() -> (OutputFormat, PathBuf) {
210 let mut args = env::args().skip(1);
211 let format = args.next();
212 let dst = args.next();
213 let resource_suffix = args.next().unwrap_or_else(String::new);
215 .map(|a| OutputFormat::from(&a, &resource_suffix))
216 .unwrap_or(OutputFormat::from("html", &resource_suffix));
217 let dst = dst.map(PathBuf::from).unwrap_or_else(|| match format {
218 OutputFormat::HTML(..) => PathBuf::from("doc/error-index.html"),
219 OutputFormat::Markdown => PathBuf::from("doc/error-index.md"),
220 OutputFormat::Unknown(..) => PathBuf::from("<nul>"),
226 rustc_driver::init_env_logger("RUST_LOG");
227 let (format, dst) = parse_args();
229 rustc_span::create_default_session_globals_then(move || main_with_result(format, &dst));
230 if let Err(e) = result {
231 panic!("{}", e.to_string());