11use std:: fmt;
22
3+ use rustc_ast:: attr:: AttributeExt ;
4+ use rustc_ast:: token:: CommentKind ;
35use rustc_ast:: util:: parser:: ExprPrecedence ;
46use rustc_ast:: {
5- self as ast, Attribute , FloatTy , InlineAsmOptions , InlineAsmTemplatePiece , IntTy , Label ,
6- LitKind , TraitObjectSyntax , UintTy ,
7+ self as ast, AttrId , AttrStyle , DelimArgs , FloatTy , InlineAsmOptions , InlineAsmTemplatePiece ,
8+ IntTy , Label , LitKind , MetaItemLit , TraitObjectSyntax , UintTy ,
79} ;
810pub use rustc_ast:: {
911 BinOp , BinOpKind , BindingMode , BorrowKind , ByRef , CaptureBy , ImplPolarity , IsAuto , Movability ,
@@ -21,6 +23,7 @@ use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Span};
2123use rustc_target:: asm:: InlineAsmRegOrRegClass ;
2224use rustc_target:: spec:: abi:: Abi ;
2325use smallvec:: SmallVec ;
26+ use thin_vec:: ThinVec ;
2427use tracing:: debug;
2528
2629use crate :: LangItem ;
@@ -942,6 +945,174 @@ pub struct ParentedNode<'tcx> {
942945 pub node : Node < ' tcx > ,
943946}
944947
948+ /// Arguments passed to an attribute macro.
949+ #[ derive( Clone , Debug , HashStable_Generic , Encodable , Decodable ) ]
950+ pub enum AttrArgs {
951+ /// No arguments: `#[attr]`.
952+ Empty ,
953+ /// Delimited arguments: `#[attr()/[]/{}]`.
954+ Delimited ( DelimArgs ) ,
955+ /// Arguments of a key-value attribute: `#[attr = "value"]`.
956+ Eq (
957+ /// Span of the `=` token.
958+ Span ,
959+ /// The "value".
960+ MetaItemLit ,
961+ ) ,
962+ }
963+
964+ #[ derive( Clone , Debug , Encodable , Decodable ) ]
965+ pub enum AttrKind {
966+ /// A normal attribute.
967+ Normal ( AttrItem ) ,
968+
969+ /// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`).
970+ /// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
971+ /// variant (which is much less compact and thus more expensive).
972+ DocComment ( CommentKind , Symbol ) ,
973+ }
974+
975+ #[ derive( Clone , Debug , HashStable_Generic , Encodable , Decodable ) ]
976+ pub struct AttrPath {
977+ pub segments : Box < [ Ident ] > ,
978+ pub span : Span ,
979+ }
980+
981+ #[ derive( Clone , Debug , HashStable_Generic , Encodable , Decodable ) ]
982+ pub struct AttrItem {
983+ pub unsafety : Safety ,
984+ // Not lowered to hir::Path because we have no NodeId to resolve to.
985+ pub path : AttrPath ,
986+ pub args : AttrArgs ,
987+ }
988+
989+ #[ derive( Clone , Debug , Encodable , Decodable ) ]
990+ pub struct Attribute {
991+ pub kind : AttrKind ,
992+ pub id : AttrId ,
993+ /// Denotes if the attribute decorates the following construct (outer)
994+ /// or the construct this attribute is contained within (inner).
995+ pub style : AttrStyle ,
996+ pub span : Span ,
997+ }
998+
999+ impl Attribute {
1000+ pub fn get_normal_item ( & self ) -> & AttrItem {
1001+ match & self . kind {
1002+ AttrKind :: Normal ( normal) => & normal,
1003+ AttrKind :: DocComment ( ..) => panic ! ( "unexpected doc comment" ) ,
1004+ }
1005+ }
1006+
1007+ pub fn unwrap_normal_item ( self ) -> AttrItem {
1008+ match self . kind {
1009+ AttrKind :: Normal ( normal) => normal,
1010+ AttrKind :: DocComment ( ..) => panic ! ( "unexpected doc comment" ) ,
1011+ }
1012+ }
1013+
1014+ pub fn value_lit ( & self ) -> Option < & MetaItemLit > {
1015+ match & self . kind {
1016+ AttrKind :: Normal ( AttrItem { args : AttrArgs :: Eq ( _, lit) , .. } ) => Some ( lit) ,
1017+ _ => None ,
1018+ }
1019+ }
1020+ }
1021+
1022+ impl AttributeExt for Attribute {
1023+ fn id ( & self ) -> AttrId {
1024+ self . id
1025+ }
1026+
1027+ fn meta_item_list ( & self ) -> Option < ThinVec < ast:: MetaItemInner > > {
1028+ match & self . kind {
1029+ AttrKind :: Normal ( AttrItem { args : AttrArgs :: Delimited ( d) , .. } ) => {
1030+ ast:: MetaItemKind :: list_from_tokens ( d. tokens . clone ( ) )
1031+ }
1032+ _ => None ,
1033+ }
1034+ }
1035+
1036+ fn value_str ( & self ) -> Option < Symbol > {
1037+ self . value_lit ( ) . and_then ( |x| x. value_str ( ) )
1038+ }
1039+
1040+ fn value_span ( & self ) -> Option < Span > {
1041+ self . value_lit ( ) . map ( |i| i. span )
1042+ }
1043+
1044+ /// For a single-segment attribute, returns its name; otherwise, returns `None`.
1045+ fn ident ( & self ) -> Option < Ident > {
1046+ match & self . kind {
1047+ AttrKind :: Normal ( AttrItem { path, .. } ) => {
1048+ if let [ ident] = path. segments . as_ref ( ) {
1049+ Some ( * ident)
1050+ } else {
1051+ None
1052+ }
1053+ }
1054+ AttrKind :: DocComment ( ..) => None ,
1055+ }
1056+ }
1057+
1058+ fn path_matches ( & self , name : & [ Symbol ] ) -> bool {
1059+ match & self . kind {
1060+ AttrKind :: Normal ( AttrItem { path, .. } ) => {
1061+ path. segments . len ( ) == name. len ( )
1062+ && path. segments . iter ( ) . zip ( name) . all ( |( s, n) | s. name == * n)
1063+ }
1064+ AttrKind :: DocComment ( ..) => false ,
1065+ }
1066+ }
1067+
1068+ fn is_doc_comment ( & self ) -> bool {
1069+ matches ! ( self . kind, AttrKind :: DocComment ( ..) )
1070+ }
1071+
1072+ fn span ( & self ) -> Span {
1073+ self . span
1074+ }
1075+
1076+ fn is_word ( & self ) -> bool {
1077+ match & self . kind {
1078+ AttrKind :: Normal ( AttrItem { args, .. } ) => {
1079+ matches ! ( args, AttrArgs :: Empty )
1080+ }
1081+ AttrKind :: DocComment ( ..) => false ,
1082+ }
1083+ }
1084+
1085+ fn ident_path ( & self ) -> Option < SmallVec < [ Ident ; 1 ] > > {
1086+ match & self . kind {
1087+ AttrKind :: Normal ( AttrItem { path, .. } ) => {
1088+ Some ( path. segments . iter ( ) . copied ( ) . collect ( ) )
1089+ }
1090+ AttrKind :: DocComment ( ..) => None ,
1091+ }
1092+ }
1093+
1094+ fn doc_str ( & self ) -> Option < Symbol > {
1095+ match & self . kind {
1096+ AttrKind :: DocComment ( .., data) => Some ( * data) ,
1097+ AttrKind :: Normal ( _) if self . has_name ( sym:: doc) => self . value_str ( ) ,
1098+ _ => None ,
1099+ }
1100+ }
1101+ fn doc_str_and_comment_kind ( & self ) -> Option < ( Symbol , CommentKind ) > {
1102+ match & self . kind {
1103+ AttrKind :: DocComment ( kind, data) => Some ( ( * data, * kind) ) ,
1104+ AttrKind :: Normal ( _) if self . name_or_empty ( ) == sym:: doc => {
1105+ self . value_str ( ) . map ( |s| ( s, CommentKind :: Line ) )
1106+ }
1107+ _ => None ,
1108+ }
1109+ }
1110+
1111+ fn style ( & self ) -> AttrStyle {
1112+ self . style
1113+ }
1114+ }
1115+
9451116/// Attributes owned by a HIR owner.
9461117#[ derive( Debug ) ]
9471118pub struct AttributeMap < ' tcx > {
0 commit comments