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)]
15 extern crate serialize
as rustc_serialize
;
17 use std
::collections
::BTreeMap
;
18 use std
::fs
::{read_dir, File}
;
19 use std
::io
::{Read, Write}
;
22 use std
::error
::Error
;
24 use syntax
::diagnostics
::metadata
::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata}
;
26 use rustdoc
::html
::markdown
::Markdown
;
27 use rustc_serialize
::json
;
31 Markdown(MarkdownFormatter
),
36 fn from(format
: &str) -> OutputFormat
{
37 match &*format
.to_lowercase() {
38 "html" => OutputFormat
::HTML(HTMLFormatter
),
39 "markdown" => OutputFormat
::Markdown(MarkdownFormatter
),
40 s
=> OutputFormat
::Unknown(s
.to_owned()),
46 fn header(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>>;
47 fn title(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>>;
48 fn error_code_block(&self, output
: &mut Write
, info
: &ErrorMetadata
,
49 err_code
: &str) -> Result
<(), Box
<Error
>>;
50 fn footer(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>>;
54 struct MarkdownFormatter
;
56 impl Formatter
for HTMLFormatter
{
57 fn header(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
58 try
!(write
!(output
, r
##"<!DOCTYPE html>
61 <title>Rust Compiler Error Index</title>
62 <meta charset="utf-8">
63 <!-- Include rust.css after main.css so its rules take priority. -->
64 <link rel="stylesheet" type="text/css" href="main.css"/>
65 <link rel="stylesheet" type="text/css" href="rust.css"/>
77 fn title(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
78 try
!(write
!(output
, "<h1>Rust Compiler Error Index</h1>\n"));
82 fn error_code_block(&self, output
: &mut Write
, info
: &ErrorMetadata
,
83 err_code
: &str) -> Result
<(), Box
<Error
>> {
84 // Enclose each error in a div so they can be shown/hidden en masse.
85 let desc_desc
= match info
.description
{
86 Some(_
) => "error-described",
87 None
=> "error-undescribed",
89 let use_desc
= match info
.use_site
{
90 Some(_
) => "error-used",
91 None
=> "error-unused",
93 try
!(write
!(output
, "<div class=\"{} {}\">", desc_desc
, use_desc
));
95 // Error title (with self-link).
97 "<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
100 // Description rendered as markdown.
101 match info
.description
{
102 Some(ref desc
) => try
!(write
!(output
, "{}", Markdown(desc
))),
103 None
=> try
!(write
!(output
, "<p>No description.</p>\n")),
106 try
!(write
!(output
, "</div>\n"));
110 fn footer(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
111 try
!(write
!(output
, "</body>\n</html>"));
116 impl Formatter
for MarkdownFormatter
{
117 #[allow(unused_variables)]
118 fn header(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
122 fn title(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
123 try
!(write
!(output
, "# Rust Compiler Error Index\n"));
127 fn error_code_block(&self, output
: &mut Write
, info
: &ErrorMetadata
,
128 err_code
: &str) -> Result
<(), Box
<Error
>> {
129 Ok(match info
.description
{
130 Some(ref desc
) => try
!(write
!(output
, "## {}\n{}\n", err_code
, desc
)),
135 #[allow(unused_variables)]
136 fn footer(&self, output
: &mut Write
) -> Result
<(), Box
<Error
>> {
141 /// Load all the metadata files from `metadata_dir` into an in-memory map.
142 fn load_all_errors(metadata_dir
: &Path
) -> Result
<ErrorMetadataMap
, Box
<Error
>> {
143 let mut all_errors
= BTreeMap
::new();
145 for entry
in try
!(read_dir(metadata_dir
)) {
146 let path
= try
!(entry
).path();
148 let mut metadata_str
= String
::new();
149 try
!(File
::open(&path
).and_then(|mut f
| f
.read_to_string(&mut metadata_str
)));
151 let some_errors
: ErrorMetadataMap
= try
!(json
::decode(&metadata_str
));
153 for (err_code
, info
) in some_errors
{
154 all_errors
.insert(err_code
, info
);
161 /// Output an HTML page for the errors in `err_map` to `output_path`.
162 fn render_error_page
<T
: Formatter
>(err_map
: &ErrorMetadataMap
, output_path
: &Path
,
163 formatter
: T
) -> Result
<(), Box
<Error
>> {
164 let mut output_file
= try
!(File
::create(output_path
));
166 try
!(formatter
.header(&mut output_file
));
167 try
!(formatter
.title(&mut output_file
));
169 for (err_code
, info
) in err_map
{
170 try
!(formatter
.error_code_block(&mut output_file
, info
, err_code
));
173 formatter
.footer(&mut output_file
)
176 fn main_with_result(format
: OutputFormat
) -> Result
<(), Box
<Error
>> {
177 let build_arch
= try
!(env
::var("CFG_BUILD"));
178 let metadata_dir
= get_metadata_dir(&build_arch
);
179 let err_map
= try
!(load_all_errors(&metadata_dir
));
181 OutputFormat
::Unknown(s
) => panic
!("Unknown output format: {}", s
),
182 OutputFormat
::HTML(h
) => try
!(render_error_page(&err_map
,
183 Path
::new("doc/error-index.html"),
185 OutputFormat
::Markdown(m
) => try
!(render_error_page(&err_map
,
186 Path
::new("doc/error-index.md"),
192 fn parse_args() -> OutputFormat
{
193 for arg
in env
::args().skip(1) {
194 return OutputFormat
::from(&arg
);
196 OutputFormat
::from("html")
200 if let Err(e
) = main_with_result(parse_args()) {
201 panic
!("{}", e
.description());