Skip to content

Commit 1f5d69d

Browse files
committed
Auto merge of #74855 - jyn514:separate-lints, r=Manishearth
Separate `missing_doc_code_examples` from intra-doc links These two lints have no relation other than both being nightly-only. This allows stabilizing intra-doc links without stabilizing `missing_doc_code_examples`. Fixes one of the issues spotted by @ollie27 in #74430 (comment). r? @Manishearth
2 parents 1454bbd + c3f5556 commit 1f5d69d

File tree

5 files changed

+113
-103
lines changed

5 files changed

+113
-103
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::clean::*;
2323
use crate::core::DocContext;
2424
use crate::fold::DocFolder;
2525
use crate::html::markdown::markdown_links;
26-
use crate::passes::{look_for_tests, Pass};
26+
use crate::passes::Pass;
2727

2828
use super::span_of_attrs;
2929

@@ -508,8 +508,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
508508
let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
509509
trace!("got documentation '{}'", dox);
510510

511-
look_for_tests(&cx, &dox, &item, true);
512-
513511
// find item's parent to resolve `Self` in item's docs below
514512
let parent_name = self.cx.as_local_hir_id(item.def_id).and_then(|item_hir| {
515513
let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir);
+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//! This pass is overloaded and runs two different lints.
2+
//!
3+
//! - MISSING_DOC_CODE_EXAMPLES: this looks for public items missing doc-tests
4+
//! - PRIVATE_DOC_TESTS: this looks for private items with doc-tests.
5+
6+
use super::{span_of_attrs, Pass};
7+
use crate::clean::*;
8+
use crate::core::DocContext;
9+
use crate::fold::DocFolder;
10+
use crate::html::markdown::{find_testable_code, ErrorCodes, LangString};
11+
use rustc_session::lint;
12+
13+
pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
14+
name: "check-private-items-doc-tests",
15+
run: check_private_items_doc_tests,
16+
description: "check private items doc tests",
17+
};
18+
19+
struct PrivateItemDocTestLinter<'a, 'tcx> {
20+
cx: &'a DocContext<'tcx>,
21+
}
22+
23+
impl<'a, 'tcx> PrivateItemDocTestLinter<'a, 'tcx> {
24+
fn new(cx: &'a DocContext<'tcx>) -> Self {
25+
PrivateItemDocTestLinter { cx }
26+
}
27+
}
28+
29+
pub fn check_private_items_doc_tests(krate: Crate, cx: &DocContext<'_>) -> Crate {
30+
let mut coll = PrivateItemDocTestLinter::new(cx);
31+
32+
coll.fold_crate(krate)
33+
}
34+
35+
impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> {
36+
fn fold_item(&mut self, item: Item) -> Option<Item> {
37+
let cx = self.cx;
38+
let dox = item.attrs.collapsed_doc_value().unwrap_or_else(String::new);
39+
40+
look_for_tests(&cx, &dox, &item);
41+
42+
self.fold_item_recur(item)
43+
}
44+
}
45+
46+
pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
47+
let hir_id = match cx.as_local_hir_id(item.def_id) {
48+
Some(hir_id) => hir_id,
49+
None => {
50+
// If non-local, no need to check anything.
51+
return;
52+
}
53+
};
54+
55+
struct Tests {
56+
found_tests: usize,
57+
}
58+
59+
impl crate::test::Tester for Tests {
60+
fn add_test(&mut self, _: String, _: LangString, _: usize) {
61+
self.found_tests += 1;
62+
}
63+
}
64+
65+
let mut tests = Tests { found_tests: 0 };
66+
67+
find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
68+
69+
if tests.found_tests == 0 {
70+
use ItemEnum::*;
71+
72+
let should_report = match item.inner {
73+
ExternCrateItem(_, _) | ImportItem(_) | PrimitiveItem(_) | KeywordItem(_) => false,
74+
_ => true,
75+
};
76+
if should_report {
77+
debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
78+
let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
79+
cx.tcx.struct_span_lint_hir(
80+
lint::builtin::MISSING_DOC_CODE_EXAMPLES,
81+
hir_id,
82+
sp,
83+
|lint| lint.build("missing code example in this documentation").emit(),
84+
);
85+
}
86+
} else if rustc_feature::UnstableFeatures::from_environment().is_nightly_build()
87+
&& tests.found_tests > 0
88+
&& !cx.renderinfo.borrow().access_levels.is_public(item.def_id)
89+
{
90+
cx.tcx.struct_span_lint_hir(
91+
lint::builtin::PRIVATE_DOC_TESTS,
92+
hir_id,
93+
span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
94+
|lint| lint.build("documentation test in private item").emit(),
95+
);
96+
}
97+
}

