@@ -57,7 +57,9 @@ use crate::ir::var::Var;
5757
5858use proc_macro2:: { Ident , Span , TokenStream } ;
5959use quote:: { ToTokens , TokenStreamExt } ;
60- use syn:: { parse_quote, Attribute } ;
60+ use syn:: parse:: ParseStream ;
61+ use syn:: token:: Pound ;
62+ use syn:: { parse, parse2, parse_quote, parse_str, Attribute , Block } ;
6163
6264use crate :: { Entry , HashMap , HashSet } ;
6365use std:: borrow:: Cow ;
@@ -500,6 +502,51 @@ trait CodeGenerator {
500502 ) -> Self :: Return ;
501503}
502504
505+ fn normalize_attributes ( attrs : HashSet < String > ) -> HashSet < String > {
506+ attrs
507+ . iter ( )
508+ . map ( |attr| {
509+ let mut in_quotes = None ;
510+ attr. chars ( )
511+ . filter_map ( |c| match c {
512+ '"' | '\'' if in_quotes. is_none ( ) => {
513+ in_quotes = Some ( c) ;
514+ Some ( c)
515+ }
516+ c if in_quotes == Some ( c) => {
517+ in_quotes = None ;
518+ Some ( c)
519+ }
520+ c if in_quotes. is_some ( ) => Some ( c) ,
521+ c if !c. is_whitespace ( ) => Some ( c) ,
522+ _ => None ,
523+ } )
524+ . collect ( )
525+ } )
526+ . collect ( )
527+ }
528+
529+ fn process_attributes (
530+ result : & mut CodegenResult ,
531+ item : & Item ,
532+ ctx : & BindgenContext ,
533+ attrs : HashSet < String > ,
534+ kind : AttributeItemKind ,
535+ ) -> Vec < TokenStream > {
536+ let mut attrs = normalize_attributes ( attrs) ;
537+ ctx. options ( ) . for_each_callback_mut ( |cb| {
538+ cb. process_attributes (
539+ & AttributeInfo {
540+ name : & item. canonical_name ( ctx) ,
541+ kind,
542+ } ,
543+ & mut attrs,
544+ ) ;
545+ } ) ;
546+ result. set_attributes ( item. id ( ) , attrs. clone ( ) ) ;
547+ parse_tokens ( normalize_attributes ( attrs) )
548+ }
549+
503550impl Item {
504551 fn process_before_codegen (
505552 & self ,
@@ -703,17 +750,24 @@ impl CodeGenerator for Var {
703750 let ty = var_ty. to_rust_ty_or_opaque ( ctx, & ( ) ) ;
704751
705752 if let Some ( val) = self . val ( ) {
706- ctx. options ( ) . for_each_callback_mut ( |cb| {
707- cb. process_attributes (
708- & AttributeInfo {
709- name : & canonical_name,
710- kind : AttributeItemKind :: Var ,
711- } ,
712- & mut attrs,
713- ) ;
714- } ) ;
715- result. set_attributes ( item. id ( ) , attrs. clone ( ) ) ;
716- let attrs = parse_tokens ( attrs) ;
753+ /*if let Item::Fn(func) = item {
754+ for attr in func.attrs {
755+ // Process the attribute and extract key-value pairs
756+ if let Ok(Meta::NameValue(meta)) = attr.parse_meta() {
757+ // Check if the value of the attribute is a string literal
758+ if let Lit::Str(value) = meta.lit {
759+ attrs.insert(meta.path.get_ident().unwrap().to_string(), value.value());
760+ }
761+ }
762+ }
763+ }*/
764+ let attrs = process_attributes (
765+ result,
766+ item,
767+ ctx,
768+ attrs,
769+ AttributeItemKind :: Var ,
770+ ) ;
717771
718772 match * val {
719773 VarType :: Bool ( val) => {
@@ -829,17 +883,13 @@ impl CodeGenerator for Var {
829883 }
830884 }
831885
832- ctx. options ( ) . for_each_callback_mut ( |cb| {
833- cb. process_attributes (
834- & AttributeInfo {
835- name : & canonical_name,
836- kind : AttributeItemKind :: Var ,
837- } ,
838- & mut attrs,
839- ) ;
840- } ) ;
841- result. set_attributes ( item. id ( ) , attrs. clone ( ) ) ;
842- let attrs = parse_tokens ( attrs) ;
886+ let attrs = process_attributes (
887+ result,
888+ item,
889+ ctx,
890+ attrs,
891+ AttributeItemKind :: Var ,
892+ ) ;
843893
844894 let maybe_mut = if self . is_const ( ) {
845895 quote ! { }
@@ -1068,15 +1118,17 @@ impl CodeGenerator for Type {
10681118 // Only apply attributes through type aliases when they are relevant to compilation
10691119 attrs. extend (
10701120 parse_tokens ( inner_attrs)
1071- . into_iter ( )
1072- . map ( |attr| parse_quote ! { #attr } )
1073- . filter_map ( |attr : Attribute |{
1074- if attr. path ( ) . is_ident ( "cfg" ) || attr. path ( ) . is_ident ( "link" ) {
1075- Some ( attr. to_token_stream ( ) . to_string ( ) )
1076- } else {
1077- None
1078- }
1079- } )
1121+ . into_iter ( )
1122+ . map ( |attr| parse_quote ! { #attr } )
1123+ . filter_map ( |attr : Attribute | {
1124+ if attr. path ( ) . is_ident ( "cfg" ) ||
1125+ attr. path ( ) . is_ident ( "link" )
1126+ {
1127+ Some ( attr. to_token_stream ( ) . to_string ( ) )
1128+ } else {
1129+ None
1130+ }
1131+ } ) ,
10801132 ) ;
10811133 }
10821134
@@ -1088,28 +1140,18 @@ impl CodeGenerator for Type {
10881140 attrs. insert ( attributes:: doc ( comment) . to_string ( ) ) ;
10891141 }
10901142
1091- // Allow the callbacks to process our attributes
1092- ctx. options ( ) . for_each_callback_mut ( |cb| {
1093- cb. process_attributes (
1094- & AttributeInfo {
1095- name : & name,
1096- // FIXME: Introduce a TypeAlias variant with extra information similar
1097- // to DiscoveredItem::Alias, indicating this is merely an alias
1098- // and not a new type definition.
1099- kind : AttributeItemKind :: Struct ,
1100- } ,
1101- & mut attrs,
1102- ) ;
1103- } ) ;
1104-
1105- // Store the final attributes of this item
1106- result. set_attributes ( item. id ( ) , attrs. clone ( ) ) ;
1143+ let attrs = process_attributes (
1144+ result,
1145+ item,
1146+ ctx,
1147+ attrs,
1148+ AttributeItemKind :: Struct ,
1149+ ) ;
11071150
1108- let attrs = parse_tokens ( attrs) ;
11091151 let mut tokens = quote ! {
11101152 #( #attrs ) *
11111153 } ;
1112-
1154+
11131155 // We prefer using `pub use` over `pub type` because of:
11141156 // https://github.com/rust-lang/rust/issues/26264
11151157 if matches ! ( inner_rust_type, syn:: Type :: Path ( _) ) &&
@@ -2608,21 +2650,18 @@ impl CodeGenerator for CompInfo {
26082650 }
26092651
26102652 attrs. extend ( item. annotations ( ) . attributes ( ) . iter ( ) . cloned ( ) ) ;
2611- ctx. options ( ) . for_each_callback_mut ( |cb| {
2612- cb. process_attributes (
2613- & AttributeInfo {
2614- name : & canonical_name,
2615- kind : if is_rust_union {
2616- AttributeItemKind :: Union
2617- } else {
2618- AttributeItemKind :: Struct
2619- } ,
2620- } ,
2621- & mut attrs,
2622- ) ;
2623- } ) ;
2624- result. set_attributes ( item. id ( ) , attrs. clone ( ) ) ;
2625- let attrs = parse_tokens ( attrs) ;
2653+
2654+ let attrs = process_attributes (
2655+ result,
2656+ item,
2657+ ctx,
2658+ attrs,
2659+ if is_rust_union {
2660+ AttributeItemKind :: Union
2661+ } else {
2662+ AttributeItemKind :: Struct
2663+ } ,
2664+ ) ;
26262665
26272666 let mut tokens = if is_rust_union {
26282667 quote ! {
@@ -3234,19 +3273,13 @@ impl Method {
32343273 attrs. insert ( attributes:: must_use ( ) . to_string ( ) ) ;
32353274 }
32363275
3237- ctx. options ( ) . for_each_callback_mut ( |cb| {
3238- cb. process_attributes (
3239- & AttributeInfo {
3240- name : & canonical_name,
3241- kind : AttributeItemKind :: Function ( FunctionKind :: Method (
3242- self . kind ( ) ,
3243- ) ) ,
3244- } ,
3245- & mut attrs,
3246- ) ;
3247- } ) ;
3248- result. set_attributes ( function_item. id ( ) , attrs. clone ( ) ) ;
3249- let attrs = parse_tokens ( attrs) ;
3276+ let attrs = process_attributes (
3277+ result,
3278+ function_item,
3279+ ctx,
3280+ attrs,
3281+ AttributeItemKind :: Function ( FunctionKind :: Method ( self . kind ( ) ) ) ,
3282+ ) ;
32503283
32513284 let name = ctx. rust_ident ( & name) ;
32523285 methods. push ( quote ! {
@@ -3859,20 +3892,21 @@ impl CodeGenerator for Enum {
38593892 // add them to the end of the list.
38603893 attrs. extend ( item. annotations ( ) . attributes ( ) . iter ( ) . cloned ( ) ) ;
38613894
3862- ctx. options ( ) . for_each_callback_mut ( |cb| {
3863- cb. process_attributes (
3864- & AttributeInfo {
3865- name : & name,
3866- kind : AttributeItemKind :: Enum ,
3867- } ,
3868- & mut attrs,
3869- ) ;
3870- } ) ;
3871- result. set_attributes ( item. id ( ) , attrs. clone ( ) ) ;
3895+ let attrs = process_attributes (
3896+ result,
3897+ item,
3898+ ctx,
3899+ attrs,
3900+ AttributeItemKind :: Enum ,
3901+ ) ;
38723902
3873- let attrs = parse_tokens ( attrs) ;
3874- let mut builder =
3875- EnumBuilder :: new ( & name, attrs. clone ( ) , repr, variation, has_typedef) ;
3903+ let mut builder = EnumBuilder :: new (
3904+ & name,
3905+ attrs. clone ( ) ,
3906+ repr,
3907+ variation,
3908+ has_typedef,
3909+ ) ;
38763910
38773911 // A map where we keep a value -> variant relation.
38783912 let mut seen_values = HashMap :: < _ , Ident > :: default ( ) ;
@@ -4820,18 +4854,14 @@ impl CodeGenerator for Function {
48204854 . unsafe_extern_blocks
48214855 . then ( || quote ! ( unsafe ) ) ;
48224856
4823- ctx. options ( ) . for_each_callback_mut ( |cb| {
4824- cb. process_attributes (
4825- & AttributeInfo {
4826- name : & name,
4827- kind : AttributeItemKind :: Function ( self . kind ( ) ) ,
4828- } ,
4829- & mut attrs,
4830- ) ;
4831- } ) ;
4832- result. set_attributes ( item. id ( ) , attrs. clone ( ) ) ;
4857+ let attrs = process_attributes (
4858+ result,
4859+ item,
4860+ ctx,
4861+ attrs,
4862+ AttributeItemKind :: Function ( FunctionKind :: Function ) ,
4863+ ) ;
48334864
4834- let attrs = parse_tokens ( attrs) ;
48354865 let tokens = quote ! {
48364866 #wasm_link_attribute
48374867 #safety extern #abi {
0 commit comments