Skip to content

Commit 016cef9

Browse files
committed
Auto merge of #25062 - michaelsproul:html-error-index, r=alexcrichton
This PR adds a program which uses the JSON output from #24884 to generate a webpage with descriptions of each diagnostic error. The page is constructed by hand, with calls to `rustdoc`'s markdown renderers where needed. I opted to generate HTML directly as I think it's more flexible than generating a markdown file and feeding it into the `rustdoc` executable. I envision adding the ability to filter errors by their properties (description, no description, used, unused), which is infeasible using the whole-file markdown approach due to the need to wrap each error in a `<div>` (markdown inside tags isn't rendered). Architecturally, I wasn't sure how to add this generator to the distribution. For the moment I've settled on a separate Rust program in `src/etc/` that gets compiled and run by a custom makefile rule. This approach doesn't seem too hackish, but I'm unsure if my usage of makefile variables is correct, particularly the call to `rustc` (and the `LD_LIBRARY_PATH` weirdness). Other options I considered were: * Integrate the error-index generator into `rustdoc` so that it gets invoked via a flag and can be built as part of `rustdoc`. * Add the error-index-generator as a "tool" to the `TOOLS` array, and make use of the facilities for building tools. The main reason I didn't do this was because it seemed like I'd need to add lots of stuff. I'm happy to investigate this further if it's the preferred method.
2 parents 6afa669 + b9d484f commit 016cef9

File tree

4 files changed

+134
-3
lines changed

4 files changed

+134
-3
lines changed

mk/crates.mk

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
5858
rustc_data_structures
5959
HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
6060
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
61-
TOOLS := compiletest rustdoc rustc rustbook
61+
TOOLS := compiletest rustdoc rustc rustbook error-index-generator
6262

6363
DEPS_core :=
6464
DEPS_libc := core
@@ -107,10 +107,12 @@ TOOL_DEPS_compiletest := test getopts
107107
TOOL_DEPS_rustdoc := rustdoc
108108
TOOL_DEPS_rustc := rustc_driver
109109
TOOL_DEPS_rustbook := std rustdoc
110+
TOOL_DEPS_error-index-generator := rustdoc syntax serialize
110111
TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs
111112
TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs
112113
TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
113114
TOOL_SOURCE_rustbook := $(S)src/rustbook/main.rs
115+
TOOL_SOURCE_error-index-generator := $(S)src/error-index-generator/main.rs
114116

115117
ONLY_RLIB_core := 1
116118
ONLY_RLIB_libc := 1

mk/docs.mk

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,13 @@ RUSTBOOK_EXE = $(HBIN2_H_$(CFG_BUILD))/rustbook$(X_$(CFG_BUILD))
7171
# ./configure
7272
RUSTBOOK = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(RUSTBOOK_EXE)
7373

74+
# The error-index-generator executable...
75+
ERR_IDX_GEN_EXE = $(HBIN2_H_$(CFG_BUILD))/error-index-generator$(X_$(CFG_BUILD))
76+
ERR_IDX_GEN = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE)
77+
7478
D := $(S)src/doc
7579

76-
DOC_TARGETS := trpl style
80+
DOC_TARGETS := trpl style error-index
7781
COMPILER_DOC_TARGETS :=
7882
DOC_L10N_TARGETS :=
7983

@@ -288,3 +292,9 @@ doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/
288292
@$(call E, rustbook: $@)
289293
$(Q)rm -rf doc/style
290294
$(Q)$(RUSTBOOK) build $(S)src/doc/style doc/style
295+
296+
error-index: doc/error-index.html
297+
298+
doc/error-index.html: $(ERR_IDX_GEN_EXE) | doc/
299+
$(Q)$(call E, error-index-generator: $@)
300+
$(Q)$(ERR_IDX_GEN)

mk/prepare.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ define PREPARE_MAN
7070
$(Q)$(PREPARE_MAN_CMD) $(PREPARE_SOURCE_MAN_DIR)/$(1) $(PREPARE_DEST_MAN_DIR)/$(1)
7171
endef
7272

