Skip to content

Commit 70dd729

Browse files
committed
add new rustdoc::hidden_intra_doc_links lint
1 parent 3fb1b53 commit 70dd729

File tree

2 files changed

+43
-9
lines changed

2 files changed

+43
-9
lines changed

src/librustdoc/lint.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ declare_rustdoc_lint! {
9797
"linking from a public item to a private one"
9898
}
9999

100+
declare_rustdoc_lint! {
101+
/// This is a subset of `broken_intra_doc_links` that warns when linking from
102+
/// a non-hidden item to a hidden one. This is a `rustdoc` only lint, see the
103+
/// documentation in the [rustdoc book].
104+
///
105+
/// [rustdoc book]: ../../../rustdoc/lints.html#hidden_intra_doc_links
106+
HIDDEN_INTRA_DOC_LINKS,
107+
Warn,
108+
"linking from a non-hidden item to a hidden one"
109+
}
110+
100111
declare_rustdoc_lint! {
101112
/// The `invalid_codeblock_attributes` lint detects code block attributes
102113
/// in documentation examples that have potentially mis-typed values. This
@@ -199,6 +210,7 @@ declare_rustdoc_lint! {
199210
pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
200211
vec![
201212
BROKEN_INTRA_DOC_LINKS,
213+
HIDDEN_INTRA_DOC_LINKS,
202214
PRIVATE_INTRA_DOC_LINKS,
203215
MISSING_DOC_CODE_EXAMPLES,
204216
PRIVATE_DOC_TESTS,

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use crate::clean::utils::find_nearest_parent_module;
3434
use crate::clean::{self, Crate, Item, ItemId, ItemLink, PrimitiveType};
3535
use crate::core::DocContext;
3636
use crate::html::markdown::{MarkdownLink, MarkdownLinkRange, markdown_links};
37-
use crate::lint::{BROKEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
37+
use crate::lint::{BROKEN_INTRA_DOC_LINKS, HIDDEN_INTRA_DOC_LINKS, PRIVATE_INTRA_DOC_LINKS};
3838
use crate::passes::Pass;
3939
use crate::visit::DocVisitor;
4040

@@ -1341,13 +1341,18 @@ impl LinkCollector<'_, '_> {
13411341
}
13421342
}
13431343

1344+
let src_def_id = diag_info.item.item_id.expect_def_id();
13441345
// item can be non-local e.g. when using `#[rustc_doc_primitive = "pointer"]`
13451346
if let Some(dst_id) = id.as_local()
1346-
&& let Some(src_id) = diag_info.item.item_id.expect_def_id().as_local()
1347+
&& let Some(src_id) = src_def_id.as_local()
13471348
&& self.cx.tcx.effective_visibilities(()).is_exported(src_id)
13481349
&& !self.cx.tcx.effective_visibilities(()).is_exported(dst_id)
13491350
{
1350-
privacy_error(self.cx, diag_info, path_str);
1351+
privacy_error(self.cx, diag_info, path_str, PrivacyErrorKind::Private);
1352+
}
1353+
1354+
if self.cx.tcx.is_doc_hidden(id) && !self.cx.tcx.is_doc_hidden(src_def_id) {
1355+
privacy_error(self.cx, diag_info, path_str, PrivacyErrorKind::Hidden);
13511356
}
13521357

13531358
Some(())
@@ -2334,8 +2339,20 @@ fn suggest_disambiguator(
23342339
}
23352340
}
23362341

2342+
#[derive(Copy, Clone)]
2343+
enum PrivacyErrorKind {
2344+
Private,
2345+
Hidden,
2346+
}
2347+
23372348
/// Report a link from a public item to a private one.
2338-
fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str: &str) {
2349+
fn privacy_error(
2350+
cx: &DocContext<'_>,
2351+
diag_info: &DiagnosticInfo<'_>,
2352+
path_str: &str,
2353+
kind: PrivacyErrorKind,
2354+
) {
2355+
use PrivacyErrorKind::*;
23392356
let sym;
23402357
let item_name = match diag_info.item.name {
23412358
Some(name) => {
@@ -2344,17 +2361,22 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str:
23442361
}
23452362
None => "<unknown>",
23462363
};
2347-
let msg = format!("public documentation for `{item_name}` links to private item `{path_str}`");
2364+
let (public, private, flag, lint) = match kind {
2365+
Private => ("public", "private", "--document-private-items", PRIVATE_INTRA_DOC_LINKS),
2366+
Hidden => ("non-hidden", "hidden", "--document-hidden-items", HIDDEN_INTRA_DOC_LINKS),
2367+
};
2368+
let msg =
2369+
format!("{public} documentation for `{item_name}` links to {private} item `{path_str}`");
23482370

2349-
report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp, _link_range| {
2371+
report_diagnostic(cx.tcx, lint, msg, diag_info, |diag, sp, _link_range| {
23502372
if let Some(sp) = sp {
2351-
diag.span_label(sp, "this item is private");
2373+
diag.span_label(sp, format!("this item is {private}"));
23522374
}
23532375

23542376
let note_msg = if cx.render_options.document_private {
2355-
"this link resolves only because you passed `--document-private-items`, but will break without"
2377+
format!("this link resolves only because you passed `{flag}`, but will break without")
23562378
} else {
2357-
"this link will resolve properly if you pass `--document-private-items`"
2379+
format!("this link will resolve properly if you pass `{flag}`")
23582380
};
23592381
diag.note(note_msg);
23602382
});

0 commit comments

Comments
 (0)