44// SPDX-License-Identifier: MIT OR Apache-2.0
55
66use crate :: { parser, syntax:: path:: path_compare_str} ;
7+ use std:: collections:: btree_map:: Entry ;
78use std:: collections:: BTreeMap ;
89use syn:: { spanned:: Spanned , Attribute , Error , Result } ;
910
10- pub struct ParsedAttribute < ' a > {
11- pub cxx_qt_attrs : BTreeMap < & ' a str , & ' a Attribute > ,
12- pub passthrough_attrs : BTreeMap < & ' a str , & ' a Attribute > ,
11+ #[ derive( Clone ) ]
12+ pub struct ParsedAttributes {
13+ pub cxx_qt_attrs : BTreeMap < String , Vec < Attribute > > ,
14+ pub passthrough_attrs : Vec < Attribute > ,
1315}
1416
1517/// Iterate the attributes of the method to extract cfg attributes
@@ -30,20 +32,28 @@ pub fn extract_docs(attrs: &[Attribute]) -> Vec<Attribute> {
3032 . collect ( )
3133}
3234
33- impl < ' a > ParsedAttribute < ' a > {
35+ impl < ' a > ParsedAttributes {
3436 /// Collects a Map of all attributes found from the allowed list
3537 /// Will error if an attribute which is not in the allowed list is found
3638 pub fn require_attributes (
37- attrs : & ' a [ Attribute ] ,
39+ mut attrs : Vec < Attribute > ,
3840 allowed : & ' a [ & str ] ,
39- ) -> Result < ParsedAttribute < ' a > > {
40- let mut output = BTreeMap :: default ( ) ;
41- for attr in attrs {
41+ ) -> Result < ParsedAttributes > {
42+ let mut output = BTreeMap :: < String , Vec < Attribute > > :: default ( ) ;
43+ for attr in attrs. drain ( .. ) {
4244 let index = allowed
4345 . iter ( )
4446 . position ( |string| path_compare_str ( attr. meta . path ( ) , & parser:: split_path ( string) ) ) ;
4547 if let Some ( index) = index {
46- output. insert ( allowed[ index] , attr) ; // TODO: Doesn't error on duplicates
48+ // TODO: ATTR Doesn't error on duplicates / distinguish allowed and disallowed duplicates
49+ match output. entry ( allowed[ index] . into ( ) ) {
50+ Entry :: Occupied ( mut entry) => {
51+ entry. get_mut ( ) . push ( attr) ;
52+ }
53+ Entry :: Vacant ( entry) => {
54+ entry. insert ( vec ! [ attr] ) ;
55+ }
56+ }
4757 } else {
4858 return Err ( Error :: new (
4959 attr. span ( ) ,
@@ -56,23 +66,54 @@ impl<'a> ParsedAttribute<'a> {
5666 }
5767 Ok ( Self {
5868 cxx_qt_attrs : output,
59- passthrough_attrs : Default :: default ( ) ,
69+ passthrough_attrs : Default :: default ( ) , // TODO: ATTR Pass the actual docs, cfgs, etc... here
6070 } )
6171 }
6272
73+ // TODO: ATTR Can this return references instead?
74+ pub fn extract_docs ( & self ) -> Vec < Attribute > {
75+ self . cxx_qt_attrs
76+ . values ( )
77+ . flatten ( )
78+ . filter ( |attr| path_compare_str ( attr. meta . path ( ) , & [ "doc" ] ) )
79+ . map ( |attr| ( * attr) . clone ( ) )
80+ . collect ( )
81+ }
82+
83+ // TODO: ATTR Can this return references instead
84+ pub fn extract_cfgs ( & self ) -> Vec < Attribute > {
85+ self . cxx_qt_attrs
86+ . values ( )
87+ . flatten ( )
88+ . filter ( |attr| path_compare_str ( attr. meta . path ( ) , & [ "cfg" ] ) )
89+ . map ( |attr| ( * attr) . clone ( ) )
90+ . collect ( )
91+ }
92+
93+ /// Returns all the attributes stored within the struct
94+ pub fn all_attrs ( & self ) -> Vec < & Attribute > {
95+ self . cxx_qt_attrs . values ( ) . flatten ( ) . collect ( )
96+ }
97+
98+ /// Returns all the attributes stored within the struct (CLONE) WIP
99+ pub fn clone_attrs ( & self ) -> Vec < Attribute > {
100+ self . cxx_qt_attrs
101+ . values ( )
102+ . flatten ( )
103+ . cloned ( )
104+ . collect :: < Vec < _ > > ( )
105+ }
106+
63107 // Wrapper methods for the internal BTreeMaps
64108 // TODO: Refactor usage to use more specialised methods / rename
65109
66110 /// Search in first the CXX-Qt, and then passthrough attributes by key
67- pub fn get ( & self , key : & str ) -> Option < & Attribute > {
68- self . cxx_qt_attrs
69- . get ( key)
70- . or ( self . passthrough_attrs . get ( key) )
71- . map ( |attr| & * * attr)
111+ pub fn get ( & self , key : & str ) -> Option < & Vec < Attribute > > {
112+ self . cxx_qt_attrs . get ( key) // TODO: Check passthrough here too
72113 }
73114
74115 /// Check if CXX-Qt or passthrough attributes contains a particular key
75116 pub fn contains_key ( & self , key : & str ) -> bool {
76- self . cxx_qt_attrs . contains_key ( key) || self . passthrough_attrs . contains_key ( key )
117+ self . cxx_qt_attrs . contains_key ( key) // TODO: Check in passthrough too
77118 }
78119}
0 commit comments