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, HeadingOffset, 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/"),
126 error_codes
: ErrorCodes
::Yes
,
127 edition
: DEFAULT_EDITION
,
128 playground
: &Some(playground
),
129 heading_offset
: HeadingOffset
::H1
,
134 None
=> write
!(output
, "<p>No description.</p>\n")?
,
137 write
!(output
, "</div>\n")?
;
141 fn footer(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
145 function onEach(arr, func) {{
146 if (arr && arr.length > 0 && func) {{
147 var length = arr.length;
149 for (i = 0; i < length; ++i) {{
158 function onEachLazy(lazyArray, func) {{
160 Array.prototype.slice.call(lazyArray),
164 function hasClass(elem, className) {{
165 return elem && elem.classList && elem.classList.contains(className);
168 onEachLazy(document.getElementsByClassName('rust-example-rendered'), function(e) {{
169 if (hasClass(e, 'compile_fail')) {{
170 e.addEventListener("mouseover", function(event) {{
171 e.parentElement.previousElementSibling.childNodes[0].style.color = '#f00';
173 e.addEventListener("mouseout", function(event) {{
174 e.parentElement.previousElementSibling.childNodes[0].style.color = '';
176 }} else if (hasClass(e, 'ignore')) {{
177 e.addEventListener("mouseover", function(event) {{
178 e.parentElement.previousElementSibling.childNodes[0].style.color = '#ff9200';
180 e.addEventListener("mouseout", function(event) {{
181 e.parentElement.previousElementSibling.childNodes[0].style.color = '';
193 impl Formatter
for MarkdownFormatter
{
194 #[allow(unused_variables)]
195 fn header(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
199 fn title(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
200 write
!(output
, "# Rust Compiler Error Index\n")?
;
206 output
: &mut dyn Write
,
207 info
: &ErrorMetadata
,
209 ) -> Result
<(), Box
<dyn Error
>> {
210 Ok(match info
.description
{
211 Some(ref desc
) => write
!(output
, "## {}\n{}\n", err_code
, desc
)?
,
216 #[allow(unused_variables)]
217 fn footer(&self, output
: &mut dyn Write
) -> Result
<(), Box
<dyn Error
>> {
222 /// Output an HTML page for the errors in `err_map` to `output_path`.
223 fn render_error_page
<T
: Formatter
>(
224 err_map
: &ErrorMetadataMap
,
227 ) -> Result
<(), Box
<dyn Error
>> {
228 let mut output_file
= File
::create(output_path
)?
;
230 formatter
.header(&mut output_file
)?
;
231 formatter
.title(&mut output_file
)?
;
233 for (err_code
, info
) in err_map
{
234 formatter
.error_code_block(&mut output_file
, info
, err_code
)?
;
237 formatter
.footer(&mut output_file
)
240 fn main_with_result(format
: OutputFormat
, dst
: &Path
) -> Result
<(), Box
<dyn Error
>> {
241 let long_codes
= register_all();
242 let mut err_map
= BTreeMap
::new();
243 for (code
, desc
) in long_codes
{
244 err_map
.insert(code
.to_string(), ErrorMetadata { description: desc.map(String::from) }
);
247 OutputFormat
::Unknown(s
) => panic
!("Unknown output format: {}", s
),
248 OutputFormat
::HTML(h
) => render_error_page(&err_map
, dst
, h
)?
,
249 OutputFormat
::Markdown(m
) => render_error_page(&err_map
, dst
, m
)?
,
254 fn parse_args() -> (OutputFormat
, PathBuf
) {
255 let mut args
= env
::args().skip(1);
256 let format
= args
.next();
257 let dst
= args
.next();
258 let resource_suffix
= args
.next().unwrap_or_else(String
::new
);
260 .map(|a
| OutputFormat
::from(&a
, &resource_suffix
))
261 .unwrap_or(OutputFormat
::from("html", &resource_suffix
));
262 let dst
= dst
.map(PathBuf
::from
).unwrap_or_else(|| match format
{
263 OutputFormat
::HTML(..) => PathBuf
::from("doc/error-index.html"),
264 OutputFormat
::Markdown(..) => PathBuf
::from("doc/error-index.md"),
265 OutputFormat
::Unknown(..) => PathBuf
::from("<nul>"),
271 rustc_driver
::init_env_logger("RUST_LOG");
272 let (format
, dst
) = parse_args();
274 rustc_span
::create_default_session_globals_then(move || main_with_result(format
, &dst
));
275 if let Err(e
) = result
{
276 panic
!("{}", e
.to_string());
280 fn register_all() -> Vec
<(&'
static str, Option
<&'
static str>)> {
281 let mut long_codes
: Vec
<(&'
static str, Option
<&'
static str>)> = Vec
::new();
282 macro_rules
! register_diagnostics
{
283 ($
($ecode
:ident
: $message
:expr
,)* ; $
($code
:ident
,)*) => (
286 (stringify
!($ecode
), Some($message
)),
292 ].iter().cloned().map(|s
| (s
, None
)).collect
::<Vec
<_
>>());}
296 include
!(concat
!(env
!("OUT_DIR"), "/all_error_codes.rs"));