diff --git a/module/core/derive_tools_meta/src/derive/from.rs b/module/core/derive_tools_meta/src/derive/from.rs index 3751abf778..26bee4d9f1 100644 --- a/module/core/derive_tools_meta/src/derive/from.rs +++ b/module/core/derive_tools_meta/src/derive/from.rs @@ -10,13 +10,6 @@ pub fn from( input : proc_macro::TokenStream ) -> Result< proc_macro2::TokenStre use macro_tools::quote::ToTokens; let original_input = input.clone(); - - // let parsed = syn::parse::< syn::ItemStruct >( input )?; - // let has_debug = attr::has_debug( parsed.attrs.iter() )?; - // let item_name = &parsed.ident; - // let mut field_types = item_struct::field_types( &parsed ); - // let field_names = item_struct::field_names( &parsed ); - let parsed = syn::parse::< StructLike >( input )?; let has_debug = attr::has_debug( parsed.attrs().iter() )?; let item_name = &parsed.ident(); @@ -226,7 +219,8 @@ fn generate_from_single_field generics_ty : &syn::punctuated::Punctuated< syn::GenericParam, syn::token::Comma >, generics_where: &syn::punctuated::Punctuated< syn::WherePredicate, syn::token::Comma >, field_type : &syn::Type, -) -> proc_macro2::TokenStream +) +-> proc_macro2::TokenStream { qt! @@ -257,7 +251,8 @@ fn generate_from_multiple_fields_named< 'a > generics_where: &syn::punctuated::Punctuated< syn::WherePredicate, syn::token::Comma >, field_names : Box< dyn macro_tools::IterTrait< 'a, &'a syn::Ident > + '_ >, field_types : impl macro_tools::IterTrait< 'a, &'a syn::Type >, -) -> proc_macro2::TokenStream +) +-> proc_macro2::TokenStream { let params : Vec< proc_macro2::TokenStream > = field_names @@ -337,7 +332,8 @@ fn generate_unit generics_impl : &syn::punctuated::Punctuated< syn::GenericParam, syn::token::Comma >, generics_ty : &syn::punctuated::Punctuated< syn::GenericParam, syn::token::Comma >, generics_where: &syn::punctuated::Punctuated< syn::WherePredicate, syn::token::Comma >, -) -> proc_macro2::TokenStream +) +-> proc_macro2::TokenStream { qt! { diff --git a/module/core/derive_tools_meta/src/lib.rs b/module/core/derive_tools_meta/src/lib.rs index ef1aca328a..b2b6f19f6b 100644 --- a/module/core/derive_tools_meta/src/lib.rs +++ b/module/core/derive_tools_meta/src/lib.rs @@ -72,7 +72,15 @@ mod derive; #[ cfg( feature = "enabled" ) ] #[ cfg( feature = "derive_from" ) ] -#[ proc_macro_derive( From, attributes( debug ) ) ] +#[ proc_macro_derive +( + From, + attributes + ( + debug, // struct + from, // field + ) +)] pub fn from( input : proc_macro::TokenStream ) -> proc_macro::TokenStream { let result = derive::from::from( input ); diff --git a/module/core/former/tests/tests.rs b/module/core/former/tests/tests.rs index fd01ed1ac9..fe0db783b8 100644 --- a/module/core/former/tests/tests.rs +++ b/module/core/former/tests/tests.rs @@ -6,5 +6,5 @@ use test_tools::exposed::*; #[ allow( unused_imports ) ] use former as the_module; -#[ cfg( enabled ) ] +#[ cfg( feature = "enabled" ) ] mod inc; diff --git a/module/core/former_meta/src/derive_former/field_attrs.rs b/module/core/former_meta/src/derive_former/field_attrs.rs index 137f84249e..77a2ae0c9a 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -17,7 +17,6 @@ pub struct FieldAttributes impl FieldAttributes { - // fn from_attrs( attributes : & Vec< syn::Attribute > ) -> Result< Self > pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { let mut config = None; diff --git a/module/core/former_meta/src/derive_former/struct_attrs.rs b/module/core/former_meta/src/derive_former/struct_attrs.rs index e8656eb982..ac71d13bd8 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -2,19 +2,14 @@ use super::*; use macro_tools::{ attr, Result }; -/// -/// Definition of a field. -/// - /// /// Attributes of a struct. /// - pub struct StructAttributes { - pub perform : Option< AttributePerform >, pub storage_fields : Option< AttributeStorageFields >, pub mutator : AttributeMutator, + pub perform : Option< AttributePerform >, } impl StructAttributes @@ -22,9 +17,9 @@ impl StructAttributes pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { - let mut perform = None; let mut storage_fields = None; - let mut mutator = Default::default(); + let mut mutator : AttributeMutator = Default::default(); + let mut perform = None; for attr in attrs { @@ -37,45 +32,20 @@ impl StructAttributes continue; } + // qqq : qqq for Anton : xxx : refactor field_attrs::FieldAttributes::from_attrs to make it similar to this function match key_str.as_ref() { - "storage_fields" => + AttributeStorageFields::KEYWORD => { - match attr.meta - { - syn::Meta::List( ref meta_list ) => - { - storage_fields.replace( syn::parse2::< AttributeStorageFields >( meta_list.tokens.clone() )? ); - }, - _ => return_syn_err!( attr, "Expects an attribute of format #[ storage_fields( a : i32, b : Option< String > ) ] -.\nGot: {}", qt!{ #attr } ), - } + storage_fields.replace( AttributeStorageFields::from_meta( attr )? ); } - "perform" => + AttributeMutator::KEYWORD => { - match attr.meta - { - syn::Meta::List( ref meta_list ) => - { - perform.replace( syn::parse2::< AttributePerform >( meta_list.tokens.clone() )? ); - }, - _ => return_syn_err!( attr, "Expects an attribute of format #[ perform( fn parse( mut self ) -> Request ) ] -.\nGot: {}", qt!{ #attr } ), - } + mutator = AttributeMutator::from_meta( attr )?; } - "mutator" => + AttributePerform::KEYWORD => { - match attr.meta - { - syn::Meta::List( ref meta_list ) => - { - mutator = syn::parse2::< AttributeMutator >( meta_list.tokens.clone() )? - }, - syn::Meta::Path( ref _path ) => - { - }, - _ => return_syn_err!( attr, "Expects an attribute of format `#[ mutator( custom = true, hint = true ) ]`. \nGot: {}", qt!{ #attr } ), - } + perform.replace( AttributePerform::from_meta( attr )? ); } "debug" => { @@ -90,7 +60,6 @@ impl StructAttributes Ok( StructAttributes { perform, storage_fields, mutator } ) } - /// /// Generate parts, used for generating `perform()`` method. /// @@ -172,40 +141,35 @@ impl StructAttributes } /// -/// Attribute to hold information about method to call after form. +/// Attribute to hold storage-specific fields. +/// Useful if formed structure should not have such fields. /// -/// `#[ perform( fn after1< 'a >() -> Option< &'a str > ) ]` +/// `#[ storage_fields( a : i32, b : Option< String > ) ]` /// -pub struct AttributePerform +pub struct AttributeStorageFields { - pub signature : syn::Signature, + pub fields : syn::punctuated::Punctuated< syn::Field, syn::token::Comma >, } -impl syn::parse::Parse for AttributePerform +impl AttributeStorageFields { - fn parse( input : syn::parse::ParseStream< '_ > ) -> Result< Self > + + const KEYWORD : &'static str = "storage_fields"; + + pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > { - // let input2; - Ok( Self + match attr.meta { - // paren_token : syn::parenthesized!( input2 in input ), - // signature : input2.parse()?, - signature : input.parse()?, - }) + syn::Meta::List( ref meta_list ) => + { + return syn::parse2::< AttributeStorageFields >( meta_list.tokens.clone() ); + }, + _ => return_syn_err!( attr, "Expects an attribute of format #[ storage_fields( a : i32, b : Option< String > ) ] +.\nGot: {}", qt!{ #attr } ), + } } -} -/// -/// Attribute to hold storage-specific fields. -/// Useful if formed structure should not have such fields. -/// -/// `#[ storage_fields( a : i32, b : Option< String > ) ]` -/// - -pub struct AttributeStorageFields -{ - pub fields : syn::punctuated::Punctuated< syn::Field, syn::token::Comma >, } impl syn::parse::Parse for AttributeStorageFields @@ -219,11 +183,6 @@ impl syn::parse::Parse for AttributeStorageFields Ok( Self { fields, - // fields : syn::Fields::Named( syn::FieldsNamed - // { - // brace_token : Default::default(), - // named : fields, - // }), }) } } @@ -250,6 +209,29 @@ pub struct AttributeMutator pub hint : bool, } +impl AttributeMutator +{ + const KEYWORD : &'static str = "mutator"; + + pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + { + match attr.meta + { + syn::Meta::List( ref meta_list ) => + { + return syn::parse2::< AttributeMutator >( meta_list.tokens.clone() ); + }, + syn::Meta::Path( ref _path ) => + { + return Ok( Default::default() ) + }, + _ => return_syn_err!( attr, "Expects an attribute of format `#[ mutator( custom = true, hint = true ) ]`. \nGot: {}", qt!{ #attr } ), + } + } + +} + + impl syn::parse::Parse for AttributeMutator { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -298,3 +280,48 @@ impl syn::parse::Parse for AttributeMutator }) } } + +/// +/// Attribute to hold information about method to call after form. +/// +/// `#[ perform( fn after1< 'a >() -> Option< &'a str > ) ]` +/// + +pub struct AttributePerform +{ + pub signature : syn::Signature, +} + +impl AttributePerform +{ + const KEYWORD : &'static str = "perform"; + + pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + { + + match attr.meta + { + syn::Meta::List( ref meta_list ) => + { + return syn::parse2::< AttributePerform >( meta_list.tokens.clone() ); + }, + _ => return_syn_err!( attr, "Expects an attribute of format #[ perform( fn parse( mut self ) -> Request ) ] +.\nGot: {}", qt!{ #attr } ), + } + } + +} + +impl syn::parse::Parse for AttributePerform +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> Result< Self > + { + // let input2; + Ok( Self + { + // paren_token : syn::parenthesized!( input2 in input ), + // signature : input2.parse()?, + signature : input.parse()?, + }) + } +} diff --git a/module/core/macro_tools/src/generic_params.rs b/module/core/macro_tools/src/generic_params.rs index 22455cb089..5af6bdc366 100644 --- a/module/core/macro_tools/src/generic_params.rs +++ b/module/core/macro_tools/src/generic_params.rs @@ -302,6 +302,13 @@ pub( crate ) mod private /// This helps in situations where you need different representations of generics for implementing traits, /// defining types, or specifying trait bounds and conditions. /// + /// This function is similar to `syn::Generics::split_for_impl`, which also splits generics into components + /// suitable for `impl` blocks and type definitions. However, `split_for_impl` wraps the tokens in `<>`, which + /// can reduce the flexibility of the results. The `decompose` function provides more control over the output + /// by not wrapping the tokens, allowing for more precise usage in macros and other contexts. + /// Additionally, `decompose` returns an extra component with the generics including defaults, which is often + /// in demand for certain macro or code generation tasks. + /// /// # Examples /// /// ```rust @@ -332,7 +339,15 @@ pub( crate ) mod private /// - `syn::punctuated::Punctuated`: Simplified generics for type definitions, only identifiers. /// - `syn::punctuated::Punctuated`: Where clauses, properly punctuated for use in where conditions. /// - /// # Example of signature of function which reuse `generic_params::decompose` + /// # Differences from `syn::Generics::split_for_impl` + /// + /// While both `decompose` and `split_for_impl` functions split generics into components for `impl` blocks, type definitions, and where clauses, + /// there are key differences: + /// - `split_for_impl` wraps the generics in `<>`, which can be limiting when you need to use the generics in a different context or format. + /// - `decompose` provides raw punctuated generic parameters, offering greater flexibility and control over the output format. + /// - `decompose` returns an extra component with the generics including defaults, which is often needed for certain macro or code generation tasks. + /// + /// # Example of function signature using `decompose` /// /// ```rust /// use macro_tools::{ syn, proc_macro2, qt };