diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9db83c903abf0..2877af1d0f981 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -951,9 +951,9 @@ fn preprocess_link<'a>( } // Parse and strip the disambiguator from the link, if present. - let (path_str, disambiguator) = match Disambiguator::from_str(&link) { - Ok(Some((d, path))) => (path.trim(), Some(d)), - Ok(None) => (link.trim(), None), + let (disambiguator, path_str, link_text) = match Disambiguator::from_str(&link) { + Ok(Some((d, path, link_text))) => (Some(d), path.trim(), link_text.trim()), + Ok(None) => (None, link.trim(), link.trim()), Err((err_msg, relative_range)) => { // Only report error if we would not have ignored this link. See issue #83859. if !should_ignore_link_with_disambiguators(link) { @@ -971,11 +971,6 @@ fn preprocess_link<'a>( return None; } - // We stripped `()` and `!` when parsing the disambiguator. - // Add them back to be displayed, but not prefix disambiguators. - let link_text = - disambiguator.map(|d| d.display_for(path_str)).unwrap_or_else(|| path_str.to_owned()); - // Strip generics from the path. let path_str = if path_str.contains(['<', '>'].as_slice()) { match strip_generics_from_path(&path_str) { @@ -1005,7 +1000,7 @@ fn preprocess_link<'a>( path_str, disambiguator, extra_fragment: extra_fragment.map(String::from), - link_text, + link_text: link_text.to_owned(), })) } @@ -1513,24 +1508,12 @@ enum Disambiguator { } impl Disambiguator { - /// The text that should be displayed when the path is rendered as HTML. - /// - /// NOTE: `path` is not the original link given by the user, but a name suitable for passing to `resolve`. - fn display_for(&self, path: &str) -> String { - match self { - // FIXME: this will have different output if the user had `m!()` originally. - Self::Kind(DefKind::Macro(MacroKind::Bang)) => format!("{}!", path), - Self::Kind(DefKind::Fn) => format!("{}()", path), - _ => path.to_owned(), - } - } - - /// Given a link, parse and return `(disambiguator, path_str)`. + /// Given a link, parse and return `(disambiguator, path_str, link_text)`. /// /// 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, Range)> { + fn from_str(link: &str) -> Result, (String, Range)> { use Disambiguator::{Kind, Namespace as NS, Primitive}; if let Some(idx) = link.find('@') { @@ -1551,18 +1534,20 @@ impl Disambiguator { "prim" | "primitive" => Primitive, _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)), }; - Ok(Some((d, &rest[1..]))) + Ok(Some((d, &rest[1..], &rest[1..]))) } else { let suffixes = [ ("!()", DefKind::Macro(MacroKind::Bang)), + ("!{}", DefKind::Macro(MacroKind::Bang)), + ("![]", DefKind::Macro(MacroKind::Bang)), ("()", DefKind::Fn), ("!", DefKind::Macro(MacroKind::Bang)), ]; for (suffix, kind) in suffixes { - if let Some(link) = link.strip_suffix(suffix) { + if let Some(path_str) = link.strip_suffix(suffix) { // Avoid turning `!` or `()` into an empty string - if !link.is_empty() { - return Ok(Some((Kind(kind), link))); + if !path_str.is_empty() { + return Ok(Some((Kind(kind), path_str, link))); } } } diff --git a/src/test/rustdoc/intra-doc/macros-disambiguators.rs b/src/test/rustdoc/intra-doc/macros-disambiguators.rs new file mode 100644 index 0000000000000..cd4caa6a89416 --- /dev/null +++ b/src/test/rustdoc/intra-doc/macros-disambiguators.rs @@ -0,0 +1,25 @@ +#![crate_name = "foo"] +#![deny(rustdoc::broken_intra_doc_links)] + +//! [foo!()] +// @has foo/index.html '//a[@href="macro.foo.html"]' 'foo!()' + +//! [foo!{}] +// @has - '//a[@href="macro.foo.html"]' 'foo!{}' + +//! [foo![]](foo![]) +// @has - '//a[@href="macro.foo.html"]' 'foo![]' + +//! [foo1](foo!()) +// @has - '//a[@href="macro.foo.html"]' 'foo1' + +//! [foo2](foo!{}) +// @has - '//a[@href="macro.foo.html"]' 'foo2' + +//! [foo3](foo![]) +// @has - '//a[@href="macro.foo.html"]' 'foo3' + +#[macro_export] +macro_rules! foo { + () => {}; +}