Skip to content

Commit 4572e7f

Browse files
committed
Lint on unknown intra-doc link disambiguators
1 parent 5e65467 commit 4572e7f

File tree

3 files changed

+84
-11
lines changed

3 files changed

+84
-11
lines changed

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -973,10 +973,13 @@ impl LinkCollector<'_, '_> {
973973
};
974974

975975
// Parse and strip the disambiguator from the link, if present.
976-
let (mut path_str, disambiguator) = if let Ok((d, path)) = Disambiguator::from_str(&link) {
977-
(path.trim(), Some(d))
978-
} else {
979-
(link.trim(), None)
976+
let (mut path_str, disambiguator) = match Disambiguator::from_str(&link) {
977+
Ok(Some((d, path))) => (path.trim(), Some(d)),
978+
Ok(None) => (link.trim(), None),
979+
Err(err_msg) => {
980+
disambiguator_error(self.cx, &item, dox, ori_link.range, &err_msg);
981+
return None;
982+
}
980983
};
981984

982985
if path_str.contains(|ch: char| !(ch.is_alphanumeric() || ":_<>, !*&;".contains(ch))) {
@@ -1514,8 +1517,12 @@ impl Disambiguator {
15141517
}
15151518
}
15161519

1517-
/// Given a link, parse and return `(disambiguator, path_str)`
1518-
fn from_str(link: &str) -> Result<(Self, &str), ()> {
1520+
/// Given a link, parse and return `(disambiguator, path_str)`.
1521+
///
1522+
/// This returns `Ok(Some(...))` if a disambiguator was found,
1523+
/// `Ok(None)` if no disambiguator was found, or `Err(...)`
1524+
/// if there was a problem with the disambiguator.
1525+
fn from_str(link: &str) -> Result<Option<(Self, &str)>, String> {
15191526
use Disambiguator::{Kind, Namespace as NS, Primitive};
15201527

15211528
let find_suffix = || {
@@ -1528,11 +1535,11 @@ impl Disambiguator {
15281535
if let Some(link) = link.strip_suffix(suffix) {
15291536
// Avoid turning `!` or `()` into an empty string
15301537
if !link.is_empty() {
1531-
return Ok((Kind(kind), link));
1538+
return Some((Kind(kind), link));
15321539
}
15331540
}
15341541
}
1535-
Err(())
1542+
None
15361543
};
15371544

15381545
if let Some(idx) = link.find('@') {
@@ -1551,11 +1558,11 @@ impl Disambiguator {
15511558
"value" => NS(Namespace::ValueNS),
15521559
"macro" => NS(Namespace::MacroNS),
15531560
"prim" | "primitive" => Primitive,
1554-
_ => return find_suffix(),
1561+
_ => return Err(format!("unknown disambiguator `{}`", prefix)),
15551562
};
1556-
Ok((d, &rest[1..]))
1563+
Ok(Some((d, &rest[1..])))
15571564
} else {
1558-
find_suffix()
1565+
Ok(find_suffix())
15591566
}
15601567
}
15611568

@@ -1979,6 +1986,22 @@ fn anchor_failure(
19791986
});
19801987
}
19811988

1989+
/// Report an error in the link disambiguator.
1990+
fn disambiguator_error(
1991+
cx: &DocContext<'_>,
1992+
item: &Item,
1993+
dox: &str,
1994+
link_range: Range<usize>,
1995+
msg: &str,
1996+
) {
1997+
report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, item, dox, &link_range, |diag, _sp| {
1998+
diag.note(
1999+
"the disambiguator is the part of the link before the `@` sign, \
2000+
or a suffix such as `()` for functions",
2001+
);
2002+
});
2003+
}
2004+
19822005
/// Report an ambiguity error, where there were multiple possible resolutions.
19832006
fn ambiguity_error(
19842007
cx: &DocContext<'_>,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//! Linking to [foo@banana] and [`bar@banana!()`].
2+
//~^ ERROR unknown disambiguator `foo`
3+
//~| ERROR unknown disambiguator `bar`
4+
//! And to [no disambiguator](@nectarine) and [another](@apricot!()).
5+
//~^ ERROR unknown disambiguator ``
6+
//~| ERROR unknown disambiguator ``
7+
8+
#![deny(warnings)]
9+
10+
fn main() {}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
error: unknown disambiguator `foo`
2+
--> $DIR/unknown-disambiguator.rs:1:17
3+
|
4+
LL | //! Linking to [foo@banana] and [`bar@banana!()`].
5+
| ^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unknown-disambiguator.rs:8:9
9+
|
10+
LL | #![deny(warnings)]
11+
| ^^^^^^^^
12+
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
13+
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions
14+
15+
error: unknown disambiguator `bar`
16+
--> $DIR/unknown-disambiguator.rs:1:34
17+
|
18+
LL | //! Linking to [foo@banana] and [`bar@banana!()`].
19+
| ^^^^^^^^^^^^^^^
20+
|
21+
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions
22+
23+
error: unknown disambiguator ``
24+
--> $DIR/unknown-disambiguator.rs:4:31
25+
|
26+
LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
27+
| ^^^^^^^^^^
28+
|
29+
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions
30+
31+
error: unknown disambiguator ``
32+
--> $DIR/unknown-disambiguator.rs:4:57
33+
|
34+
LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
35+
| ^^^^^^^^^^^
36+
|
37+
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions
38+
39+
error: aborting due to 4 previous errors
40+

0 commit comments

Comments
 (0)