@@ -38,7 +38,7 @@ use std::sync::{Arc, Weak};
38
38
use pulldown_cmark:: {
39
39
BrokenLink , CodeBlockKind , CowStr , Event , LinkType , Options , Parser , Tag , TagEnd , html,
40
40
} ;
41
- use rustc_data_structures:: fx:: FxHashMap ;
41
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap } ;
42
42
use rustc_errors:: { Diag , DiagMessage } ;
43
43
use rustc_hir:: def_id:: LocalDefId ;
44
44
use rustc_middle:: ty:: TyCtxt ;
@@ -1762,6 +1762,46 @@ pub(crate) fn markdown_links<'md, R>(
1762
1762
}
1763
1763
} ;
1764
1764
1765
+ let span_for_refdef = |link : & CowStr < ' _ > , span : Range < usize > | {
1766
+ // We want to underline the link's definition, but `span` will point at the entire refdef.
1767
+ // Skip the label, then try to find the entire URL.
1768
+ let mut square_brace_count = 0 ;
1769
+ let mut iter = md. as_bytes ( ) [ span. start ..span. end ] . iter ( ) . copied ( ) . enumerate ( ) ;
1770
+ for ( _i, c) in & mut iter {
1771
+ match c {
1772
+ b':' if square_brace_count == 0 => break ,
1773
+ b'[' => square_brace_count += 1 ,
1774
+ b']' => square_brace_count -= 1 ,
1775
+ _ => { }
1776
+ }
1777
+ }
1778
+ while let Some ( ( i, c) ) = iter. next ( ) {
1779
+ if c == b'<' {
1780
+ while let Some ( ( j, c) ) = iter. next ( ) {
1781
+ match c {
1782
+ b'\\' => {
1783
+ let _ = iter. next ( ) ;
1784
+ }
1785
+ b'>' => {
1786
+ return MarkdownLinkRange :: Destination (
1787
+ i + 1 + span. start ..j + span. start ,
1788
+ ) ;
1789
+ }
1790
+ _ => { }
1791
+ }
1792
+ }
1793
+ } else if !c. is_ascii_whitespace ( ) {
1794
+ while let Some ( ( j, c) ) = iter. next ( ) {
1795
+ if c. is_ascii_whitespace ( ) {
1796
+ return MarkdownLinkRange :: Destination ( i + span. start ..j + span. start ) ;
1797
+ }
1798
+ }
1799
+ return MarkdownLinkRange :: Destination ( i + span. start ..span. end ) ;
1800
+ }
1801
+ }
1802
+ span_for_link ( link, span)
1803
+ } ;
1804
+
1765
1805
let span_for_offset_backward = |span : Range < usize > , open : u8 , close : u8 | {
1766
1806
let mut open_brace = !0 ;
1767
1807
let mut close_brace = !0 ;
@@ -1843,9 +1883,16 @@ pub(crate) fn markdown_links<'md, R>(
1843
1883
. into_offset_iter ( ) ;
1844
1884
let mut links = Vec :: new ( ) ;
1845
1885
1886
+ let mut refdefs = FxIndexMap :: default ( ) ;
1887
+ for ( label, refdef) in event_iter. reference_definitions ( ) . iter ( ) {
1888
+ refdefs. insert ( label. to_string ( ) , ( false , refdef. dest . to_string ( ) , refdef. span . clone ( ) ) ) ;
1889
+ }
1890
+
1846
1891
for ( event, span) in event_iter {
1847
1892
match event {
1848
- Event :: Start ( Tag :: Link { link_type, dest_url, .. } ) if may_be_doc_link ( link_type) => {
1893
+ Event :: Start ( Tag :: Link { link_type, dest_url, id, .. } )
1894
+ if may_be_doc_link ( link_type) =>
1895
+ {
1849
1896
let range = match link_type {
1850
1897
// Link is pulled from the link itself.
1851
1898
LinkType :: ReferenceUnknown | LinkType :: ShortcutUnknown => {
@@ -1855,7 +1902,12 @@ pub(crate) fn markdown_links<'md, R>(
1855
1902
LinkType :: Inline => span_for_offset_backward ( span, b'(' , b')' ) ,
1856
1903
// Link is pulled from elsewhere in the document.
1857
1904
LinkType :: Reference | LinkType :: Collapsed | LinkType :: Shortcut => {
1858
- span_for_link ( & dest_url, span)
1905
+ if let Some ( ( is_used, dest_url, span) ) = refdefs. get_mut ( & id[ ..] ) {
1906
+ * is_used = true ;
1907
+ span_for_refdef ( & CowStr :: from ( & dest_url[ ..] ) , span. clone ( ) )
1908
+ } else {
1909
+ span_for_link ( & dest_url, span)
1910
+ }
1859
1911
}
1860
1912
LinkType :: Autolink | LinkType :: Email => unreachable ! ( ) ,
1861
1913
} ;
@@ -1872,6 +1924,18 @@ pub(crate) fn markdown_links<'md, R>(
1872
1924
}
1873
1925
}
1874
1926
1927
+ for ( _label, ( is_used, dest_url, span) ) in refdefs. into_iter ( ) {
1928
+ if !is_used
1929
+ && let Some ( link) = preprocess_link ( MarkdownLink {
1930
+ kind : LinkType :: Reference ,
1931
+ range : span_for_refdef ( & CowStr :: from ( & dest_url[ ..] ) , span) ,
1932
+ link : dest_url,
1933
+ } )
1934
+ {
1935
+ links. push ( link) ;
1936
+ }
1937
+ }
1938
+
1875
1939
links
1876
1940
}
1877
1941
0 commit comments