Skip to content

Commit e7503c6

Browse files
authored
Rollup merge of rust-lang#90905 - GuillaumeGomez:empty-impl-blocks, r=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``
2 parents 760237f + eca12e3 commit e7503c6

File tree

7 files changed

+68
-19
lines changed

7 files changed

+68
-19
lines changed

src/etc/htmldocck.py

+31-16
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@
9494
in the specified file. The number of occurrences must match the given
9595
count.
9696
97+
* `@count PATH XPATH TEXT COUNT` checks for the occurrence of the given XPath
98+
with the given text in the specified file. The number of occurrences must
99+
match the given count.
100+
97101
* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
98102
A snapshot test captures a subtree of the DOM, at the location
99103
determined by the XPath, and compares it to a pre-recorded value
@@ -382,23 +386,25 @@ def check_tree_attr(tree, path, attr, pat, regexp):
382386
return ret
383387

384388

385-
def check_tree_text(tree, path, pat, regexp):
389+
# Returns the number of occurences matching the regex (`regexp`) and the text (`pat`).
390+
def check_tree_text(tree, path, pat, regexp, stop_at_first):
386391
path = normalize_xpath(path)
387-
ret = False
392+
match_count = 0
388393
try:
389394
for e in tree.findall(path):
390395
try:
391396
value = flatten(e)
392397
except KeyError:
393398
continue
394399
else:
395-
ret = check_string(value, pat, regexp)
396-
if ret:
397-
break
400+
if check_string(value, pat, regexp):
401+
match_count += 1
402+
if stop_at_first:
403+
break
398404
except Exception:
399405
print('Failed to get path "{}"'.format(path))
400406
raise
401-
return ret
407+
return match_count
402408

403409

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

520526

527+
def get_nb_matching_elements(cache, c, regexp, stop_at_first):
528+
tree = cache.get_tree(c.args[0])
529+
pat, sep, attr = c.args[1].partition('/@')
530+
if sep: # attribute
531+
tree = cache.get_tree(c.args[0])
532+
return check_tree_attr(tree, pat, attr, c.args[2], False)
533+
else: # normalized text
534+
pat = c.args[1]
535+
if pat.endswith('/text()'):
536+
pat = pat[:-7]
537+
return check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp, stop_at_first)
538+
539+
521540
ERR_COUNT = 0
522541

523542

@@ -538,16 +557,7 @@ def check_command(c, cache):
538557
ret = check_string(cache.get_file(c.args[0]), c.args[1], regexp)
539558
elif len(c.args) == 3: # @has/matches <path> <pat> <match> = XML tree test
540559
cerr = "`XPATH PATTERN` did not match"
541-
tree = cache.get_tree(c.args[0])
542-
pat, sep, attr = c.args[1].partition('/@')
543-
if sep: # attribute
544-
tree = cache.get_tree(c.args[0])
545-
ret = check_tree_attr(tree, pat, attr, c.args[2], regexp)
546-
else: # normalized text
547-
pat = c.args[1]
548-
if pat.endswith('/text()'):
549-
pat = pat[:-7]
550-
ret = check_tree_text(cache.get_tree(c.args[0]), pat, c.args[2], regexp)
560+
ret = get_nb_matching_elements(cache, c, regexp, True) != 0
551561
else:
552562
raise InvalidCheck('Invalid number of @{} arguments'.format(c.cmd))
553563

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

src/librustdoc/html/render/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,13 @@ fn render_impl(
16001600
}
16011601

16021602
if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
1603+
if trait_.is_none() && i.inner_impl().items.is_empty() {
1604+
w.write_str(
1605+
"<div class=\"item-info\">\
1606+
<div class=\"stab empty-impl\">This impl block contains no items.</div>
1607+
</div>",
1608+
);
1609+
}
16031610
write!(
16041611
w,
16051612
"<div class=\"docblock\">{}</div>",

src/librustdoc/html/static/css/themes/ayu.css

+5-1
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,13 @@ details.undocumented > summary::before {
281281
color: #000;
282282
}
283283

284+
/* Created this empty rule to satisfy the theme checks. */
285+
.stab.empty-impl {}
286+
284287
.stab.unstable,
285288
.stab.deprecated,
286-
.stab.portability {
289+
.stab.portability,
290+
.stab.empty-impl {
287291
color: #c5c5c5;
288292
background: #314559 !important;
289293
border-style: none !important;

src/librustdoc/html/static/css/themes/dark.css

+1
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ details.undocumented > summary::before {
266266
color: #ddd;
267267
}
268268

269+
.stab.empty-impl { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
269270
.stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; }
270271
.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; }
271272
.stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; }

src/librustdoc/html/static/css/themes/light.css

+1
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ details.undocumented > summary::before {
255255
color: #000;
256256
}
257257

258+
.stab.empty-impl { background: #FFF5D6; border-color: #FFC600; }
258259
.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
259260
.stab.deprecated { background: #ffc4c4; border-color: #db7b7b; }
260261
.stab.portability { background: #F3DFFF; border-color: #b07bdb; }

src/librustdoc/passes/stripper.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,9 @@ pub(crate) struct ImplStripper<'a> {
124124
impl<'a> DocFolder for ImplStripper<'a> {
125125
fn fold_item(&mut self, i: Item) -> Option<Item> {
126126
if let clean::ImplItem(ref imp) = *i.kind {
127-
// emptied none trait impls can be stripped
128-
if imp.trait_.is_none() && imp.items.is_empty() {
127+
// Impl blocks can be skipped if they are: empty; not a trait impl; and have no
128+
// documentation.
129+
if imp.trait_.is_none() && imp.items.is_empty() && i.doc_value().is_none() {
129130
return None;
130131
}
131132
if let Some(did) = imp.for_.def_id(self.cache) {

src/test/rustdoc/empty-impl-block.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![crate_name = "foo"]
2+
3+
// @has 'foo/struct.Foo.html'
4+
pub struct Foo;
5+
6+
// @has - '//*[@class="docblock"]' 'Hello empty impl block!'
7+
// @has - '//*[@class="item-info"]' 'This impl block contains no items.'
8+
/// Hello empty impl block!
9+
impl Foo {}
10+
// We ensure that this empty impl block without doc isn't rendered.
11+
// @count - '//*[@class="impl has-srclink"]' 'impl Foo' 1
12+
impl Foo {}
13+
14+
// Just to ensure that empty trait impl blocks are rendered.
15+
pub struct Another;
16+
pub trait Bar {}
17+
18+
// @has 'foo/struct.Another.html'
19+
// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Another'
20+
impl Bar for Another {}

0 commit comments

Comments
 (0)