@@ -914,7 +914,6 @@ crate struct DocFragment {
914914 crate parent_module : Option < DefId > ,
915915 crate doc : Symbol ,
916916 crate kind : DocFragmentKind ,
917- crate need_backline : bool ,
918917 crate indent : usize ,
919918}
920919
@@ -930,28 +929,25 @@ crate enum DocFragmentKind {
930929 RawDoc ,
931930}
932931
933- // The goal of this function is to apply the `DocFragment` transformations that are required when
934- // transforming into the final markdown. So the transformations in here are:
935- //
936- // * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
937- // multiple lines in case of `#[doc = ""]`).
938- // * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
939- // `need_backline` field).
932+ /// The goal of this function is to apply the `DocFragment` transformation that is required when
933+ /// transforming into the final Markdown, which is applying the computed indent to each line in
934+ /// each doc fragment (a `DocFragment` can contain multiple lines in case of `#[doc = ""]`).
935+ ///
936+ /// Note: remove the trailing newline where appropriate
940937fn add_doc_fragment ( out : & mut String , frag : & DocFragment ) {
941938 let s = frag. doc . as_str ( ) ;
942- let mut iter = s. lines ( ) . peekable ( ) ;
939+ let mut iter = s. lines ( ) ;
940+ if s == "" {
941+ out. push ( '\n' ) ;
942+ return ;
943+ }
943944 while let Some ( line) = iter. next ( ) {
944945 if line. chars ( ) . any ( |c| !c. is_whitespace ( ) ) {
945946 assert ! ( line. len( ) >= frag. indent) ;
946947 out. push_str ( & line[ frag. indent ..] ) ;
947948 } else {
948949 out. push_str ( line) ;
949950 }
950- if iter. peek ( ) . is_some ( ) {
951- out. push ( '\n' ) ;
952- }
953- }
954- if frag. need_backline {
955951 out. push ( '\n' ) ;
956952 }
957953}
@@ -963,6 +959,7 @@ crate fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
963959 for frag in doc_strings {
964960 add_doc_fragment ( & mut acc, frag) ;
965961 }
962+ acc. pop ( ) ;
966963 acc
967964}
968965
@@ -1028,7 +1025,6 @@ impl Attributes {
10281025 additional_attrs : Option < ( & [ ast:: Attribute ] , DefId ) > ,
10291026 ) -> Attributes {
10301027 let mut doc_strings: Vec < DocFragment > = vec ! [ ] ;
1031-
10321028 let clean_attr = |( attr, parent_module) : ( & ast:: Attribute , Option < DefId > ) | {
10331029 if let Some ( value) = attr. doc_str ( ) {
10341030 trace ! ( "got doc_str={:?}" , value) ;
@@ -1039,18 +1035,8 @@ impl Attributes {
10391035 DocFragmentKind :: RawDoc
10401036 } ;
10411037
1042- let frag = DocFragment {
1043- span : attr. span ,
1044- doc : value,
1045- kind,
1046- parent_module,
1047- need_backline : false ,
1048- indent : 0 ,
1049- } ;
1050-
1051- if let Some ( prev) = doc_strings. last_mut ( ) {
1052- prev. need_backline = true ;
1053- }
1038+ let frag =
1039+ DocFragment { span : attr. span , doc : value, kind, parent_module, indent : 0 } ;
10541040
10551041 doc_strings. push ( frag) ;
10561042
@@ -1086,6 +1072,7 @@ impl Attributes {
10861072 }
10871073 add_doc_fragment ( & mut out, new_frag) ;
10881074 }
1075+ out. pop ( ) ;
10891076 if out. is_empty ( ) { None } else { Some ( out) }
10901077 }
10911078
@@ -1094,10 +1081,17 @@ impl Attributes {
10941081 /// The module can be different if this is a re-export with added documentation.
10951082 crate fn collapsed_doc_value_by_module_level ( & self ) -> FxHashMap < Option < DefId > , String > {
10961083 let mut ret = FxHashMap :: default ( ) ;
1084+ if self . doc_strings . len ( ) == 0 {
1085+ return ret;
1086+ }
1087+ let last_index = self . doc_strings . len ( ) - 1 ;
10971088
1098- for new_frag in self . doc_strings . iter ( ) {
1089+ for ( i , new_frag) in self . doc_strings . iter ( ) . enumerate ( ) {
10991090 let out = ret. entry ( new_frag. parent_module ) . or_default ( ) ;
11001091 add_doc_fragment ( out, new_frag) ;
1092+ if i == last_index {
1093+ out. pop ( ) ;
1094+ }
11011095 }
11021096 ret
11031097 }
0 commit comments