1
Fork 0

Auto merge of #113167 - ChAoSUnItY:redundant_explicit_link, r=GuillaumeGomez

rustdoc: Add lint `redundant_explicit_links`

Closes #87799.
- Lint warns by default
- Reworks link parser to cache original link's display text

r? `@jyn514`
This commit is contained in:
bors 2023-08-20 01:04:22 +00:00
commit 9c699a40cc
24 changed files with 2066 additions and 118 deletions

View file

@ -30,7 +30,7 @@ pub use super::{
/// will be retrieved.
#[derive(Debug, Copy, Clone)]
pub enum ConsumerOptions {
/// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
/// Retrieve the [`Body`] along with the [`BorrowSet`]
/// and [`RegionInferenceContext`]. If you would like the body only, use
/// [`TyCtxt::mir_promoted`].
///

View file

@ -452,11 +452,11 @@ struct HandlerInner {
/// have been converted.
check_unstable_expect_diagnostics: bool,
/// Expected [`Diagnostic`][diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
/// Expected [`Diagnostic`][struct@diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
/// the lint level. [`LintExpectationId`]s created early during the compilation
/// (before `HirId`s have been defined) are not stable and can therefore not be
/// stored on disk. This buffer stores these diagnostics until the ID has been
/// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][diagnostic::Diagnostic]s are the
/// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][struct@diagnostic::Diagnostic]s are the
/// submitted for storage and added to the list of fulfilled expectations.
unstable_expect_diagnostics: Vec<Diagnostic>,

View file

@ -1,4 +1,4 @@
use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag};
use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, Options, Parser, Tag};
use rustc_ast as ast;
use rustc_ast::util::comments::beautify_doc_string;
use rustc_data_structures::fx::FxHashMap;
@ -392,16 +392,73 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<s
let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
Parser::new_with_broken_link_callback(
parse_links(&doc)
}
/// Similiar version of `markdown_links` from rustdoc.
/// This will collect destination links and display text if exists.
fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
let mut event_iter = Parser::new_with_broken_link_callback(
&doc,
main_body_opts(),
Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
Some(&mut broken_link_callback),
)
.filter_map(|event| match event {
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
Some(preprocess_link(&dest))
.into_iter();
let mut links = Vec::new();
while let Some(event) = event_iter.next() {
match event {
Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
if matches!(
link_type,
LinkType::Inline
| LinkType::ReferenceUnknown
| LinkType::Reference
| LinkType::Shortcut
| LinkType::ShortcutUnknown
) {
if let Some(display_text) = collect_link_data(&mut event_iter) {
links.push(display_text);
}
}
links.push(preprocess_link(&dest));
}
_ => {}
}
_ => None,
})
.collect()
}
links
}
/// Collects additional data of link.
fn collect_link_data<'input, 'callback>(
event_iter: &mut Parser<'input, 'callback>,
) -> Option<Box<str>> {
let mut display_text: Option<String> = None;
let mut append_text = |text: CowStr<'_>| {
if let Some(display_text) = &mut display_text {
display_text.push_str(&text);
} else {
display_text = Some(text.to_string());
}
};
while let Some(event) = event_iter.next() {
match event {
Event::Text(text) => {
append_text(text);
}
Event::Code(code) => {
append_text(code);
}
Event::End(_) => {
break;
}
_ => {}
}
}
display_text.map(String::into_boxed_str)
}