Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to intra-doc link macro disambiguators #86523

Merged
merged 3 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 12 additions & 27 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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(),
}))
}

Expand Down Expand Up @@ -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<Option<(Self, &str)>, (String, Range<usize>)> {
fn from_str(link: &str) -> Result<Option<(Self, &str, &str)>, (String, Range<usize>)> {
use Disambiguator::{Kind, Namespace as NS, Primitive};

if let Some(idx) = link.find('@') {
Expand All @@ -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)));
}
}
}
Expand Down
25 changes: 25 additions & 0 deletions src/test/rustdoc/intra-doc/macros-disambiguators.rs
Original file line number Diff line number Diff line change
@@ -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 {
() => {};
}