src/librustdoc/passes/mod.rs

+2-50
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
44
use rustc_hir::def_id::{DefId, DefIdSet};
55
use rustc_middle::middle::privacy::AccessLevels;
6-
use rustc_session::lint;
76
use rustc_span::{InnerSpan, Span, DUMMY_SP};
87
use std::mem;
98
use std::ops::Range;
@@ -12,7 +11,6 @@ use self::Condition::*;
1211
use crate::clean::{self, GetDefId, Item};
1312
use crate::core::DocContext;
1413
use crate::fold::{DocFolder, StripItem};
15-
use crate::html::markdown::{find_testable_code, ErrorCodes, LangString};
1614

1715
mod collapse_docs;
1816
pub use self::collapse_docs::COLLAPSE_DOCS;
@@ -35,8 +33,8 @@ pub use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
3533
mod collect_intra_doc_links;
3634
pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
3735

38-
mod private_items_doc_tests;
39-
pub use self::private_items_doc_tests::CHECK_PRIVATE_ITEMS_DOC_TESTS;
36+
mod doc_test_lints;
37+
pub use self::doc_test_lints::CHECK_PRIVATE_ITEMS_DOC_TESTS;
4038

4139
mod collect_trait_impls;
4240
pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
@@ -312,52 +310,6 @@ impl DocFolder for ImportStripper {
312310
}
313311
}
314312

315-
pub fn look_for_tests<'tcx>(
316-
cx: &DocContext<'tcx>,
317-
dox: &str,
318-
item: &Item,
319-
check_missing_code: bool,
320-
) {
321-
let hir_id = match cx.as_local_hir_id(item.def_id) {
322-
Some(hir_id) => hir_id,
323-
None => {
324-
// If non-local, no need to check anything.
325-
return;
326-
}
327-
};
328-
329-
struct Tests {
330-
found_tests: usize,
331-
}
332-
333-
impl crate::test::Tester for Tests {
334-
fn add_test(&mut self, _: String, _: LangString, _: usize) {
335-
self.found_tests += 1;
336-
}
337-
}
338-
339-
let mut tests = Tests { found_tests: 0 };
340-
341-
find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
342-
343-
if check_missing_code && tests.found_tests == 0 {
344-
let sp = span_of_attrs(&item.attrs).unwrap_or(item.source.span());
345-
cx.tcx.struct_span_lint_hir(lint::builtin::MISSING_DOC_CODE_EXAMPLES, hir_id, sp, |lint| {
346-
lint.build("missing code example in this documentation").emit()
347-
});
348-
} else if !check_missing_code
349-
&& tests.found_tests > 0
350-
&& !cx.renderinfo.borrow().access_levels.is_public(item.def_id)
351-
{
352-
cx.tcx.struct_span_lint_hir(
353-
lint::builtin::PRIVATE_DOC_TESTS,
354-
hir_id,
355-
span_of_attrs(&item.attrs).unwrap_or(item.source.span()),
356-
|lint| lint.build("documentation test in private item").emit(),
357-
);
358-
}
359-
}
360-
361313
/// Returns a span encompassing all the given attributes.
362314
crate fn span_of_attrs(attrs: &clean::Attributes) -> Option<Span> {
363315
if attrs.doc_strings.is_empty() {

src/librustdoc/passes/private_items_doc_tests.rs

-37
This file was deleted.

src/test/rustdoc-ui/lint-group.stderr

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
error: missing code example in this documentation
2+
--> $DIR/lint-group.rs:16:1
3+
|
4+
LL | /// wait, this doesn't have a doctest?
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/lint-group.rs:7:9
9+
|
10+
LL | #![deny(rustdoc)]
11+
| ^^^^^^^
12+
= note: `#[deny(missing_doc_code_examples)]` implied by `#[deny(rustdoc)]`
13+
114
error: documentation test in private item
215
--> $DIR/lint-group.rs:19:1
316
|
@@ -29,18 +42,5 @@ LL | #![deny(rustdoc)]
2942
= note: `#[deny(intra_doc_link_resolution_failure)]` implied by `#[deny(rustdoc)]`
3043
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
3144

32-
error: missing code example in this documentation
33-
--> $DIR/lint-group.rs:16:1
34-
|
35-
LL | /// wait, this doesn't have a doctest?
36-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37-
|
38-
note: the lint level is defined here
39-
--> $DIR/lint-group.rs:7:9
40-
|
41-
LL | #![deny(rustdoc)]
42-
| ^^^^^^^
43-
= note: `#[deny(missing_doc_code_examples)]` implied by `#[deny(rustdoc)]`
44-
4545
error: aborting due to 3 previous errors
4646

0 commit comments

Comments
 (0)