1
1
use std:: fmt;
2
2
3
+ use rustc_ast:: attr:: AttributeExt ;
4
+ use rustc_ast:: token:: CommentKind ;
3
5
use rustc_ast:: util:: parser:: ExprPrecedence ;
4
6
use 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 ,
7
9
} ;
8
10
pub use rustc_ast:: {
9
11
BinOp , BinOpKind , BindingMode , BorrowKind , ByRef , CaptureBy , ImplPolarity , IsAuto , Movability ,
@@ -21,6 +23,7 @@ use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Span};
21
23
use rustc_target:: asm:: InlineAsmRegOrRegClass ;
22
24
use rustc_target:: spec:: abi:: Abi ;
23
25
use smallvec:: SmallVec ;
26
+ use thin_vec:: ThinVec ;
24
27
use tracing:: debug;
25
28
26
29
use crate :: LangItem ;
@@ -942,6 +945,174 @@ pub struct ParentedNode<'tcx> {
942
945
pub node : Node < ' tcx > ,
943
946
}
944
947
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
+
945
1116
/// Attributes owned by a HIR owner.
946
1117
#[ derive( Debug ) ]
947
1118
pub struct AttributeMap < ' tcx > {
0 commit comments