summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/rustdoc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/rustdoc.rs')
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs75
1 files changed, 66 insertions, 9 deletions
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index d433391f2..ba7417b6d 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -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));
+ }
+ _ => {}
+ }
+ }
+
+ 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;
+ }
+ _ => {}
}
- _ => None,
- })
- .collect()
+ }
+
+ display_text.map(String::into_boxed_str)
}