Skip to content

Commit

Permalink
Rollup merge of rust-lang#90905 - GuillaumeGomez:empty-impl-blocks, r…
Browse files Browse the repository at this point in the history
…=jsha

Add empty impl blocks if they have documentation

Fixes rust-lang#90866.

The update for the test script is needed to count the number of impl blocks we have with only the struct. To be noted that with rust-lang#89676 merged, it wouldn't be needed (I don't know what is the status of it btw. cc ``@Mark-Simulacrum).``

It looks like this:

![Screenshot from 2021-11-14 16-51-28](https://user-images.githubusercontent.com/3050060/141689100-e57123c0-bf50-4c42-adf5-d991e169a0e4.png)

cc ``@jyn514``
r? ``@camelid``
  • Loading branch information
Dylan-DPC committed Jun 6, 2022
2 parents 760237f + eca12e3 commit e7503c6
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 19 deletions.
47 changes: 31 additions & 16 deletions src/etc/htmldocck.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@
in the specified file. The number of occurrences must match the given
count.
* `@count PATH XPATH TEXT COUNT` checks for the occurrence of the given XPath
with the given text in the specified file. The number of occurrences must
match the given count.
* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
A snapshot test captures a subtree of the DOM, at the location
determined by the XPath, and compares it to a pre-recorded value
Expand Down Expand Up @@ -382,23 +386,25 @@ def check_tree_attr(tree, path, attr, pat, regexp):
return ret


def check_tree_text(tree, path, pat, regexp):
# Returns the number of occurences matching the regex (`regexp`) and the text (`pat`).
def check_tree_text(tree, path, pat, regexp, stop_at_first):
path = normalize_xpath(path)
ret = False
match_count = 0
try:
for e in tree.findall(path):
try:
value = flatten(e)
except KeyError:
continue
else:
ret = check_string(value, pat, regexp)
if ret:
break
if check_string(value, pat, regexp):
match_count += 1
if stop_at_first:
break
except Exception:
print('Failed to get path "{}"'.format(path))
raise
return ret
return match_count


def get_tree_count(tree, path):
Expand Down Expand Up @@ -518,6 +524,19 @@ def print_err(lineno, context, err, message=None):
stderr("\t{}".format(context))


def get_nb_matching_elements(cache, c, regexp, stop_at_first):
tree = cache.get_tree(c.args[0])
pat, sep, attr = c.args[1].partition('/@')
if sep: # attribute
tree = cache.get_tree(c.args[0])
return check_tree_attr(tree, pat, attr, c.args[2], False)
else: # normalized text
pat = c.args[1]
if pat.endswith('/text()'):
pat = pat[:-7]
return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)


ERR_COUNT = 0


Expand All @@ -538,16 +557,7 @@ def check_command(c, cache):
ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp)
elif len(c.args) == 3: # @has/matches <path> <pat> <match> = XML tree test
cerr = "`XPATH PATTERN` did not match"
tree = cache.get_tree(c.args[0])
pat, sep, attr = c.args[1].partition('/@')
if sep: # attribute
tree = cache.get_tree(c.args[0])
ret = check_tree_attr(tree, pat, attr, c.args[2], regexp)
else: # normalized text
pat = c.args[1]
if pat.endswith('/text()'):
pat = pat[:-7]
ret = check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp)
ret = get_nb_matching_elements(cache, c, regexp, True) != 0
else:
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))

Expand All @@ -557,6 +567,11 @@ def check_command(c, cache):
found = get_tree_count(cache.get_tree(c.args[0]), c.args[1])
cerr = "Expected {} occurrences but found {}".format(expected, found)
ret = expected == found
elif len(c.args) == 4: # @count <path> <pat> <text> <count> = count test
expected = int(c.args[3])
found = get_nb_matching_elements(cache, c, False, False)
cerr = "Expected {} occurrences but found {}".format(expected, found)
ret = found == expected
else:
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))

Expand Down
7 changes: 7 additions & 0 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1600,6 +1600,13 @@ fn render_impl(
}

if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
if trait_.is_none() && i.inner_impl().items.is_empty() {
w.write_str(
"<div class=\"item-info\">\
<div class=\"stab empty-impl\">This impl block contains no items.</div>
</div>",
);
}
write!(
w,
"<div class=\"docblock\">{}</div>",
Expand Down
6 changes: 5 additions & 1 deletion src/librustdoc/html/static/css/themes/ayu.css
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,13 @@ details.undocumented > summary::before {
color: #000;
}

/* Created this empty rule to satisfy the theme checks. */
.stab.empty-impl {}

.stab.unstable,
.stab.deprecated,
.stab.portability {
.stab.portability,
.stab.empty-impl {
color: #c5c5c5;
background: #314559 !important;
border-style: none !important;
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/html/static/css/themes/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ details.undocumented > summary::before {
color: #ddd;
}

.stab.empty-impl { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/html/static/css/themes/light.css
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ details.undocumented > summary::before {
color: #000;
}

.stab.empty-impl { background: #FFF5D6; border-color: #FFC600; }
.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
.stab.portability { background: #F3DFFF; border-color: #b07bdb; }
Expand Down
5 changes: 3 additions & 2 deletions src/librustdoc/passes/stripper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ pub(crate) struct ImplStripper<'a> {
impl<'a> DocFolder for ImplStripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
if let clean::ImplItem(ref imp) = *i.kind {
// emptied none trait impls can be stripped
if imp.trait_.is_none() && imp.items.is_empty() {
// Impl blocks can be skipped if they are: empty; not a trait impl; and have no
// documentation.
if imp.trait_.is_none() && imp.items.is_empty() && i.doc_value().is_none() {
return None;
}
if let Some(did) = imp.for_.def_id(self.cache) {
Expand Down
20 changes: 20 additions & 0 deletions src/test/rustdoc/empty-impl-block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#![crate_name = "foo"]

// @has 'foo/struct.Foo.html'
pub struct Foo;

// @has - '//*[@class="docblock"]' 'Hello empty impl block!'
// @has - '//*[@class="item-info"]' 'This impl block contains no items.'
/// Hello empty impl block!
impl Foo {}
// We ensure that this empty impl block without doc isn't rendered.
// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 1
impl Foo {}

// Just to ensure that empty trait impl blocks are rendered.
pub struct Another;
pub trait Bar {}

// @has 'foo/struct.Another.html'
// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Another'
impl Bar for Another {}

0 comments on commit e7503c6

Please sign in to comment.