@@ -14,18 +14,13 @@ pub struct ParsedAttributes {
1414 pub passthrough_attrs : Vec < Attribute > ,
1515}
1616
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 ,
22+ /// Indicates that this attribute is required
23+ Required ,
2924}
3025
3126/// Iterate the attributes of the method to extract cfg attributes
@@ -48,32 +43,49 @@ pub fn extract_docs(attrs: &[Attribute]) -> Vec<Attribute> {
4843
4944impl < ' a > ParsedAttributes {
5045 /// 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
46+ /// Will error if an attribute which is not in the allowed list is found, or attribute is used incorrectly
5247 pub fn require_attributes (
5348 mut attrs : Vec < Attribute > ,
54- allowed : & ' a [ & str ] ,
49+ allowed : & ' a [ ( AttributeConstraint , & str ) ] ,
5550 ) -> Result < ParsedAttributes > {
5651 let mut output = BTreeMap :: < String , Vec < Attribute > > :: default ( ) ;
5752 for attr in attrs. drain ( ..) {
58- let index = allowed
59- . iter ( )
60- . position ( |string| path_compare_str ( attr . meta . path ( ) , & parser :: split_path ( string ) ) ) ;
53+ let index = allowed. iter ( ) . position ( | ( _ , string ) | {
54+ path_compare_str ( attr . meta . path ( ) , & parser :: split_path ( string ) )
55+ } ) ;
6156 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] ) ;
57+ match allowed[ index] . 0 {
58+ AttributeConstraint :: Unique => {
59+ match output. entry ( allowed[ index] . 1 . into ( ) ) {
60+ Entry :: Occupied ( _) => return Err ( Error :: new_spanned (
61+ attr,
62+ "There must be at most one of this attribute on this given item" ,
63+ ) ) ,
64+ Entry :: Vacant ( entry) => {
65+ entry. insert ( vec ! [ attr] ) ;
66+ }
67+ }
6968 }
69+ AttributeConstraint :: Duplicate => match output. entry ( allowed[ index] . 1 . into ( ) ) {
70+ Entry :: Occupied ( mut entry) => {
71+ entry. get_mut ( ) . push ( attr) ;
72+ }
73+ Entry :: Vacant ( entry) => {
74+ entry. insert ( vec ! [ attr] ) ;
75+ }
76+ } ,
77+ AttributeConstraint :: Required => { }
7078 }
7179 } else {
7280 return Err ( Error :: new (
7381 attr. span ( ) ,
7482 format ! (
7583 "Unsupported attribute! The only attributes allowed on this item are\n {}" ,
76- allowed. join( ", " )
84+ allowed
85+ . iter( )
86+ . map( |( _, string) | * string)
87+ . collect:: <Vec <_>>( )
88+ . join( ", " )
7789 ) ,
7890 ) ) ;
7991 }
@@ -122,18 +134,6 @@ impl<'a> ParsedAttributes {
122134 self . cxx_qt_attrs . get ( key) ?. first ( )
123135 }
124136
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-
137137 /// Check if CXX-Qt or passthrough attributes contains a particular key
138138 pub fn contains_key ( & self , key : & str ) -> bool {
139139 self . cxx_qt_attrs . contains_key ( key) // TODO: Check in passthrough too
0 commit comments