Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compile-fail test in rustdoc #30726

Merged
merged 5 commits into from
Feb 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion mk/docs.mk
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ 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)
ERR_IDX_GEN_MD = $(RPATH_VAR2_T_$(CFG_BUILD)_H_$(CFG_BUILD)) $(ERR_IDX_GEN_EXE) markdown

D := $(S)src/doc

Expand Down Expand Up @@ -217,6 +218,12 @@ doc/style/index.html: $(RUSTBOOK_EXE) $(wildcard $(S)/src/doc/style/*.md) | doc/

error-index: doc/error-index.html

doc/error-index.html: $(ERR_IDX_GEN_EXE) | doc/
# Metadata used to generate the index is created as a side effect of
# the build so this depends on every crate being up to date.
doc/error-index.html: $(ERR_IDX_GEN_EXE) $(CSREQ$(2)_T_$(CFG_BUILD)_H_$(CFG_BUILD)) | doc/
$(Q)$(call E, error-index-generator: $@)
$(Q)$(ERR_IDX_GEN)

doc/error-index.md: $(ERR_IDX_GEN_EXE) $(CSREQ$(2)_T_$(CFG_BUILD)_H_$(CFG_BUILD)) | doc/
$(Q)$(call E, error-index-generator: $@)
$(Q)$(ERR_IDX_GEN_MD)
43 changes: 33 additions & 10 deletions mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -298,14 +298,14 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
check-stage$(1)-T-$(2)-H-$(3)-rfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
check-stage$(1)-T-$(2)-H-$(3)-rustdocck-exec \
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-gdb-exec \
check-stage$(1)-T-$(2)-H-$(3)-debuginfo-lldb-exec \
check-stage$(1)-T-$(2)-H-$(3)-codegen-exec \
Expand Down Expand Up @@ -673,8 +673,8 @@ CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \
CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
CTEST_DEPS_codegen-units_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_UNITS_TESTS)
CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
$(S)src/etc/htmldocck.py
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
$(S)src/etc/htmldocck.py

endef

Expand Down Expand Up @@ -892,6 +892,28 @@ $(foreach host,$(CFG_HOST), \
$(foreach crate,$(TEST_DOC_CRATES), \
$(eval $(call DEF_CRATE_DOC_TEST,$(stage),$(target),$(host),$(crate)))))))

define DEF_DOC_TEST_ERROR_INDEX

check-stage$(1)-T-$(2)-H-$(3)-doc-error-index-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index)

ifeq ($(2),$$(CFG_BUILD))
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index): \
$$(TEST_SREQ$(1)_T_$(2)_H_$(3)) \
doc/error-index.md
$$(Q)touch [email protected]_time
$$(RUSTDOC_$(1)_T_$(2)_H_$(3)) --test doc/error-index.md
$$(Q)touch -r [email protected]_time $$@ && rm [email protected]_time
else
$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-error-index):
$$(Q)touch $$@
endif
endef

$(foreach host,$(CFG_HOST), \
$(foreach target,$(CFG_TARGET), \
$(foreach stage,$(STAGES), \
$(eval $(call DEF_DOC_TEST_ERROR_INDEX,$(stage),$(target),$(host))))))

######################################################################
# Shortcut rules
######################################################################
Expand All @@ -901,7 +923,7 @@ TEST_GROUPS = \
$(foreach crate,$(TEST_CRATES),$(crate)) \
$(foreach crate,$(TEST_DOC_CRATES),doc-crate-$(crate)) \
rpass \
rpass-valgrind \
rpass-valgrind \
rpass-full \
rfail-full \
cfail-full \
Expand All @@ -918,7 +940,7 @@ TEST_GROUPS = \
$(foreach docname,$(DOC_NAMES),doc-$(docname)) \
pretty \
pretty-rpass \
pretty-rpass-valgrind \
pretty-rpass-valgrind \
pretty-rpass-full \
pretty-rfail-full \
pretty-rfail \
Expand Down Expand Up @@ -987,7 +1009,8 @@ define DEF_CHECK_DOC_FOR_STAGE
check-stage$(1)-docs: $$(foreach docname,$$(DOC_NAMES), \
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-$$(docname)) \
$$(foreach crate,$$(TEST_DOC_CRATES), \
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-crate-$$(crate))
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-crate-$$(crate)) \
check-stage$(1)-T-$$(CFG_BUILD)-H-$$(CFG_BUILD)-doc-error-index-exec
endef

$(foreach stage,$(STAGES), \
Expand Down
154 changes: 120 additions & 34 deletions src/error-index-generator/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,37 +21,41 @@ use std::env;
use std::path::Path;
use std::error::Error;

use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap};
use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};

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<ErrorMetadataMap, Box<Error>> {
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));
enum OutputFormat {
HTML(HTMLFormatter),
Markdown(MarkdownFormatter),
Unknown(String),
}

for (err_code, info) in some_errors {
all_errors.insert(err_code, info);
impl OutputFormat {
fn from(format: &str) -> OutputFormat {
match &*format.to_lowercase() {
"html" => OutputFormat::HTML(HTMLFormatter),
"markdown" => OutputFormat::Markdown(MarkdownFormatter),
s => OutputFormat::Unknown(s.to_owned()),
}
}
}

Ok(all_errors)
trait Formatter {
fn header(&self, output: &mut Write) -> Result<(), Box<Error>>;
fn title(&self, output: &mut Write) -> Result<(), Box<Error>>;
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
err_code: &str) -> Result<(), Box<Error>>;
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>>;
}

/// 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<Error>> {
let mut output_file = try!(File::create(output_path));
struct HTMLFormatter;
struct MarkdownFormatter;

try!(write!(&mut output_file,
r##"<!DOCTYPE html>
impl Formatter for HTMLFormatter {
fn header(&self, output: &mut Write) -> Result<(), Box<Error>> {
try!(write!(output, r##"<!DOCTYPE html>
<html>
<head>
<title>Rust Compiler Error Index</title>
Expand All @@ -66,12 +70,17 @@ r##"<!DOCTYPE html>
</style>
</head>
<body>
"##
));
"##));
Ok(())
}

try!(write!(&mut output_file, "<h1>Rust Compiler Error Index</h1>\n"));
fn title(&self, output: &mut Write) -> Result<(), Box<Error>> {
try!(write!(output, "<h1>Rust Compiler Error Index</h1>\n"));
Ok(())
}

for (err_code, info) in err_map {
fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
err_code: &str) -> Result<(), Box<Error>> {
// Enclose each error in a div so they can be shown/hidden en masse.
let desc_desc = match info.description {
Some(_) => "error-described",
Expand All @@ -81,37 +90,114 @@ r##"<!DOCTYPE html>
Some(_) => "error-used",
None => "error-unused",
};
try!(write!(&mut output_file, "<div class=\"{} {}\">", desc_desc, use_desc));
try!(write!(output, "<div class=\"{} {}\">", desc_desc, use_desc));

// Error title (with self-link).
try!(write!(&mut output_file,
try!(write!(output,
"<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\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, "<p>No description.</p>\n")),
Some(ref desc) => try!(write!(output, "{}", Markdown(desc))),
None => try!(write!(output, "<p>No description.</p>\n")),
}

try!(write!(&mut output_file, "</div>\n"));
try!(write!(output, "</div>\n"));
Ok(())
}

try!(write!(&mut output_file, "</body>\n</html>"));
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
try!(write!(output, "</body>\n</html>"));
Ok(())
}
}

Ok(())
impl Formatter for MarkdownFormatter {
#[allow(unused_variables)]
fn header(&self, output: &mut Write) -> Result<(), Box<Error>> {
Ok(())
}

fn title(&self, output: &mut Write) -> Result<(), Box<Error>> {
try!(write!(output, "# Rust Compiler Error Index\n"));
Ok(())
}

fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
err_code: &str) -> Result<(), Box<Error>> {
Ok(match info.description {
Some(ref desc) => try!(write!(output, "## {}\n{}\n", err_code, desc)),
None => (),
})
}

#[allow(unused_variables)]
fn footer(&self, output: &mut Write) -> Result<(), Box<Error>> {
Ok(())
}
}

/// Load all the metadata files from `metadata_dir` into an in-memory map.
fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<Error>> {
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<T: Formatter>(err_map: &ErrorMetadataMap, output_path: &Path,
formatter: T) -> Result<(), Box<Error>> {
let mut output_file = try!(File::create(output_path));

try!(formatter.header(&mut output_file));
try!(formatter.title(&mut output_file));

for (err_code, info) in err_map {
try!(formatter.error_code_block(&mut output_file, info, err_code));
}

formatter.footer(&mut output_file)
}

fn main_with_result() -> Result<(), Box<Error>> {
fn main_with_result(format: OutputFormat) -> Result<(), Box<Error>> {
let build_arch = try!(env::var("CFG_BUILD"));
let metadata_dir = get_metadata_dir(&build_arch);
let err_map = try!(load_all_errors(&metadata_dir));
try!(render_error_page(&err_map, Path::new("doc/error-index.html")));
match format {
OutputFormat::Unknown(s) => panic!("Unknown output format: {}", s),
OutputFormat::HTML(h) => try!(render_error_page(&err_map,
Path::new("doc/error-index.html"),
h)),
OutputFormat::Markdown(m) => try!(render_error_page(&err_map,
Path::new("doc/error-index.md"),
m)),
}
Ok(())
}

fn parse_args() -> OutputFormat {
for arg in env::args().skip(1) {
return OutputFormat::from(&arg);
}
OutputFormat::from("html")
}

fn main() {
if let Err(e) = main_with_result() {
if let Err(e) = main_with_result(parse_args()) {
panic!("{}", e.description());
}
}
Loading