diff --git a/mk/crates.mk b/mk/crates.mk index 367c25a8a6d..546b16c1b85 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -58,7 +58,7 @@ RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \ rustc_data_structures HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros CRATES := $(TARGET_CRATES) $(HOST_CRATES) -TOOLS := compiletest rustdoc rustc rustbook +TOOLS := compiletest rustdoc rustc rustbook error-index-generator DEPS_core := DEPS_libc := core @@ -107,10 +107,12 @@ TOOL_DEPS_compiletest := test getopts TOOL_DEPS_rustdoc := rustdoc TOOL_DEPS_rustc := rustc_driver TOOL_DEPS_rustbook := std rustdoc +TOOL_DEPS_error-index-generator := rustdoc syntax serialize TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs TOOL_SOURCE_rustc := $(S)src/driver/driver.rs TOOL_SOURCE_rustbook := $(S)src/rustbook/main.rs +TOOL_SOURCE_error-index-generator := $(S)src/error-index-generator/main.rs ONLY_RLIB_core := 1 ONLY_RLIB_libc := 1 diff --git a/mk/docs.mk b/mk/docs.mk index d179d337faa..6f16e0d9578 100644 --- a/mk/docs.mk +++ b/mk/docs.mk @@ -71,6 +71,10 @@ RUSTBOOK_EXE = $(HBIN2_H_$(CFG_BUILD))/rustbook$(X_$(CFG_BUILD)) # ./configure RUSTBOOK = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(RUSTBOOK_EXE) +# The error-index-generator executable... +ERR_IDX_GEN_EXE = $(HBIN2_H_$(CFG_BUILD))/error-index-generator$(X_$(CFG_BUILD)) +ERR_IDX_GEN = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE) + D := $(S)src/doc DOC_TARGETS := trpl style @@ -288,3 +292,9 @@ doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/ @$(call E, rustbook: $@) $(Q)rm -rf doc/style $(Q)$(RUSTBOOK) build $(S)src/doc/style doc/style + +error-index: doc/error-index.html + +doc/error-index.html: $(ERR_IDX_GEN_EXE) | doc/ + $(Q)$(call E, error-index-generator: $@) + $(Q)$(ERR_IDX_GEN) diff --git a/mk/prepare.mk b/mk/prepare.mk index 1382d160e13..1ae6a61c95a 100644 --- a/mk/prepare.mk +++ b/mk/prepare.mk @@ -70,7 +70,7 @@ define PREPARE_MAN $(Q)$(PREPARE_MAN_CMD) $(PREPARE_SOURCE_MAN_DIR)/$(1) $(PREPARE_DEST_MAN_DIR)/$(1) endef -PREPARE_TOOLS = $(filter-out compiletest rustbook, $(TOOLS)) +PREPARE_TOOLS = $(filter-out compiletest rustbook error-index-generator, $(TOOLS)) # $(1) is tool diff --git a/src/error-index-generator/main.rs b/src/error-index-generator/main.rs new file mode 100644 index 00000000000..1f18eded3c9 --- /dev/null +++ b/src/error-index-generator/main.rs @@ -0,0 +1,111 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_private, rustdoc)] + +extern crate syntax; +extern crate rustdoc; +extern crate serialize as rustc_serialize; + +use std::collections::BTreeMap; +use std::fs::{read_dir, File}; +use std::io::{Read, Write}; +use std::path::Path; +use std::error::Error; + +use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap}; + +use rustdoc::html::markdown::Markdown; +use rustc_serialize::json; + +/// Load all the metadata files from `metadata_dir` into an in-memory map. +fn load_all_errors(metadata_dir: &Path) -> Result> { + let mut all_errors = BTreeMap::new(); + + for entry in try!(read_dir(metadata_dir)) { + let path = try!(entry).path(); + + let mut metadata_str = String::new(); + try!( + File::open(&path).and_then(|mut f| + f.read_to_string(&mut metadata_str)) + ); + + let some_errors: ErrorMetadataMap = try!(json::decode(&metadata_str)); + + for (err_code, info) in some_errors { + all_errors.insert(err_code, info); + } + } + + Ok(all_errors) +} + +/// Output an HTML page for the errors in `err_map` to `output_path`. +fn render_error_page(err_map: &ErrorMetadataMap, output_path: &Path) -> Result<(), Box> { + let mut output_file = try!(File::create(output_path)); + + try!(write!(&mut output_file, +r##" + + +Rust Compiler Error Index + + + +"## + )); + + try!(write!(&mut output_file, "

Rust Compiler Error Index

\n")); + + for (err_code, info) in err_map.iter() { + // Enclose each error in a div so they can be shown/hidden en masse. + let desc_desc = match info.description { + Some(_) => "error-described", + None => "error-undescribed" + }; + let use_desc = match info.use_site { + Some(_) => "error-used", + None => "error-unused" + }; + try!(write!(&mut output_file, "
", desc_desc, use_desc)); + + // Error title (with self-link). + try!(write!(&mut output_file, + "

{0}

\n", + err_code + )); + + // Description rendered as markdown. + match info.description { + Some(ref desc) => try!(write!(&mut output_file, "{}", Markdown(desc))), + None => try!(write!(&mut output_file, "

No description.

\n")) + } + + try!(write!(&mut output_file, "
\n")); + } + + try!(write!(&mut output_file, "\n")); + + Ok(()) +} + +fn main_with_result() -> Result<(), Box> { + let metadata_dir = get_metadata_dir(); + let err_map = try!(load_all_errors(&metadata_dir)); + try!(render_error_page(&err_map, Path::new("doc/error-index.html"))); + Ok(()) +} + +fn main() { + if let Err(e) = main_with_result() { + panic!("{}", e.description()); + } +}