@@ -14,18 +14,11 @@ pub struct ParsedAttributes {
14
14
pub passthrough_attrs : Vec < Attribute > ,
15
15
}
16
16
17
- // TODO: ATTR could this instead be used as Result<ParsedAttribute> to encapsulate error states
18
- pub enum ParsedAttribute < ' a > {
19
- /// A single attribute was found
20
- Single ( & ' a Attribute ) ,
21
- /// An attribute was not found, but this is ok
22
- Absent ,
23
- /// An attribute was not found, and this is an error
24
- AbsentRequired ,
25
- /// Multiple attributes were found, but this is ok
26
- Multiple ( Vec < & ' a Attribute > ) ,
27
- /// Multiple attributes were found, but this is an error
28
- MultipleDisallowed ( Vec < & ' a Attribute > ) ,
17
+ pub enum AttributeConstraint {
18
+ /// Indicates that there must be only one of this attribute
19
+ Unique ,
20
+ /// Indicates there can be multiple of this attribute
21
+ Duplicate ,
29
22
}
30
23
31
24
/// Iterate the attributes of the method to extract cfg attributes
@@ -48,32 +41,49 @@ pub fn extract_docs(attrs: &[Attribute]) -> Vec<Attribute> {
48
41
49
42
impl < ' a > ParsedAttributes {
50
43
/// Collects a Map of all attributes found from the allowed list
51
- /// Will error if an attribute which is not in the allowed list is found
44
+ /// Will error if an attribute which is not in the allowed list is found, or attribute is used incorrectly
52
45
pub fn require_attributes (
53
46
mut attrs : Vec < Attribute > ,
54
- allowed : & ' a [ & str ] ,
47
+ allowed : & ' a [ ( AttributeConstraint , & str ) ] ,
55
48
) -> Result < ParsedAttributes > {
56
49
let mut output = BTreeMap :: < String , Vec < Attribute > > :: default ( ) ;
50
+ // Iterate all attributes found
57
51
for attr in attrs. drain ( ..) {
58
- let index = allowed
59
- . iter ( )
60
- . position ( |string| path_compare_str ( attr . meta . path ( ) , & parser :: split_path ( string ) ) ) ;
52
+ let index = allowed. iter ( ) . position ( | ( _ , string ) | {
53
+ path_compare_str ( attr . meta . path ( ) , & parser :: split_path ( string ) )
54
+ } ) ;
61
55
if let Some ( index) = index {
62
- // TODO: ATTR Doesn't error on duplicates / distinguish allowed and disallowed duplicates
63
- match output. entry ( allowed[ index] . into ( ) ) {
64
- Entry :: Occupied ( mut entry) => {
65
- entry. get_mut ( ) . push ( attr) ;
66
- }
67
- Entry :: Vacant ( entry) => {
68
- entry. insert ( vec ! [ attr] ) ;
56
+ match allowed[ index] . 0 {
57
+ AttributeConstraint :: Unique => {
58
+ match output. entry ( allowed[ index] . 1 . into ( ) ) {
59
+ Entry :: Occupied ( _) => return Err ( Error :: new_spanned (
60
+ attr,
61
+ "There must be at most one of this attribute on this given item" ,
62
+ ) ) ,
63
+ Entry :: Vacant ( entry) => {
64
+ entry. insert ( vec ! [ attr] ) ;
65
+ }
66
+ }
69
67
}
68
+ AttributeConstraint :: Duplicate => match output. entry ( allowed[ index] . 1 . into ( ) ) {
69
+ Entry :: Occupied ( mut entry) => {
70
+ entry. get_mut ( ) . push ( attr) ;
71
+ }
72
+ Entry :: Vacant ( entry) => {
73
+ entry. insert ( vec ! [ attr] ) ;
74
+ }
75
+ } ,
70
76
}
71
77
} else {
72
78
return Err ( Error :: new (
73
79
attr. span ( ) ,
74
80
format ! (
75
81
"Unsupported attribute! The only attributes allowed on this item are\n {}" ,
76
- allowed. join( ", " )
82
+ allowed
83
+ . iter( )
84
+ . map( |( _, string) | * string)
85
+ . collect:: <Vec <_>>( )
86
+ . join( ", " )
77
87
) ,
78
88
) ) ;
79
89
}
@@ -122,18 +132,6 @@ impl<'a> ParsedAttributes {
122
132
self . cxx_qt_attrs . get ( key) ?. first ( )
123
133
}
124
134
125
- pub fn require_one ( & self , key : & str ) -> ParsedAttribute {
126
- if let Some ( attrs) = self . cxx_qt_attrs . get ( key) {
127
- if attrs. len ( ) != 1 {
128
- ParsedAttribute :: MultipleDisallowed ( attrs. iter ( ) . by_ref ( ) . collect ( ) )
129
- } else {
130
- ParsedAttribute :: Single ( attrs. first ( ) . expect ( "Expected at least one attribute" ) )
131
- }
132
- } else {
133
- ParsedAttribute :: Absent
134
- }
135
- }
136
-
137
135
/// Check if CXX-Qt or passthrough attributes contains a particular key
138
136
pub fn contains_key ( & self , key : & str ) -> bool {
139
137
self . cxx_qt_attrs . contains_key ( key) // TODO: Check in passthrough too
0 commit comments