From 56347a173a49ef1232ced3974ccbf8e16c5da78c Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 28 Mar 2021 17:02:26 -0700 Subject: [PATCH] Point to disambiguator instead of whole link And, now that we do that, we can remove the explanatory note since the error span should make it clear what the disambiguator is. --- src/librustdoc/html/markdown.rs | 1 + .../passes/collect_intra_doc_links.rs | 39 ++++++++++++++----- .../intra-doc/unknown-disambiguator.stderr | 17 +++----- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b39f9f878921a..c44514ed3cb83 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1162,6 +1162,7 @@ crate fn plain_text_summary(md: &str) -> String { s } +#[derive(Debug)] crate struct MarkdownLink { pub kind: LinkType, pub link: String, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index f5c5c9ca4aa9c..417637d238423 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -950,6 +950,7 @@ impl LinkCollector<'_, '_> { } let link = ori_link.link.replace("`", ""); + let no_backticks_range = range_between_backticks(&ori_link); let parts = link.split('#').collect::>(); let (link, extra_fragment) = if parts.len() > 2 { // A valid link can't have multiple #'s @@ -976,8 +977,10 @@ impl LinkCollector<'_, '_> { 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); + Err((err_msg, relative_range)) => { + let disambiguator_range = (no_backticks_range.start + relative_range.start) + ..(no_backticks_range.start + relative_range.end); + disambiguator_error(self.cx, &item, dox, disambiguator_range, &err_msg); return None; } }; @@ -1491,6 +1494,27 @@ impl LinkCollector<'_, '_> { } } +/// Get the section of a link between the backticks, +/// or the whole link if there aren't any backticks. +/// +/// For example: +/// +/// ```text +/// [`Foo`] +/// ^^^ +/// ``` +fn range_between_backticks(ori_link: &MarkdownLink) -> Range { + let after_first_backtick_group = ori_link.link.bytes().position(|b| b != b'`').unwrap_or(0); + let before_second_backtick_group = ori_link + .link + .bytes() + .skip(after_first_backtick_group) + .position(|b| b == b'`') + .unwrap_or(ori_link.link.len()); + (ori_link.range.start + after_first_backtick_group) + ..(ori_link.range.start + before_second_backtick_group) +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] /// Disambiguators for a link. enum Disambiguator { @@ -1522,7 +1546,7 @@ impl Disambiguator { /// 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, String> { + fn from_str(link: &str) -> Result, (String, Range)> { use Disambiguator::{Kind, Namespace as NS, Primitive}; let find_suffix = || { @@ -1558,7 +1582,7 @@ impl Disambiguator { "value" => NS(Namespace::ValueNS), "macro" => NS(Namespace::MacroNS), "prim" | "primitive" => Primitive, - _ => return Err(format!("unknown disambiguator `{}`", prefix)), + _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)), }; Ok(Some((d, &rest[1..]))) } else { @@ -1994,12 +2018,7 @@ fn disambiguator_error( link_range: Range, 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_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, item, dox, &link_range, |_diag, _sp| {}); } /// Report an ambiguity error, where there were multiple possible resolutions. diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr index 9e7699eea9a28..2904603dfc312 100644 --- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr +++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr @@ -2,7 +2,7 @@ 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 @@ -10,31 +10,24 @@ note: the lint level is defined here 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 + --> $DIR/unknown-disambiguator.rs:1:35 | 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