@@ -226,15 +226,28 @@ impl ExternalCrate {
226226 }
227227
228228 pub ( crate ) fn keywords ( & self , tcx : TyCtxt < ' _ > ) -> impl Iterator < Item = ( DefId , Symbol ) > {
229- fn as_keyword ( did : DefId , tcx : TyCtxt < ' _ > ) -> Option < ( DefId , Symbol ) > {
229+ self . retrieve_keywords_or_documented_attributes ( tcx, sym:: keyword)
230+ }
231+ pub ( crate ) fn documented_attributes (
232+ & self ,
233+ tcx : TyCtxt < ' _ > ,
234+ ) -> impl Iterator < Item = ( DefId , Symbol ) > {
235+ self . retrieve_keywords_or_documented_attributes ( tcx, sym:: attribute)
236+ }
237+
238+ fn retrieve_keywords_or_documented_attributes (
239+ & self ,
240+ tcx : TyCtxt < ' _ > ,
241+ name : Symbol ,
242+ ) -> impl Iterator < Item = ( DefId , Symbol ) > {
243+ let as_target = move |did : DefId , tcx : TyCtxt < ' _ > | -> Option < ( DefId , Symbol ) > {
230244 tcx. get_attrs ( did, sym:: doc)
231245 . flat_map ( |attr| attr. meta_item_list ( ) . unwrap_or_default ( ) )
232- . filter ( |meta| meta. has_name ( sym :: keyword ) )
246+ . filter ( |meta| meta. has_name ( name ) )
233247 . find_map ( |meta| meta. value_str ( ) )
234248 . map ( |value| ( did, value) )
235- }
236-
237- self . mapped_root_modules ( tcx, as_keyword)
249+ } ;
250+ self . mapped_root_modules ( tcx, as_target)
238251 }
239252
240253 pub ( crate ) fn primitives (
@@ -592,6 +605,9 @@ impl Item {
592605 pub ( crate ) fn is_keyword ( & self ) -> bool {
593606 self . type_ ( ) == ItemType :: Keyword
594607 }
608+ pub ( crate ) fn is_attribute ( & self ) -> bool {
609+ self . type_ ( ) == ItemType :: Attribute
610+ }
595611 pub ( crate ) fn is_stripped ( & self ) -> bool {
596612 match self . kind {
597613 StrippedItem ( ..) => true ,
@@ -735,7 +751,9 @@ impl Item {
735751 // Primitives and Keywords are written in the source code as private modules.
736752 // The modules need to be private so that nobody actually uses them, but the
737753 // keywords and primitives that they are documenting are public.
738- ItemKind :: KeywordItem | ItemKind :: PrimitiveItem ( _) => return Some ( Visibility :: Public ) ,
754+ ItemKind :: KeywordItem | ItemKind :: PrimitiveItem ( _) | ItemKind :: AttributeItem => {
755+ return Some ( Visibility :: Public ) ;
756+ }
739757 // Variant fields inherit their enum's visibility.
740758 StructFieldItem ( ..) if is_field_vis_inherited ( tcx, def_id) => {
741759 return None ;
@@ -942,7 +960,12 @@ pub(crate) enum ItemKind {
942960 AssocTypeItem ( Box < TypeAlias > , Vec < GenericBound > ) ,
943961 /// An item that has been stripped by a rustdoc pass
944962 StrippedItem ( Box < ItemKind > ) ,
963+ /// This item represents a module with a `#[doc(keyword = "...")]` attribute which is used
964+ /// to generate documentation for Rust keywords.
945965 KeywordItem ,
966+ /// This item represents a module with a `#[doc(attribute = "...")]` attribute which is used
967+ /// to generate documentation for Rust builtin attributes.
968+ AttributeItem ,
946969}
947970
948971impl ItemKind {
@@ -983,7 +1006,8 @@ impl ItemKind {
9831006 | RequiredAssocTypeItem ( ..)
9841007 | AssocTypeItem ( ..)
9851008 | StrippedItem ( _)
986- | KeywordItem => [ ] . iter ( ) ,
1009+ | KeywordItem
1010+ | AttributeItem => [ ] . iter ( ) ,
9871011 }
9881012 }
9891013
0 commit comments