Skip to content

Commit

Permalink
Lint on unknown intra-doc link disambiguators
Browse files Browse the repository at this point in the history
  • Loading branch information
camelid committed Mar 27, 2021
1 parent 5e65467 commit 4572e7f
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 11 deletions.
45 changes: 34 additions & 11 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -973,10 +973,13 @@ impl LinkCollector<'_, '_> {
};

// Parse and strip the disambiguator from the link, if present.
let (mut path_str, disambiguator) = if let Ok((d, path)) = Disambiguator::from_str(&link) {
(path.trim(), Some(d))
} else {
(link.trim(), None)
let (mut path_str, disambiguator) = match Disambiguator::from_str(&link) {
Ok(Some((d, path))) => (path.trim(), Some(d)),
Ok(None) => (link.trim(), None),
Err(err_msg) => {
disambiguator_error(self.cx, &item, dox, ori_link.range, &err_msg);
return None;
}
};

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

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

let find_suffix = || {
Expand All @@ -1528,11 +1535,11 @@ impl Disambiguator {
if let Some(link) = link.strip_suffix(suffix) {
// Avoid turning `!` or `()` into an empty string
if !link.is_empty() {
return Ok((Kind(kind), link));
return Some((Kind(kind), link));
}
}
}
Err(())
None
};

if let Some(idx) = link.find('@') {
Expand All @@ -1551,11 +1558,11 @@ impl Disambiguator {
"value" => NS(Namespace::ValueNS),
"macro" => NS(Namespace::MacroNS),
"prim" | "primitive" => Primitive,
_ => return find_suffix(),
_ => return Err(format!("unknown disambiguator `{}`", prefix)),
};
Ok((d, &rest[1..]))
Ok(Some((d, &rest[1..])))
} else {
find_suffix()
Ok(find_suffix())
}
}

Expand Down Expand Up @@ -1979,6 +1986,22 @@ fn anchor_failure(
});
}

/// Report an error in the link disambiguator.
fn disambiguator_error(
cx: &DocContext<'_>,
item: &Item,
dox: &str,
link_range: Range<usize>,
msg: &str,
) {
report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, item, dox, &link_range, |diag, _sp| {
diag.note(
"the disambiguator is the part of the link before the `@` sign, \
or a suffix such as `()` for functions",
);
});
}

/// Report an ambiguity error, where there were multiple possible resolutions.
fn ambiguity_error(
cx: &DocContext<'_>,
Expand Down
10 changes: 10 additions & 0 deletions src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Linking to [foo@banana] and [`bar@banana!()`].
//~^ ERROR unknown disambiguator `foo`
//~| ERROR unknown disambiguator `bar`
//! And to [no disambiguator](@nectarine) and [another](@apricot!()).
//~^ ERROR unknown disambiguator ``
//~| ERROR unknown disambiguator ``

#![deny(warnings)]

fn main() {}
40 changes: 40 additions & 0 deletions src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
error: unknown disambiguator `foo`
--> $DIR/unknown-disambiguator.rs:1:17
|
LL | //! Linking to [foo@banana] and [`bar@banana!()`].
| ^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/unknown-disambiguator.rs:8:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions

error: unknown disambiguator `bar`
--> $DIR/unknown-disambiguator.rs:1:34
|
LL | //! Linking to [foo@banana] and [`bar@banana!()`].
| ^^^^^^^^^^^^^^^
|
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions

error: unknown disambiguator ``
--> $DIR/unknown-disambiguator.rs:4:31
|
LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
| ^^^^^^^^^^
|
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions

error: unknown disambiguator ``
--> $DIR/unknown-disambiguator.rs:4:57
|
LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
| ^^^^^^^^^^^
|
= note: the disambiguator is the part of the link before the `@` sign, or a suffix such as `()` for functions

error: aborting due to 4 previous errors

0 comments on commit 4572e7f

Please sign in to comment.