Skip to content

Commit

Permalink
Merge pull request #1347 from Wandalen/program_tools_v1
Browse files Browse the repository at this point in the history
AUTO : Forward from program_tools_v1 to alpha
  • Loading branch information
Wandalen authored May 19, 2024
2 parents b3a67f0 + 1f4dfee commit adb6ff7
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 83 deletions.
16 changes: 6 additions & 10 deletions module/core/derive_tools_meta/src/derive/from.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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!
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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!
{
Expand Down
10 changes: 9 additions & 1 deletion module/core/derive_tools_meta/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
Expand Down
2 changes: 1 addition & 1 deletion module/core/former/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ use test_tools::exposed::*;
#[ allow( unused_imports ) ]
use former as the_module;

#[ cfg( enabled ) ]
#[ cfg( feature = "enabled" ) ]
mod inc;
1 change: 0 additions & 1 deletion module/core/former_meta/src/derive_former/field_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
165 changes: 96 additions & 69 deletions module/core/former_meta/src/derive_former/struct_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,24 @@
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
{

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
{
Expand All @@ -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" =>
{
Expand All @@ -90,7 +60,6 @@ impl StructAttributes
Ok( StructAttributes { perform, storage_fields, mutator } )
}


///
/// Generate parts, used for generating `perform()`` method.
///
Expand Down Expand Up @@ -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
Expand All @@ -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,
// }),
})
}
}
Expand All @@ -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 >
Expand Down Expand Up @@ -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()?,
})
}
}
17 changes: 16 additions & 1 deletion module/core/macro_tools/src/generic_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -332,7 +339,15 @@ pub( crate ) mod private
/// - `syn::punctuated::Punctuated<syn::GenericParam, syn::token::Comma>`: Simplified generics for type definitions, only identifiers.
/// - `syn::punctuated::Punctuated<syn::WherePredicate, syn::token::Comma>`: 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 };
Expand Down

0 comments on commit adb6ff7

Please sign in to comment.