@@ -14,18 +14,11 @@ 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 ,
2922}
3023
3124/// Iterate the attributes of the method to extract cfg attributes
@@ -48,32 +41,49 @@ pub fn extract_docs(attrs: &[Attribute]) -> Vec<Attribute> {
4841
4942impl < ' a > ParsedAttributes {
5043 /// 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
5245 pub fn require_attributes (
5346 mut attrs : Vec < Attribute > ,
54- allowed : & ' a [ & str ] ,
47+ allowed : & ' a [ ( AttributeConstraint , & str ) ] ,
5548 ) -> Result < ParsedAttributes > {
5649 let mut output = BTreeMap :: < String , Vec < Attribute > > :: default ( ) ;
50+ // Iterate all attributes found
5751 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+ } ) ;
6155 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+ }
6967 }
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+ } ,
7076 }
7177 } else {
7278 return Err ( Error :: new (
7379 attr. span ( ) ,
7480 format ! (
7581 "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( ", " )
7787 ) ,
7888 ) ) ;
7989 }
@@ -122,18 +132,6 @@ impl<'a> ParsedAttributes {
122132 self . cxx_qt_attrs . get ( key) ?. first ( )
123133 }
124134
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-
137135 /// Check if CXX-Qt or passthrough attributes contains a particular key
138136 pub fn contains_key ( & self , key : & str ) -> bool {
139137 self . cxx_qt_attrs . contains_key ( key) // TODO: Check in passthrough too
0 commit comments