From f07354333f254fc7d3f20c939b29ba93143b8671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Thu, 31 Dec 2020 10:38:12 +0100 Subject: [PATCH] Only use locate for borrowed strings --- src/librustdoc/html/markdown.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index f0dd552f82c..465aeecbd3e 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1135,6 +1135,7 @@ crate fn markdown_links(md: &str) -> Vec<(String, Range)> { let links = RefCell::new(vec![]); + // FIXME: remove this function once pulldown_cmark can provide spans for link definitions. let locate = |s: &str, fallback: Range| unsafe { let s_start = s.as_ptr(); let s_end = s_start.add(s.len()); @@ -1149,10 +1150,25 @@ crate fn markdown_links(md: &str) -> Vec<(String, Range)> { } }; + let span_for_link = |link: &CowStr<'_>, span: Range| { + // For diagnostics, we want to underline the link's definition but `span` will point at + // where the link is used. This is a problem for reference-style links, where the definition + // is separate from the usage. + match link { + // `Borrowed` variant means the string (the link's destination) may come directly from + // the markdown text and we can locate the original link destination. + // NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources, + // so `locate()` can fall back to use `span`. + CowStr::Borrowed(s) => locate(s, span), + + // For anything else, we can only use the provided range. + CowStr::Boxed(_) | CowStr::Inlined(_) => span, + } + }; + let mut push = |link: BrokenLink<'_>| { - // FIXME: use `link.span` instead of `locate` - // (doing it now includes the `[]` as well as the text) - links.borrow_mut().push((link.reference.to_owned(), locate(link.reference, link.span))); + let span = span_for_link(&CowStr::Borrowed(link.reference), link.span); + links.borrow_mut().push((link.reference.to_owned(), span)); None }; let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter(); @@ -1165,10 +1181,8 @@ crate fn markdown_links(md: &str) -> Vec<(String, Range)> { for ev in iter { if let Event::Start(Tag::Link(_, dest, _)) = ev.0 { debug!("found link: {}", dest); - links.borrow_mut().push(match dest { - CowStr::Borrowed(s) => (s.to_owned(), locate(s, ev.1)), - s @ (CowStr::Boxed(..) | CowStr::Inlined(..)) => (s.into_string(), ev.1), - }); + let span = span_for_link(&dest, ev.1); + links.borrow_mut().push((dest.into_string(), span)); } }