1 #![feature(rustc_private)]
3 extern crate rustc_driver
;
4 extern crate rustc_span
;
6 use std
::cell
::RefCell
;
7 use std
::collections
::BTreeMap
;
13 use std
::path
::PathBuf
;
15 use rustc_span
::edition
::DEFAULT_EDITION
;
17 use rustdoc
::html
::markdown
::{ErrorCodes, IdMap, Markdown, Playground}
;
19 pub struct ErrorMetadata
{
20 pub description
: Option
<String
>,
23 /// Mapping from error codes to metadata that can be (de)serialized.
24 pub type ErrorMetadataMap
= BTreeMap
<String
, ErrorMetadata
>;
28 Markdown(MarkdownFormatter
),
33 fn from(format
: &str, resource_suffix
: &str) -> OutputFormat
{
34 match &*format
.to_lowercase() {
35 "html" => OutputFormat
::HTML(HTMLFormatter(
36 RefCell
::new(IdMap
::new()),
37 resource_suffix
.to_owned(),
39 "markdown" => OutputFormat
::Markdown(MarkdownFormatter
),
40 s
=> OutputFormat
::Unknown(s
.to_owned()),
46 fn header(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>>;
47 fn title(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>>;
50 output
: &mut dyn Write
,
53 ) -> Result
<(), Box
<dyn Error
>>;
54 fn footer(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>>;
57 struct HTMLFormatter(RefCell
<IdMap
>, String
);
58 struct MarkdownFormatter
;
60 impl Formatter
for HTMLFormatter
{
61 fn header(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
67 <title>Rust Compiler Error Index</title>
68 <meta charset="utf-8">
69 <!-- Include rust.css after light.css so its rules take priority. -->
70 <link rel="stylesheet" type="text/css" href="rustdoc{suffix}.css"/>
71 <link rel="stylesheet" type="text/css" href="light{suffix}.css"/>
72 <link rel="stylesheet" type="text/css" href="rust.css"/>
86 fn title(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
87 write
!(output
, "<h1>Rust Compiler Error Index</h1>\n")?
;
93 output
: &mut dyn Write
,
96 ) -> Result
<(), Box
<dyn Error
>> {
97 // Enclose each error in a div so they can be shown/hidden en masse.
98 let desc_desc
= match info
.description
{
99 Some(_
) => "error-described",
100 None
=> "error-undescribed",
102 write
!(output
, "<div class=\"{}\">", desc_desc
)?
;
104 // Error title (with self-link).
107 "<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
111 // Description rendered as markdown.
112 match info
.description
{
114 let mut id_map
= self.0.borrow_mut();
115 let playground
= Playground
{
117 url
: String
::from("https://play.rust-lang.org/"),
133 None
=> write
!(output
, "<p>No description.</p>\n")?
,
136 write
!(output
, "</div>\n")?
;
140 fn footer(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
144 function onEach(arr, func) {{
145 if (arr && arr.length > 0 && func) {{
146 for (var i = 0; i < arr.length; i++) {{
152 function hasClass(elem, className) {{
153 if (elem && className && elem.className) {{
154 var elemClass = elem.className;
155 var start = elemClass.indexOf(className);
158 }} else if (elemClass.length === className.length) {{
161 if (start > 0 && elemClass[start - 1] !== ' ') {{
164 var end = start + className.length;
165 if (end < elemClass.length && elemClass[end] !== ' ') {{
170 if (start > 0 && elemClass[start - 1] !== ' ') {{
173 var end = start + className.length;
174 if (end < elemClass.length && elemClass[end] !== ' ') {{
182 onEach(document.getElementsByClassName('rust-example-rendered'), function(e) {{
183 if (hasClass(e, 'compile_fail')) {{
184 e.addEventListener("mouseover", function(event) {{
185 e.previousElementSibling.childNodes[0].style.color = '#f00';
187 e.addEventListener("mouseout", function(event) {{
188 e.previousElementSibling.childNodes[0].style.color = '';
190 }} else if (hasClass(e, 'ignore')) {{
191 e.addEventListener("mouseover", function(event) {{
192 e.previousElementSibling.childNodes[0].style.color = '#ff9200';
194 e.addEventListener("mouseout", function(event) {{
195 e.previousElementSibling.childNodes[0].style.color = '';
207 impl Formatter
for MarkdownFormatter
{
208 #[allow(unused_variables)]
209 fn header(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
213 fn title(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
214 write
!(output
, "# Rust Compiler Error Index\n")?
;
220 output
: &mut dyn Write
,
221 info
: &ErrorMetadata
,
223 ) -> Result
<(), Box
<dyn Error
>> {
224 Ok(match info
.description
{
225 Some(ref desc
) => write
!(output
, "## {}\n{}\n", err_code
, desc
)?
,
230 #[allow(unused_variables)]
231 fn footer(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
236 /// Output an HTML page for the errors in `err_map` to `output_path`.
237 fn render_error_page
<T
: Formatter
>(
238 err_map
: &ErrorMetadataMap
,
241 ) -> Result
<(), Box
<dyn Error
>> {
242 let mut output_file
= File
::create(output_path
)?
;
244 formatter
.header(&mut output_file
)?
;
245 formatter
.title(&mut output_file
)?
;
247 for (err_code
, info
) in err_map
{
248 formatter
.error_code_block(&mut output_file
, info
, err_code
)?
;
251 formatter
.footer(&mut output_file
)
254 fn main_with_result(format
: OutputFormat
, dst
: &Path
) -> Result
<(), Box
<dyn Error
>> {
255 let long_codes
= register_all();
256 let mut err_map
= BTreeMap
::new();
257 for (code
, desc
) in long_codes
{
258 err_map
.insert(code
.to_string(), ErrorMetadata { description: desc.map(String::from) }
);
261 OutputFormat
::Unknown(s
) => panic
!("Unknown output format: {}", s
),
262 OutputFormat
::HTML(h
) => render_error_page(&err_map
, dst
, h
)?
,
263 OutputFormat
::Markdown(m
) => render_error_page(&err_map
, dst
, m
)?
,
268 fn parse_args() -> (OutputFormat
, PathBuf
) {
269 let mut args
= env
::args().skip(1);
270 let format
= args
.next();
271 let dst
= args
.next();
272 let resource_suffix
= args
.next().unwrap_or_else(String
::new
);
274 .map(|a
| OutputFormat
::from(&a
, &resource_suffix
))
275 .unwrap_or(OutputFormat
::from("html", &resource_suffix
));
276 let dst
= dst
.map(PathBuf
::from
).unwrap_or_else(|| match format
{
277 OutputFormat
::HTML(..) => PathBuf
::from("doc/error-index.html"),
278 OutputFormat
::Markdown(..) => PathBuf
::from("doc/error-index.md"),
279 OutputFormat
::Unknown(..) => PathBuf
::from("<nul>"),
285 rustc_driver
::init_env_logger("RUST_LOG");
286 let (format
, dst
) = parse_args();
288 rustc_span
::create_default_session_globals_then(move || main_with_result(format
, &dst
));
289 if let Err(e
) = result
{
290 panic
!("{}", e
.to_string());
294 include
!(concat
!(env
!("OUT_DIR"), "/error_codes.rs"));