@@ -391,6 +391,24 @@ pub enum DocFragmentKind {
391391 /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
392392 /// given filename and the file contents.
393393 Include { filename : String } ,
394+ /// A doc fragment used to distinguish between documentation in different modules.
395+ ///
396+ /// In particular, this prevents `collapse_docs` from turning all documentation comments
397+ /// into a single giant attributes even when the item is re-exported with documentation on the re-export.
398+ Divider ,
399+ }
400+
401+ impl DocFragment {
402+ /// Creates a dummy doc-fragment which divides earlier and later fragments.
403+ fn divider ( ) -> Self {
404+ DocFragment {
405+ line : 0 ,
406+ span : DUMMY_SP ,
407+ parent_module : None ,
408+ doc : String :: new ( ) ,
409+ kind : DocFragmentKind :: Divider ,
410+ }
411+ }
394412}
395413
396414impl < ' a > FromIterator < & ' a DocFragment > for String {
@@ -531,68 +549,72 @@ impl Attributes {
531549 attrs : & [ ast:: Attribute ] ,
532550 additional_attrs : Option < ( & [ ast:: Attribute ] , DefId ) > ,
533551 ) -> Attributes {
534- let mut doc_strings = vec ! [ ] ;
552+ let doc_strings = RefCell :: new ( vec ! [ ] ) ;
535553 let mut sp = None ;
536554 let mut cfg = Cfg :: True ;
537555 let mut doc_line = 0 ;
538556
539- // Additional documentation should be shown before the original documentation
540- let other_attrs = additional_attrs
541- . into_iter ( )
542- . map ( |( attrs, id) | attrs. iter ( ) . map ( move |attr| ( attr, Some ( id) ) ) )
543- . flatten ( )
544- . chain ( attrs. iter ( ) . map ( |attr| ( attr, None ) ) )
545- . filter_map ( |( attr, parent_module) | {
546- if let Some ( value) = attr. doc_str ( ) {
547- trace ! ( "got doc_str={:?}" , value) ;
548- let value = beautify_doc_string ( value) ;
549- let kind = if attr. is_doc_comment ( ) {
550- DocFragmentKind :: SugaredDoc
551- } else {
552- DocFragmentKind :: RawDoc
553- } ;
554-
555- let line = doc_line;
556- doc_line += value. lines ( ) . count ( ) ;
557- doc_strings. push ( DocFragment {
558- line,
559- span : attr. span ,
560- doc : value,
561- kind,
562- parent_module,
563- } ) ;
564-
565- if sp. is_none ( ) {
566- sp = Some ( attr. span ) ;
567- }
568- None
557+ let clean_attr = |( attr, parent_module) : ( & ast:: Attribute , _ ) | {
558+ if let Some ( value) = attr. doc_str ( ) {
559+ trace ! ( "got doc_str={:?}" , value) ;
560+ let value = beautify_doc_string ( value) ;
561+ let kind = if attr. is_doc_comment ( ) {
562+ DocFragmentKind :: SugaredDoc
569563 } else {
570- if attr. has_name ( sym:: doc) {
571- if let Some ( mi) = attr. meta ( ) {
572- if let Some ( cfg_mi) = Attributes :: extract_cfg ( & mi) {
573- // Extracted #[doc(cfg(...))]
574- match Cfg :: parse ( cfg_mi) {
575- Ok ( new_cfg) => cfg &= new_cfg,
576- Err ( e) => diagnostic. span_err ( e. span , e. msg ) ,
577- }
578- } else if let Some ( ( filename, contents) ) =
579- Attributes :: extract_include ( & mi)
580- {
581- let line = doc_line;
582- doc_line += contents. lines ( ) . count ( ) ;
583- doc_strings. push ( DocFragment {
584- line,
585- span : attr. span ,
586- doc : contents,
587- kind : DocFragmentKind :: Include { filename } ,
588- parent_module : parent_module,
589- } ) ;
564+ DocFragmentKind :: RawDoc
565+ } ;
566+
567+ let line = doc_line;
568+ doc_line += value. lines ( ) . count ( ) ;
569+ doc_strings. borrow_mut ( ) . push ( DocFragment {
570+ line,
571+ span : attr. span ,
572+ doc : value,
573+ kind,
574+ parent_module,
575+ } ) ;
576+
577+ if sp. is_none ( ) {
578+ sp = Some ( attr. span ) ;
579+ }
580+ None
581+ } else {
582+ if attr. has_name ( sym:: doc) {
583+ if let Some ( mi) = attr. meta ( ) {
584+ if let Some ( cfg_mi) = Attributes :: extract_cfg ( & mi) {
585+ // Extracted #[doc(cfg(...))]
586+ match Cfg :: parse ( cfg_mi) {
587+ Ok ( new_cfg) => cfg &= new_cfg,
588+ Err ( e) => diagnostic. span_err ( e. span , e. msg ) ,
590589 }
590+ } else if let Some ( ( filename, contents) ) = Attributes :: extract_include ( & mi)
591+ {
592+ let line = doc_line;
593+ doc_line += contents. lines ( ) . count ( ) ;
594+ doc_strings. borrow_mut ( ) . push ( DocFragment {
595+ line,
596+ span : attr. span ,
597+ doc : contents,
598+ kind : DocFragmentKind :: Include { filename } ,
599+ parent_module : parent_module,
600+ } ) ;
591601 }
592602 }
593- Some ( attr. clone ( ) )
594603 }
604+ Some ( attr. clone ( ) )
605+ }
606+ } ;
607+
608+ // Additional documentation should be shown before the original documentation
609+ let other_attrs = additional_attrs
610+ . into_iter ( )
611+ . map ( |( attrs, id) | {
612+ doc_strings. borrow_mut ( ) . push ( DocFragment :: divider ( ) ) ;
613+ attrs. iter ( ) . map ( move |attr| ( attr, Some ( id) ) )
595614 } )
615+ . flatten ( )
616+ . chain ( attrs. iter ( ) . map ( |attr| ( attr, None ) ) )
617+ . filter_map ( clean_attr)
596618 . collect ( ) ;
597619
598620 // treat #[target_feature(enable = "feat")] attributes as if they were
@@ -618,7 +640,7 @@ impl Attributes {
618640 . map_or ( true , |a| a. style == AttrStyle :: Inner ) ;
619641
620642 Attributes {
621- doc_strings,
643+ doc_strings : doc_strings . into_inner ( ) ,
622644 other_attrs,
623645 cfg : if cfg == Cfg :: True { None } else { Some ( Arc :: new ( cfg) ) } ,
624646 span : sp,
0 commit comments