Skip to content

Commit

Permalink
Auto merge of #41991 - GuillaumeGomez:rustdoc-html-diff, r=nrc
Browse files Browse the repository at this point in the history
Add warnings when rustdoc html rendering differs
  • Loading branch information
bors committed Aug 31, 2017
2 parents 890c87b + b501d00 commit 97b01ab
Show file tree
Hide file tree
Showing 9 changed files with 406 additions and 56 deletions.
305 changes: 290 additions & 15 deletions src/Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/librustdoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ path = "lib.rs"
env_logger = { version = "0.4", default-features = false }
log = "0.3"
pulldown-cmark = { version = "0.0.14", default-features = false }
html-diff = "0.0.3"

[build-dependencies]
build_helper = { path = "../build_helper" }
Expand Down
33 changes: 31 additions & 2 deletions src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ use html::item_type::ItemType;
use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, RenderType};
use html::{highlight, layout};

use html_diff;

/// A pair of name and its optional document.
pub type NameDoc = (String, Option<String>);

Expand Down Expand Up @@ -1643,6 +1645,33 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
Ok(())
}

fn get_html_diff(w: &mut fmt::Formatter, md_text: &str, render_type: RenderType,
prefix: &str) -> fmt::Result {
let output = format!("{}", Markdown(md_text, render_type));
let old = format!("{}", Markdown(md_text, match render_type {
RenderType::Hoedown => RenderType::Pulldown,
RenderType::Pulldown => RenderType::Hoedown,
}));
let differences = html_diff::get_differences(&output, &old);
if !differences.is_empty() {
println!("Differences spotted in {:?}:\n{}",
md_text,
differences.iter()
.filter_map(|s| {
match *s {
html_diff::Difference::NodeText { ref elem_text,
ref opposite_elem_text,
.. }
if elem_text.trim() == opposite_elem_text.trim() => None,
_ => Some(format!("=> {}", s.to_string())),
}
})
.collect::<Vec<String>>()
.join("\n"));
}
write!(w, "<div class='docblock'>{}{}</div>", prefix, output)
}

fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLink,
render_type: RenderType, prefix: &str) -> fmt::Result {
if let Some(s) = item.doc_value() {
Expand All @@ -1652,7 +1681,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
} else {
format!("{}", &plain_summary_line(Some(s)))
};
write!(w, "<div class='docblock'>{}{}</div>", prefix, Markdown(&markdown, render_type))?;
get_html_diff(w, &markdown, render_type, prefix)?;
} else if !prefix.is_empty() {
write!(w, "<div class='docblock'>{}</div>", prefix)?;
}
Expand All @@ -1676,7 +1705,7 @@ fn render_assoc_const_value(item: &clean::Item) -> String {
fn document_full(w: &mut fmt::Formatter, item: &clean::Item,
render_type: RenderType, prefix: &str) -> fmt::Result {
if let Some(s) = item.doc_value() {
write!(w, "<div class='docblock'>{}{}</div>", prefix, Markdown(s, render_type))?;
get_html_diff(w, s, render_type, prefix)?;
} else if !prefix.is_empty() {
write!(w, "<div class='docblock'>{}</div>", prefix)?;
}
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
extern crate arena;
extern crate getopts;
extern crate env_logger;
extern crate html_diff;
extern crate libc;
extern crate rustc;
extern crate rustc_data_structures;
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@
//! # }
//! ```
//!
//! [functions-list]: #functions-1
//! [functions-list]: #functions-2
//!
//! ## io::Result
//!
Expand Down
37 changes: 2 additions & 35 deletions src/test/run-make/sysroot-crates-are-unstable/Makefile
Original file line number Diff line number Diff line change
@@ -1,35 +1,2 @@
-include ../tools.mk

# This is a whitelist of files which are stable crates or simply are not crates,
# we don't check for the instability of these crates as they're all stable!
STABLE_CRATES := \
std \
core \
proc_macro \
rsbegin.o \
rsend.o \
dllcrt2.o \
crt2.o \
clang_rt.%_dynamic.dylib

# Generate a list of all crates in the sysroot. To do this we list all files in
# rustc's sysroot, look at the filename, strip everything after the `-`, and
# strip the leading `lib` (if present)
SYSROOT := $(shell $(RUSTC) --print sysroot)
LIBS := $(wildcard $(SYSROOT)/lib/rustlib/$(TARGET)/lib/*)
LIBS := $(foreach lib,$(LIBS),$(notdir $(lib)))
LIBS := $(foreach lib,$(LIBS),$(word 1,$(subst -, ,$(lib))))
LIBS := $(foreach lib,$(LIBS),$(patsubst lib%,%,$(lib)))
LIBS := $(filter-out $(STABLE_CRATES),$(LIBS))

all: $(foreach lib,$(LIBS),check-crate-$(lib)-is-unstable)

check-crate-%-is-unstable:
@echo verifying $* is an unstable crate
@echo 'extern crate $*;' | \
$(RUSTC) - --crate-type rlib 2>&1 | cat > $(TMPDIR)/$*; \
true
@grep -q 'use of unstable library feature' $(TMPDIR)/$* || \
(echo crate $* is not unstable && \
cat $(TMPDIR)/$* && \
false)
all:
python2.7 test.py
71 changes: 71 additions & 0 deletions src/test/run-make/sysroot-crates-are-unstable/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# 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 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.

import sys
import os
from os import listdir
from os.path import isfile, join
from subprocess import PIPE, Popen


# This is a whitelist of files which are stable crates or simply are not crates,
# we don't check for the instability of these crates as they're all stable!
STABLE_CRATES = ['std', 'core', 'proc_macro', 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o',
'clang_rt']


def convert_to_string(s):
if s.__class__.__name__ == 'bytes':
return s.decode('utf-8')
return s


def exec_command(command, to_input=None):
child = None
if to_input is None:
child = Popen(command, stdout=PIPE, stderr=PIPE)
else:
child = Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE)
stdout, stderr = child.communicate(input=to_input)
return (convert_to_string(stdout), convert_to_string(stderr))


def check_lib(lib):
if lib['name'] in STABLE_CRATES:
return True
print('verifying if {} is an unstable crate'.format(lib['name']))
stdout, stderr = exec_command([os.environ['RUSTC'], '-', '--crate-type', 'rlib',
'--extern', '{}={}'.format(lib['name'], lib['path'])],
to_input='extern crate {};'.format(lib['name']))
if not 'use of unstable library feature' in '{}{}'.format(stdout, stderr):
print('crate {} "{}" is not unstable'.format(lib['name'], lib['path']))
print('{}{}'.format(stdout, stderr))
print('')
return False
return True

# Generate a list of all crates in the sysroot. To do this we list all files in
# rustc's sysroot, look at the filename, strip everything after the `-`, and
# strip the leading `lib` (if present)
def get_all_libs(dir_path):
return [{ 'path': join(dir_path, f), 'name': f[3:].split('-')[0] }
for f in listdir(dir_path)
if isfile(join(dir_path, f)) and f.endswith('.rlib') and f not in STABLE_CRATES]


sysroot = exec_command([os.environ['RUSTC'], '--print', 'sysroot'])[0].replace('\n', '')
libs = get_all_libs(join(sysroot, 'lib/rustlib/{}/lib'.format(os.environ['TARGET'])))

ret = 0
for lib in libs:
if not check_lib(lib):
# We continue so users can see all the not unstable crates.
ret = 1
sys.exit(ret)
6 changes: 3 additions & 3 deletions src/test/rustdoc/issue-29449.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ impl Foo {
/// # Panics
pub fn bar() {}

// @has - '//*[@id="examples-1"]//a' 'Examples'
// @has - '//*[@id="examples-2"]//a' 'Examples'
/// # Examples
pub fn bar_1() {}

// @has - '//*[@id="examples-2"]//a' 'Examples'
// @has - '//*[@id="panics-1"]//a' 'Panics'
// @has - '//*[@id="examples-4"]//a' 'Examples'
// @has - '//*[@id="panics-2"]//a' 'Panics'
/// # Examples
/// # Panics
pub fn bar_2() {}
Expand Down
6 changes: 6 additions & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ static EXCEPTIONS: &'static [&'static str] = &[
"openssl", // BSD+advertising clause, cargo, mdbook
"pest", // MPL2, mdbook via handlebars
"thread-id", // Apache-2.0, mdbook
"cssparser", // MPL-2.0, rustdoc
"smallvec", // MPL-2.0, rustdoc
"magenta-sys", // BSD-3-Clause, rustdoc
"magenta", // BSD-3-Clause, rustdoc
"cssparser-macros", // MPL-2.0, rustdoc
"selectors", // MPL-2.0, rustdoc
];

pub fn check(path: &Path, bad: &mut bool) {
Expand Down

0 comments on commit 97b01ab

Please sign in to comment.