1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 #![feature(rustc_private, rustdoc)]
12 #![feature(question_mark)]
16 extern crate serialize
as rustc_serialize
;
18 use std
::collections
::BTreeMap
;
20 use std
::error
::Error
;
21 use std
::fs
::{read_dir, File}
;
22 use std
::io
::{Read, Write}
;
24 use std
::path
::PathBuf
;
26 use syntax
::diagnostics
::metadata
::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}
;
28 use rustdoc
::html
::markdown
::Markdown
;
29 use rustc_serialize
::json
;
33 Markdown(MarkdownFormatter
),
38 fn from(format
: &str) -> OutputFormat
{
39 match &*format
.to_lowercase() {
40 "html" => OutputFormat
::HTML(HTMLFormatter
),
41 "markdown" => OutputFormat
::Markdown(MarkdownFormatter
),
42 s
=> OutputFormat
::Unknown(s
.to_owned()),
48 fn header(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>>;
49 fn title(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>>;
50 fn error_code_block(&self, output
: &mut Write
, info
: &ErrorMetadata
,
51 err_code
: &str) -> Result
<(), Box
<Error
>>;
52 fn footer(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>>;
56 struct MarkdownFormatter
;
58 impl Formatter
for HTMLFormatter
{
59 fn header(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
60 write
!(output
, r
##"<!DOCTYPE html>
63 <title>Rust Compiler Error Index</title>
64 <meta charset="utf-8">
65 <!-- Include rust.css after main.css so its rules take priority. -->
66 <link rel="stylesheet" type="text/css" href="main.css"/>
67 <link rel="stylesheet" type="text/css" href="rust.css"/>
79 fn title(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
80 write
!(output
, "<h1>Rust Compiler Error Index</h1>\n")?
;
84 fn error_code_block(&self, output
: &mut Write
, info
: &ErrorMetadata
,
85 err_code
: &str) -> Result
<(), Box
<Error
>> {
86 // Enclose each error in a div so they can be shown/hidden en masse.
87 let desc_desc
= match info
.description
{
88 Some(_
) => "error-described",
89 None
=> "error-undescribed",
91 let use_desc
= match info
.use_site
{
92 Some(_
) => "error-used",
93 None
=> "error-unused",
95 write
!(output
, "<div class=\"{} {}\">", desc_desc
, use_desc
)?
;
97 // Error title (with self-link).
99 "<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
102 // Description rendered as markdown.
103 match info
.description
{
104 Some(ref desc
) => write
!(output
, "{}", Markdown(desc
))?
,
105 None
=> write
!(output
, "<p>No description.</p>\n")?
,
108 write
!(output
, "</div>\n")?
;
112 fn footer(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
113 write
!(output
, "</body>\n</html>")?
;
118 impl Formatter
for MarkdownFormatter
{
119 #[allow(unused_variables)]
120 fn header(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
124 fn title(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
125 write
!(output
, "# Rust Compiler Error Index\n")?
;
129 fn error_code_block(&self, output
: &mut Write
, info
: &ErrorMetadata
,
130 err_code
: &str) -> Result
<(), Box
<Error
>> {
131 Ok(match info
.description
{
132 Some(ref desc
) => write
!(output
, "## {}\n{}\n", err_code
, desc
)?
,
137 #[allow(unused_variables)]
138 fn footer(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
143 /// Load all the metadata files from `metadata_dir` into an in-memory map.
144 fn load_all_errors(metadata_dir
: &Path
) -> Result
<ErrorMetadataMap
, Box
<Error
>> {
145 let mut all_errors
= BTreeMap
::new();
147 for entry
in read_dir(metadata_dir
)?
{
148 let path
= entry?
.path();
150 let mut metadata_str
= String
::new();
151 File
::open(&path
).and_then(|mut f
| f
.read_to_string(&mut metadata_str
))?
;
153 let some_errors
: ErrorMetadataMap
= json
::decode(&metadata_str
)?
;
155 for (err_code
, info
) in some_errors
{
156 all_errors
.insert(err_code
, info
);
163 /// Output an HTML page for the errors in `err_map` to `output_path`.
164 fn render_error_page
<T
: Formatter
>(err_map
: &ErrorMetadataMap
, output_path
: &Path
,
165 formatter
: T
) -> Result
<(), Box
<Error
>> {
166 let mut output_file
= File
::create(output_path
)?
;
168 formatter
.header(&mut output_file
)?
;
169 formatter
.title(&mut output_file
)?
;
171 for (err_code
, info
) in err_map
{
172 formatter
.error_code_block(&mut output_file
, info
, err_code
)?
;
175 formatter
.footer(&mut output_file
)
178 fn main_with_result(format
: OutputFormat
, dst
: &Path
) -> Result
<(), Box
<Error
>> {
179 let build_arch
= env
::var("CFG_BUILD")?
;
180 let metadata_dir
= get_metadata_dir(&build_arch
);
181 let err_map
= load_all_errors(&metadata_dir
)?
;
183 OutputFormat
::Unknown(s
) => panic
!("Unknown output format: {}", s
),
184 OutputFormat
::HTML(h
) => render_error_page(&err_map
, dst
, h
)?
,
185 OutputFormat
::Markdown(m
) => render_error_page(&err_map
, dst
, m
)?
,
190 fn parse_args() -> (OutputFormat
, PathBuf
) {
191 let mut args
= env
::args().skip(1);
192 let format
= args
.next().map(|a
| OutputFormat
::from(&a
))
193 .unwrap_or(OutputFormat
::from("html"));
194 let dst
= args
.next().map(PathBuf
::from
).unwrap_or_else(|| {
196 OutputFormat
::HTML(..) => PathBuf
::from("doc/error-index.html"),
197 OutputFormat
::Markdown(..) => PathBuf
::from("doc/error-index.md"),
198 OutputFormat
::Unknown(..) => PathBuf
::from("<nul>"),
205 let (format
, dst
) = parse_args();
206 if let Err(e
) = main_with_result(format
, &dst
) {
207 panic
!("{}", e
.description());