@@ -21,7 +21,7 @@ use rustc_metadata::rendered_const;
2121use rustc_middle:: ty:: fast_reject:: SimplifiedType ;
2222use rustc_middle:: ty:: { self , Ty , TyCtxt , Visibility } ;
2323use rustc_resolve:: rustdoc:: {
24- DocFragment , add_doc_fragment , attrs_to_doc_fragments, inner_docs, span_of_fragments,
24+ DocFragment , attrs_to_doc_fragments, inner_docs, prepare_fragments , span_of_fragments,
2525} ;
2626use rustc_session:: Session ;
2727use rustc_span:: def_id:: { CRATE_DEF_ID , ModId } ;
@@ -122,6 +122,42 @@ impl ItemId {
122122 | ItemId :: DefId ( id) => id. krate ,
123123 }
124124 }
125+
126+ pub ( crate ) fn links ( & self , cx : & Context < ' _ > ) -> Vec < RenderedLink > {
127+ use crate :: html:: format:: { href_with_path_check, link_tooltip} ;
128+
129+ let Some ( links) = cx. cache ( ) . intra_doc_links . get ( & self ) else {
130+ return vec ! [ ] ;
131+ } ;
132+ links
133+ . iter ( )
134+ . filter_map ( |ItemLink { link : s, link_text, page_id : id, fragment } | {
135+ debug ! ( ?id) ;
136+ if let Ok ( HrefInfo { mut url, .. } ) = href_with_path_check ( * id, cx, link_text) {
137+ debug ! ( ?url) ;
138+ match fragment {
139+ Some ( UrlFragment :: Item ( def_id) ) => {
140+ write ! ( url, "{}" , crate :: html:: format:: fragment( * def_id, cx. tcx( ) ) )
141+ . unwrap ( ) ;
142+ }
143+ Some ( UrlFragment :: UserWritten ( raw) ) => {
144+ url. push ( '#' ) ;
145+ url. push_str ( raw) ;
146+ }
147+ None => { }
148+ }
149+ Some ( RenderedLink {
150+ original_text : s. clone ( ) ,
151+ new_text : link_text. clone ( ) ,
152+ tooltip : link_tooltip ( * id, fragment, cx, Some ( link_text) ) . to_string ( ) ,
153+ href : url,
154+ } )
155+ } else {
156+ None
157+ }
158+ } )
159+ . collect ( )
160+ }
125161}
126162
127163impl From < DefId > for ItemId {
@@ -363,7 +399,7 @@ impl fmt::Debug for Item {
363399 fmt. field ( "attrs" , & self . attrs ) . field ( "kind" , & self . kind ) . field ( "cfg" , & self . cfg ) ;
364400 } else {
365401 fmt. field ( "kind" , & self . type_ ( ) ) ;
366- fmt. field ( "docs" , & self . doc_value ( ) ) ;
402+ fmt. field ( "docs" , & self . doc_values ( ) . values ( ) . cloned ( ) . collect :: < Vec < String > > ( ) ) ;
367403 }
368404 fmt. finish ( )
369405 }
@@ -507,16 +543,20 @@ impl Item {
507543 . unwrap_or_else ( || self . span ( tcx) . map_or ( DUMMY_SP , |span| span. inner ( ) ) )
508544 }
509545
510- /// Combine all doc strings into a single value handling indentation and newlines as needed.
511- pub ( crate ) fn doc_value ( & self ) -> String {
512- self . attrs . doc_value ( )
546+ /// Combine each reexport's docstrings into one docstring per item, handling indentation and
547+ /// newlines as needed.
548+ pub ( crate ) fn doc_values ( & self ) -> FxIndexMap < Option < DefId > , String > {
549+ self . attrs . doc_values ( )
513550 }
514551
515- /// Combine all doc strings into a single value handling indentation and newlines as needed.
552+ /// Combine each reexport's docstrings into one docstring per item.
553+ ///
516554 /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
517555 /// documentation but it is empty (e.g. `#[doc = ""]`).
518- pub ( crate ) fn opt_doc_value ( & self ) -> Option < String > {
519- self . attrs . opt_doc_value ( )
556+ ///
557+ /// The trailing newline is trimmed.
558+ pub ( crate ) fn opt_doc_values ( & self ) -> Option < FxIndexMap < Option < DefId > , String > > {
559+ self . attrs . opt_doc_values ( )
520560 }
521561
522562 pub ( crate ) fn from_def_id_and_parts (
@@ -559,58 +599,6 @@ impl Item {
559599 }
560600 }
561601
562- /// If the item has doc comments from a reexport, returns the item id of that reexport,
563- /// otherwise returns returns the item id.
564- ///
565- /// This is used as a key for caching intra-doc link resolution,
566- /// to prevent two reexports of the same item from using the same cache.
567- pub ( crate ) fn item_or_reexport_id ( & self ) -> ItemId {
568- // added documentation on a reexport is always prepended.
569- self . attrs
570- . doc_strings
571- . first ( )
572- . map ( |x| x. item_id )
573- . flatten ( )
574- . map ( ItemId :: from)
575- . unwrap_or ( self . item_id )
576- }
577-
578- pub ( crate ) fn links ( & self , cx : & Context < ' _ > ) -> Vec < RenderedLink > {
579- use crate :: html:: format:: { href_with_path_check, link_tooltip} ;
580-
581- let Some ( links) = cx. cache ( ) . intra_doc_links . get ( & self . item_or_reexport_id ( ) ) else {
582- return vec ! [ ] ;
583- } ;
584- links
585- . iter ( )
586- . filter_map ( |ItemLink { link : s, link_text, page_id : id, fragment } | {
587- debug ! ( ?id) ;
588- if let Ok ( HrefInfo { mut url, .. } ) = href_with_path_check ( * id, cx, link_text) {
589- debug ! ( ?url) ;
590- match fragment {
591- Some ( UrlFragment :: Item ( def_id) ) => {
592- write ! ( url, "{}" , crate :: html:: format:: fragment( * def_id, cx. tcx( ) ) )
593- . unwrap ( ) ;
594- }
595- Some ( UrlFragment :: UserWritten ( raw) ) => {
596- url. push ( '#' ) ;
597- url. push_str ( raw) ;
598- }
599- None => { }
600- }
601- Some ( RenderedLink {
602- original_text : s. clone ( ) ,
603- new_text : link_text. clone ( ) ,
604- tooltip : link_tooltip ( * id, fragment, cx, Some ( link_text) ) . to_string ( ) ,
605- href : url,
606- } )
607- } else {
608- None
609- }
610- } )
611- . collect ( )
612- }
613-
614602 /// Find a list of all link names, without finding their href.
615603 ///
616604 /// This is used for generating summary text, which does not include
@@ -1095,21 +1083,26 @@ impl Attributes {
10951083 Attributes { doc_strings, other_attrs }
10961084 }
10971085
1098- /// Combine all doc strings into a single value handling indentation and newlines as needed.
1099- pub ( crate ) fn doc_value ( & self ) -> String {
1100- self . opt_doc_value ( ) . unwrap_or_default ( )
1086+ /// Combine each reexport's docstrings into one docstring per item, handling indentation and
1087+ /// newlines as needed.
1088+ pub ( crate ) fn doc_values ( & self ) -> FxIndexMap < Option < DefId > , String > {
1089+ self . opt_doc_values ( ) . unwrap_or_default ( )
11011090 }
11021091
1103- /// Combine all doc strings into a single value handling indentation and newlines as needed.
1092+ /// Combine each reexport's docstrings into one docstring per item.
1093+ ///
11041094 /// Returns `None` is there's no documentation at all, and `Some("")` if there is some
11051095 /// documentation but it is empty (e.g. `#[doc = ""]`).
1106- pub ( crate ) fn opt_doc_value ( & self ) -> Option < String > {
1096+ ///
1097+ /// The trailing newline is trimmed.
1098+ pub ( crate ) fn opt_doc_values ( & self ) -> Option < FxIndexMap < Option < DefId > , String > > {
11071099 ( !self . doc_strings . is_empty ( ) ) . then ( || {
1108- let mut res = String :: new ( ) ;
1109- for frag in & self . doc_strings {
1110- add_doc_fragment ( & mut res, frag) ;
1100+ let mut res = prepare_fragments ( & self . doc_strings ) ;
1101+ for string in res. values_mut ( ) {
1102+ if string. as_bytes ( ) . last ( ) == Some ( & b'\n' ) {
1103+ string. pop ( ) ;
1104+ }
11111105 }
1112- res. pop ( ) ;
11131106 res
11141107 } )
11151108 }
0 commit comments