@@ -287,24 +287,20 @@ impl CheckAttrVisitor<'tcx> {
287
287
}
288
288
}
289
289
290
- fn doc_alias_str_error ( & self , meta : & NestedMetaItem ) {
290
+ fn doc_attr_str_error ( & self , meta : & NestedMetaItem , attr_name : & str ) {
291
291
self . tcx
292
292
. sess
293
293
. struct_span_err (
294
294
meta. span ( ) ,
295
- "doc alias attribute expects a string: #[doc(alias = \" 0 \" )]" ,
295
+ & format ! ( "doc {0} attribute expects a string: #[doc({0} = \" a \" )]" , attr_name ) ,
296
296
)
297
297
. emit ( ) ;
298
298
}
299
299
300
300
fn check_doc_alias ( & self , meta : & NestedMetaItem , hir_id : HirId , target : Target ) -> bool {
301
- if !meta. is_value_str ( ) {
302
- self . doc_alias_str_error ( meta) ;
303
- return false ;
304
- }
305
301
let doc_alias = meta. value_str ( ) . map ( |s| s. to_string ( ) ) . unwrap_or_else ( String :: new) ;
306
302
if doc_alias. is_empty ( ) {
307
- self . doc_alias_str_error ( meta) ;
303
+ self . doc_attr_str_error ( meta, "alias" ) ;
308
304
return false ;
309
305
}
310
306
if let Some ( c) =
@@ -365,6 +361,49 @@ impl CheckAttrVisitor<'tcx> {
365
361
true
366
362
}
367
363
364
+ fn check_doc_keyword ( & self , meta : & NestedMetaItem , hir_id : HirId ) -> bool {
365
+ let doc_keyword = meta. value_str ( ) . map ( |s| s. to_string ( ) ) . unwrap_or_else ( String :: new) ;
366
+ if doc_keyword. is_empty ( ) {
367
+ self . doc_attr_str_error ( meta, "keyword" ) ;
368
+ return false ;
369
+ }
370
+ match self . tcx . hir ( ) . expect_item ( hir_id) . kind {
371
+ ItemKind :: Mod ( ref module) => {
372
+ if !module. item_ids . is_empty ( ) {
373
+ self . tcx
374
+ . sess
375
+ . struct_span_err (
376
+ meta. span ( ) ,
377
+ "`#[doc(keyword = \" ...\" )]` can only be used on empty modules" ,
378
+ )
379
+ . emit ( ) ;
380
+ return false ;
381
+ }
382
+ }
383
+ _ => {
384
+ self . tcx
385
+ . sess
386
+ . struct_span_err (
387
+ meta. span ( ) ,
388
+ "`#[doc(keyword = \" ...\" )]` can only be used on modules" ,
389
+ )
390
+ . emit ( ) ;
391
+ return false ;
392
+ }
393
+ }
394
+ if !rustc_lexer:: is_ident ( & doc_keyword) {
395
+ self . tcx
396
+ . sess
397
+ . struct_span_err (
398
+ meta. name_value_literal_span ( ) . unwrap_or_else ( || meta. span ( ) ) ,
399
+ & format ! ( "`{}` is not a valid identifier" , doc_keyword) ,
400
+ )
401
+ . emit ( ) ;
402
+ return false ;
403
+ }
404
+ true
405
+ }
406
+
368
407
fn check_attr_crate_level (
369
408
& self ,
370
409
meta : & NestedMetaItem ,
@@ -384,6 +423,7 @@ impl CheckAttrVisitor<'tcx> {
384
423
. emit ( ) ;
385
424
return false ;
386
425
}
426
+ true
387
427
}
388
428
389
429
fn check_doc_attrs ( & self , attr : & Attribute , hir_id : HirId , target : Target ) -> bool {
@@ -396,6 +436,12 @@ impl CheckAttrVisitor<'tcx> {
396
436
{
397
437
return false ;
398
438
}
439
+ } else if meta. has_name ( sym:: keyword) {
440
+ if !self . check_attr_crate_level ( meta, hir_id, "keyword" )
441
+ || !self . check_doc_keyword ( meta, hir_id)
442
+ {
443
+ return false ;
444
+ }
399
445
}
400
446
}
401
447
}
0 commit comments