73-
PREPARE_TOOLS = $(filter-out compiletest rustbook, $(TOOLS))
73+
PREPARE_TOOLS = $(filter-out compiletest rustbook error-index-generator, $(TOOLS))
7474

7575

7676
# $(1) is tool

src/error-index-generator/main.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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.
4+
//
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.
10+
11+
#![feature(rustc_private, rustdoc)]
12+
13+
extern crate syntax;
14+
extern crate rustdoc;
15+
extern crate serialize as rustc_serialize;
16+
17+
use std::collections::BTreeMap;
18+
use std::fs::{read_dir, File};
19+
use std::io::{Read, Write};
20+
use std::path::Path;
21+
use std::error::Error;
22+
23+
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap};
24+
25+
use rustdoc::html::markdown::Markdown;
26+
use rustc_serialize::json;
27+
28+
/// Load all the metadata files from `metadata_dir` into an in-memory map.
29+
fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<Error>> {
30+
let mut all_errors = BTreeMap::new();
31+
32+
for entry in try!(read_dir(metadata_dir)) {
33+
let path = try!(entry).path();
34+
35+
let mut metadata_str = String::new();
36+
try!(
37+
File::open(&path).and_then(|mut f|
38+
f.read_to_string(&mut metadata_str))
39+
);
40+
41+
let some_errors: ErrorMetadataMap = try!(json::decode(&metadata_str));
42+
43+
for (err_code, info) in some_errors {
44+
all_errors.insert(err_code, info);
45+
}
46+
}
47+
48+
Ok(all_errors)
49+
}
50+
51+
/// Output an HTML page for the errors in `err_map` to `output_path`.
52+
fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Path) -> Result<(), Box<Error>> {
53+
let mut output_file = try!(File::create(output_path));
54+
55+
try!(write!(&mut output_file,
56+
r##"<!DOCTYPE html>
57+
<html>
58+
<head>
59+
<title>Rust Compiler Error Index</title>
60+
<meta charset="utf-8">
61+
<!-- Include rust.css after main.css so its rules take priority. -->
62+
<link rel="stylesheet" type="text/css" href="main.css"/>
63+
<link rel="stylesheet" type="text/css" href="rust.css"/>
64+
<style>
65+
.error-undescribed {{
66+
display: none;
67+
}}
68+
</style>
69+
</head>
70+
<body>
71+
"##
72+
));
73+
74+
try!(write!(&mut output_file, "<h1>Rust Compiler Error Index</h1>\n"));
75+
76+
for (err_code, info) in err_map.iter() {
77+
// Enclose each error in a div so they can be shown/hidden en masse.
78+
let desc_desc = match info.description {
79+
Some(_) => "error-described",
80+
None => "error-undescribed"
81+
};
82+
let use_desc = match info.use_site {
83+
Some(_) => "error-used",
84+
None => "error-unused"
85+
};
86+
try!(write!(&mut output_file, "<div class=\"{} {}\">", desc_desc, use_desc));
87+
88+
// Error title (with self-link).
89+
try!(write!(&mut output_file,
90+
"<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
91+
err_code
92+
));
93+
94+
// Description rendered as markdown.
95+
match info.description {
96+
Some(ref desc) => try!(write!(&mut output_file, "{}", Markdown(desc))),
97+
None => try!(write!(&mut output_file, "<p>No description.</p>\n"))
98+
}
99+
100+
try!(write!(&mut output_file, "</div>\n"));
101+
}
102+
103+
try!(write!(&mut output_file, "</body>\n</html>"));
104+
105+
Ok(())
106+
}
107+
108+
fn main_with_result() -> Result<(), Box<Error>> {
109+
let metadata_dir = get_metadata_dir();
110+
let err_map = try!(load_all_errors(&metadata_dir));
111+
try!(render_error_page(&err_map, Path::new("doc/error-index.html")));
112+
Ok(())
113+
}
114+
115+
fn main() {
116+
if let Err(e) = main_with_result() {
117+
panic!("{}", e.description());
118+
}
119+
}

0 commit comments

Comments
 (0)