@@ -63,7 +63,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet};
63
63
use rustc:: session:: config:: nightly_options:: is_nightly_build;
64
64
use rustc_data_structures:: flock;
65
65
66
- use clean:: { self , AttributesExt , GetDefId , SelfTy , Mutability } ;
66
+ use clean:: { self , AttributesExt , GetDefId , SelfTy , Mutability , Span } ;
67
67
use doctree;
68
68
use fold:: DocFolder ;
69
69
use html:: escape:: Escape ;
@@ -126,7 +126,7 @@ pub struct SharedContext {
126
126
pub css_file_extension : Option < PathBuf > ,
127
127
/// Warnings for the user if rendering would differ using different markdown
128
128
/// parsers.
129
- pub markdown_warnings : RefCell < Vec < ( String , Vec < String > ) > > ,
129
+ pub markdown_warnings : RefCell < Vec < ( Span , String , Vec < html_diff :: Difference > ) > > ,
130
130
}
131
131
132
132
/// Indicates where an external crate can be found.
@@ -589,15 +589,98 @@ pub fn run(mut krate: clean::Crate,
589
589
let result = cx. krate ( krate) ;
590
590
591
591
let markdown_warnings = scx. markdown_warnings . borrow ( ) ;
592
- for & ( ref text, ref diffs) in & * markdown_warnings {
593
- println ! ( "Differences spotted in {:?}:\n {}" ,
594
- text,
595
- diffs. join( "\n " ) ) ;
592
+ if !markdown_warnings. is_empty ( ) {
593
+ println ! ( "WARNING: documentation for this crate may be rendered \
594
+ differently using the new Pulldown renderer.") ;
595
+ println ! ( " See https://github.com/rust-lang/rust/issues/44229 for details." ) ;
596
+ for & ( ref span, ref text, ref diffs) in & * markdown_warnings {
597
+ println ! ( "WARNING: rendering difference in `{}`" , concise_str( text) ) ;
598
+ println ! ( " --> {}:{}:{}" , span. filename, span. loline, span. locol) ;
599
+ for d in diffs {
600
+ render_difference ( d) ;
601
+ }
602
+ }
596
603
}
597
604
598
605
result
599
606
}
600
607
608
+ // A short, single-line view of `s`.
609
+ fn concise_str ( s : & str ) -> String {
610
+ if s. contains ( '\n' ) {
611
+ return format ! ( "{}..." , & s[ ..s. find( '\n' ) . unwrap( ) ] ) ;
612
+ }
613
+ if s. len ( ) > 70 {
614
+ return format ! ( "{} ... {}" , & s[ ..50 ] , & s[ s. len( ) -20 ..] ) ;
615
+ }
616
+ s. to_owned ( )
617
+ }
618
+
619
+ // Returns short versions of s1 and s2, starting from where the strings differ.
620
+ fn concise_compared_strs ( s1 : & str , s2 : & str ) -> ( String , String ) {
621
+ let s1 = s1. trim ( ) ;
622
+ let s2 = s2. trim ( ) ;
623
+ if !s1. contains ( '\n' ) && !s2. contains ( '\n' ) && s1. len ( ) <= 70 && s2. len ( ) <= 70 {
624
+ return ( s1. to_owned ( ) , s2. to_owned ( ) ) ;
625
+ }
626
+
627
+ let mut start_byte = 0 ;
628
+ for ( c1, c2) in s1. chars ( ) . zip ( s2. chars ( ) ) {
629
+ if c1 != c2 {
630
+ break ;
631
+ }
632
+
633
+ start_byte += c1. len_utf8 ( ) ;
634
+ }
635
+
636
+ if start_byte == 0 {
637
+ return ( concise_str ( s1) , concise_str ( s2) ) ;
638
+ }
639
+
640
+ let s1 = & s1[ start_byte..] ;
641
+ let s2 = & s2[ start_byte..] ;
642
+ ( format ! ( "...{}" , concise_str( s1) ) , format ! ( "...{}" , concise_str( s2) ) )
643
+ }
644
+
645
+ fn render_difference ( diff : & html_diff:: Difference ) {
646
+ match * diff {
647
+ html_diff:: Difference :: NodeType { ref elem, ref opposite_elem } => {
648
+ println ! ( " {} Types differ: expected: `{}`, found: `{}`" ,
649
+ elem. path, elem. element_name, opposite_elem. element_name) ;
650
+ }
651
+ html_diff:: Difference :: NodeName { ref elem, ref opposite_elem } => {
652
+ println ! ( " {} Tags differ: expected: `{}`, found: `{}`" ,
653
+ elem. path, elem. element_name, opposite_elem. element_name) ;
654
+ }
655
+ html_diff:: Difference :: NodeAttributes { ref elem,
656
+ ref elem_attributes,
657
+ ref opposite_elem_attributes,
658
+ .. } => {
659
+ println ! ( " {} Attributes differ in `{}`: expected: `{:?}`, found: `{:?}`" ,
660
+ elem. path, elem. element_name, elem_attributes, opposite_elem_attributes) ;
661
+ }
662
+ html_diff:: Difference :: NodeText { ref elem, ref elem_text, ref opposite_elem_text, .. } => {
663
+ let ( s1, s2) = concise_compared_strs ( elem_text, opposite_elem_text) ;
664
+ println ! ( " {} Text differs:\n expected: `{}`\n found: `{}`" ,
665
+ elem. path, s1, s2) ;
666
+ }
667
+ html_diff:: Difference :: NotPresent { ref elem, ref opposite_elem } => {
668
+ if let Some ( ref elem) = * elem {
669
+ println ! ( " {} One element is missing: expected: `{}`" ,
670
+ elem. path, elem. element_name) ;
671
+ } else if let Some ( ref elem) = * opposite_elem {
672
+ if elem. element_name . is_empty ( ) {
673
+ println ! ( " {} Unexpected element: `{}`" ,
674
+ elem. path, concise_str( & elem. element_content) ) ;
675
+ } else {
676
+ println ! ( " {} Unexpected element `{}`: found: `{}`" ,
677
+ elem. path, elem. element_name, concise_str( & elem. element_content) ) ;
678
+ }
679
+ }
680
+ }
681
+ }
682
+ }
683
+
601
684
/// Build the search index from the collected metadata
602
685
fn build_index ( krate : & clean:: Crate , cache : & mut Cache ) -> String {
603
686
let mut nodeid_to_pathid = FxHashMap ( ) ;
@@ -1664,6 +1747,7 @@ fn document(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item) -> fmt::Re
1664
1747
/// rendering between Pulldown and Hoedown.
1665
1748
fn render_markdown ( w : & mut fmt:: Formatter ,
1666
1749
md_text : & str ,
1750
+ span : Span ,
1667
1751
render_type : RenderType ,
1668
1752
prefix : & str ,
1669
1753
scx : & SharedContext )
@@ -1673,20 +1757,20 @@ fn render_markdown(w: &mut fmt::Formatter,
1673
1757
let output = if render_type == RenderType :: Pulldown {
1674
1758
let pulldown_output = format ! ( "{}" , Markdown ( md_text, RenderType :: Pulldown ) ) ;
1675
1759
let differences = html_diff:: get_differences ( & pulldown_output, & hoedown_output) ;
1676
- let differences = differences. iter ( )
1677
- . filter_map ( |s| {
1760
+ let differences = differences. into_iter ( )
1761
+ . filter ( |s| {
1678
1762
match * s {
1679
1763
html_diff:: Difference :: NodeText { ref elem_text,
1680
1764
ref opposite_elem_text,
1681
1765
.. }
1682
- if elem_text. trim ( ) == opposite_elem_text. trim ( ) => None ,
1683
- _ => Some ( format ! ( "=> {}" , s . to_string ( ) ) ) ,
1766
+ if elem_text. trim ( ) == opposite_elem_text. trim ( ) => false ,
1767
+ _ => true ,
1684
1768
}
1685
1769
} )
1686
- . collect :: < Vec < String > > ( ) ;
1770
+ . collect :: < Vec < _ > > ( ) ;
1687
1771
1688
1772
if !differences. is_empty ( ) {
1689
- scx. markdown_warnings . borrow_mut ( ) . push ( ( md_text. to_owned ( ) , differences) ) ;
1773
+ scx. markdown_warnings . borrow_mut ( ) . push ( ( span , md_text. to_owned ( ) , differences) ) ;
1690
1774
}
1691
1775
1692
1776
pulldown_output
@@ -1706,7 +1790,7 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
1706
1790
} else {
1707
1791
format ! ( "{}" , & plain_summary_line( Some ( s) ) )
1708
1792
} ;
1709
- render_markdown ( w, & markdown, cx. render_type , prefix, & cx. shared ) ?;
1793
+ render_markdown ( w, & markdown, item . source . clone ( ) , cx. render_type , prefix, & cx. shared ) ?;
1710
1794
} else if !prefix. is_empty ( ) {
1711
1795
write ! ( w, "<div class='docblock'>{}</div>" , prefix) ?;
1712
1796
}
@@ -1730,7 +1814,7 @@ fn render_assoc_const_value(item: &clean::Item) -> String {
1730
1814
fn document_full ( w : & mut fmt:: Formatter , item : & clean:: Item ,
1731
1815
cx : & Context , prefix : & str ) -> fmt:: Result {
1732
1816
if let Some ( s) = item. doc_value ( ) {
1733
- render_markdown ( w, s, cx. render_type , prefix, & cx. shared ) ?;
1817
+ render_markdown ( w, s, item . source . clone ( ) , cx. render_type , prefix, & cx. shared ) ?;
1734
1818
} else if !prefix. is_empty ( ) {
1735
1819
write ! ( w, "<div class='docblock'>{}</div>" , prefix) ?;
1736
1820
}
0 commit comments