@@ -228,15 +228,28 @@ impl ExternalCrate {
228228 }
229229
230230 pub ( crate ) fn keywords ( & self , tcx : TyCtxt < ' _ > ) -> impl Iterator < Item = ( DefId , Symbol ) > {
231- fn as_keyword ( did : DefId , tcx : TyCtxt < ' _ > ) -> Option < ( DefId , Symbol ) > {
231+ self . retrieve_keywords_or_documented_attributes ( tcx, sym:: keyword)
232+ }
233+ pub ( crate ) fn documented_attributes (
234+ & self ,
235+ tcx : TyCtxt < ' _ > ,
236+ ) -> impl Iterator < Item = ( DefId , Symbol ) > {
237+ self . retrieve_keywords_or_documented_attributes ( tcx, sym:: attribute)
238+ }
239+
240+ fn retrieve_keywords_or_documented_attributes (
241+ & self ,
242+ tcx : TyCtxt < ' _ > ,
243+ name : Symbol ,
244+ ) -> impl Iterator < Item = ( DefId , Symbol ) > {
245+ let as_target = move |did : DefId , tcx : TyCtxt < ' _ > | -> Option < ( DefId , Symbol ) > {
232246 tcx. get_attrs ( did, sym:: doc)
233247 . flat_map ( |attr| attr. meta_item_list ( ) . unwrap_or_default ( ) )
234- . filter ( |meta| meta. has_name ( sym :: keyword ) )
248+ . filter ( |meta| meta. has_name ( name ) )
235249 . find_map ( |meta| meta. value_str ( ) )
236250 . map ( |value| ( did, value) )
237- }
238-
239- self . mapped_root_modules ( tcx, as_keyword)
251+ } ;
252+ self . mapped_root_modules ( tcx, as_target)
240253 }
241254
242255 pub ( crate ) fn primitives (
@@ -579,6 +592,9 @@ impl Item {
579592 pub ( crate ) fn is_keyword ( & self ) -> bool {
580593 self . type_ ( ) == ItemType :: Keyword
581594 }
595+ pub ( crate ) fn is_attribute ( & self ) -> bool {
596+ self . type_ ( ) == ItemType :: Attribute
597+ }
582598 pub ( crate ) fn is_stripped ( & self ) -> bool {
583599 match self . kind {
584600 StrippedItem ( ..) => true ,
@@ -722,7 +738,9 @@ impl Item {
722738 // Primitives and Keywords are written in the source code as private modules.
723739 // The modules need to be private so that nobody actually uses them, but the
724740 // keywords and primitives that they are documenting are public.
725- ItemKind :: KeywordItem | ItemKind :: PrimitiveItem ( _) => return Some ( Visibility :: Public ) ,
741+ ItemKind :: KeywordItem | ItemKind :: PrimitiveItem ( _) | ItemKind :: AttributeItem => {
742+ return Some ( Visibility :: Public ) ;
743+ }
726744 // Variant fields inherit their enum's visibility.
727745 StructFieldItem ( ..) if is_field_vis_inherited ( tcx, def_id) => {
728746 return None ;
@@ -959,7 +977,12 @@ pub(crate) enum ItemKind {
959977 AssocTypeItem ( Box < TypeAlias > , Vec < GenericBound > ) ,
960978 /// An item that has been stripped by a rustdoc pass
961979 StrippedItem ( Box < ItemKind > ) ,
980+ /// This item represents a module with a `#[doc(keyword = "...")]` attribute which is used
981+ /// to generate documentation for Rust keywords.
962982 KeywordItem ,
983+ /// This item represents a module with a `#[doc(attribute = "...")]` attribute which is used
984+ /// to generate documentation for Rust builtin attributes.
985+ AttributeItem ,
963986}
964987
965988impl ItemKind {
@@ -1000,7 +1023,8 @@ impl ItemKind {
10001023 | RequiredAssocTypeItem ( ..)
10011024 | AssocTypeItem ( ..)
10021025 | StrippedItem ( _)
1003- | KeywordItem => [ ] . iter ( ) ,
1026+ | KeywordItem
1027+ | AttributeItem => [ ] . iter ( ) ,
10041028 }
10051029 }
10061030
0 commit comments