@@ -200,16 +200,27 @@ impl ExternalCrate {
200
200
}
201
201
202
202
pub ( crate ) fn keywords ( & self , tcx : TyCtxt < ' _ > ) -> ThinVec < ( DefId , Symbol ) > {
203
+ self . retrieve_keywords_or_documented_attributes ( tcx, sym:: keyword)
204
+ }
205
+ pub ( crate ) fn documented_attributes ( & self , tcx : TyCtxt < ' _ > ) -> ThinVec < ( DefId , Symbol ) > {
206
+ self . retrieve_keywords_or_documented_attributes ( tcx, sym:: attribute)
207
+ }
208
+
209
+ fn retrieve_keywords_or_documented_attributes (
210
+ & self ,
211
+ tcx : TyCtxt < ' _ > ,
212
+ name : Symbol ,
213
+ ) -> ThinVec < ( DefId , Symbol ) > {
203
214
let root = self . def_id ( ) ;
204
215
205
- let as_keyword = |res : Res < !> | {
216
+ let as_target = |res : Res < !> | {
206
217
if let Res :: Def ( DefKind :: Mod , def_id) = res {
207
218
let mut keyword = None ;
208
219
let meta_items = tcx
209
220
. get_attrs ( def_id, sym:: doc)
210
221
. flat_map ( |attr| attr. meta_item_list ( ) . unwrap_or_default ( ) ) ;
211
222
for meta in meta_items {
212
- if meta. has_name ( sym :: keyword )
223
+ if meta. has_name ( name )
213
224
&& let Some ( v) = meta. value_str ( )
214
225
{
215
226
keyword = Some ( v) ;
@@ -228,14 +239,14 @@ impl ExternalCrate {
228
239
let item = tcx. hir_item ( id) ;
229
240
match item. kind {
230
241
hir:: ItemKind :: Mod ( ..) => {
231
- as_keyword ( Res :: Def ( DefKind :: Mod , id. owner_id . to_def_id ( ) ) )
242
+ as_target ( Res :: Def ( DefKind :: Mod , id. owner_id . to_def_id ( ) ) )
232
243
}
233
244
_ => None ,
234
245
}
235
246
} )
236
247
. collect ( )
237
248
} else {
238
- tcx. module_children ( root) . iter ( ) . map ( |item| item. res ) . filter_map ( as_keyword ) . collect ( )
249
+ tcx. module_children ( root) . iter ( ) . map ( |item| item. res ) . filter_map ( as_target ) . collect ( )
239
250
}
240
251
}
241
252
@@ -597,6 +608,9 @@ impl Item {
597
608
pub ( crate ) fn is_keyword ( & self ) -> bool {
598
609
self . type_ ( ) == ItemType :: Keyword
599
610
}
611
+ pub ( crate ) fn is_attribute ( & self ) -> bool {
612
+ self . type_ ( ) == ItemType :: Attribute
613
+ }
600
614
pub ( crate ) fn is_stripped ( & self ) -> bool {
601
615
match self . kind {
602
616
StrippedItem ( ..) => true ,
@@ -727,7 +741,9 @@ impl Item {
727
741
// Primitives and Keywords are written in the source code as private modules.
728
742
// The modules need to be private so that nobody actually uses them, but the
729
743
// keywords and primitives that they are documenting are public.
730
- ItemKind :: KeywordItem | ItemKind :: PrimitiveItem ( _) => return Some ( Visibility :: Public ) ,
744
+ ItemKind :: KeywordItem | ItemKind :: PrimitiveItem ( _) | ItemKind :: AttributeItem => {
745
+ return Some ( Visibility :: Public ) ;
746
+ }
731
747
// Variant fields inherit their enum's visibility.
732
748
StructFieldItem ( ..) if is_field_vis_inherited ( tcx, def_id) => {
733
749
return None ;
@@ -943,7 +959,12 @@ pub(crate) enum ItemKind {
943
959
AssocTypeItem ( Box < TypeAlias > , Vec < GenericBound > ) ,
944
960
/// An item that has been stripped by a rustdoc pass
945
961
StrippedItem ( Box < ItemKind > ) ,
962
+ /// This item represents a module with a `#[doc(keyword = "...")]` attribute which is used
963
+ /// to generate documentation for Rust keywords.
946
964
KeywordItem ,
965
+ /// This item represents a module with a `#[doc(attribute = "...")]` attribute which is used
966
+ /// to generate documentation for Rust builtin attributes.
967
+ AttributeItem ,
947
968
}
948
969
949
970
impl ItemKind {
@@ -984,7 +1005,8 @@ impl ItemKind {
984
1005
| RequiredAssocTypeItem ( ..)
985
1006
| AssocTypeItem ( ..)
986
1007
| StrippedItem ( _)
987
- | KeywordItem => [ ] . iter ( ) ,
1008
+ | KeywordItem
1009
+ | AttributeItem => [ ] . iter ( ) ,
988
1010
}
989
1011
}
990
1012
0 commit comments