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