From 176b481fd45f8b8b0a468a97cbb6d71b45e7a6a7 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 08:22:58 +0300 Subject: [PATCH 01/44] former : renames --- .../core/former_meta/src/derive_former/field_attrs.rs | 10 +++++----- .../core/former_meta/src/derive_former/struct_attrs.rs | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) 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 b6104b3551..0948bc601a 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -24,6 +24,7 @@ impl FieldAttributes let mut subform_scalar = None; let mut subform_collection = None; let mut subform_entry = None; + for attr in attrs { let key_ident = attr.path().get_ident() @@ -43,7 +44,6 @@ impl FieldAttributes } AttributeScalarSetter::KEYWORD => { - // qqq : move this part of parsing into attribute. do that for all attributes -- done scalar.replace( AttributeScalarSetter::from_meta( &attr )? ); } AttributeSubformScalarSetter::KEYWORD => @@ -86,7 +86,7 @@ pub struct AttributeConfig impl AttributeConfig { - const KEYWORD: &'static str = "former"; + const KEYWORD : &'static str = "former"; pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > { @@ -284,7 +284,7 @@ pub struct AttributeSubformScalarSetter impl AttributeSubformScalarSetter { - const KEYWORD: &'static str = "subform_scalar"; + const KEYWORD : &'static str = "subform_scalar"; pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > { @@ -394,7 +394,7 @@ pub struct AttributeSubformCollectionSetter impl AttributeSubformCollectionSetter { - const KEYWORD: &'static str = "subform_collection"; + const KEYWORD : &'static str = "subform_collection"; pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > { @@ -515,7 +515,7 @@ pub struct AttributeSubformEntrySetter impl AttributeSubformEntrySetter { - const KEYWORD: &'static str = "subform_entry"; + const KEYWORD : &'static str = "subform_entry"; pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > { 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 f40dd61d61..16de2b5a5d 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -32,7 +32,6 @@ impl StructAttributes continue; } - // qqq : qqq for Anton : xxx : refactor field_attrs::FieldAttributes::from_attrs to make it similar to this function -- done match key_str.as_ref() { AttributeStorageFields::KEYWORD => @@ -52,7 +51,7 @@ impl StructAttributes } _ => { - return Err( syn_err!( attr, "Known structure attirbutes are : `storage_fields`, `perform`, `debug`.\nUnknown structure attribute : {}", qt!{ #attr } ) ); + return Err( syn_err!( attr, "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`.\nUnknown structure attribute : {}", qt!{ #attr } ) ); } } } From e317bda5abcaf2bd7bbf9a833daf06dbcec81836 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 12:55:24 +0300 Subject: [PATCH 02/44] former_types: split out types from crate former to been able use them without importing derives --- Cargo.toml | 5 + module/core/former/Cargo.toml | 25 +++-- module/core/former/src/lib.rs | 98 +++++++++-------- .../inc/components_tests/component_assign.rs | 2 +- .../component_assign_manual.rs | 2 +- .../inc/components_tests/component_from.rs | 2 +- .../components_tests/component_from_manual.rs | 2 +- .../inc/components_tests/components_assign.rs | 2 +- .../components_assign_manual.rs | 2 +- .../tests/inc/components_tests/composite.rs | 2 +- .../inc/components_tests/composite_manual.rs | 2 +- .../inc/components_tests/from_components.rs | 2 +- .../from_components_manual.rs | 2 +- ...omponent_assign.rs => component_assign.rs} | 0 ...ts_component_from.rs => component_from.rs} | 0 ...ponents_assign.rs => components_assign.rs} | 2 +- .../{components_composite.rs => composite.rs} | 0 ..._from_components.rs => from_components.rs} | 0 .../src/derive_former/field_attrs.rs | 2 + .../src/derive_former/struct_attrs.rs | 2 + module/core/former_types/Cargo.toml | 64 +++++++++++ module/core/former_types/License | 23 ++++ module/core/former_types/Readme.md | 70 ++++++++++++ .../examples/former_types_trivial.rs | 68 ++++++++++++ .../{former => former_types}/src/axiomatic.rs | 0 .../src/collection.rs | 8 +- .../src/collection/binary_heap.rs | 0 .../src/collection/btree_map.rs | 0 .../src/collection/btree_set.rs | 0 .../src/collection/hash_map.rs | 0 .../src/collection/hash_set.rs | 0 .../src/collection/linked_list.rs | 0 .../src/collection/vector.rs | 0 .../src/collection/vector_deque.rs | 0 .../{former => former_types}/src/component.rs | 4 +- .../src/definition.rs | 0 .../{former => former_types}/src/forming.rs | 0 module/core/former_types/src/lib.rs | 101 ++++++++++++++++++ .../{former => former_types}/src/storage.rs | 0 module/core/former_types/tests/inc/mod.rs | 51 +++++++++ module/core/former_types/tests/smoke_test.rs | 14 +++ module/core/former_types/tests/tests.rs | 12 +++ 42 files changed, 497 insertions(+), 72 deletions(-) rename module/core/former/tests/inc/components_tests/only_test/{components_component_assign.rs => component_assign.rs} (100%) rename module/core/former/tests/inc/components_tests/only_test/{components_component_from.rs => component_from.rs} (100%) rename module/core/former/tests/inc/components_tests/only_test/{components_components_assign.rs => components_assign.rs} (96%) rename module/core/former/tests/inc/components_tests/only_test/{components_composite.rs => composite.rs} (100%) rename module/core/former/tests/inc/components_tests/only_test/{components_from_components.rs => from_components.rs} (100%) create mode 100644 module/core/former_types/Cargo.toml create mode 100644 module/core/former_types/License create mode 100644 module/core/former_types/Readme.md create mode 100644 module/core/former_types/examples/former_types_trivial.rs rename module/core/{former => former_types}/src/axiomatic.rs (100%) rename module/core/{former => former_types}/src/collection.rs (96%) rename module/core/{former => former_types}/src/collection/binary_heap.rs (100%) rename module/core/{former => former_types}/src/collection/btree_map.rs (100%) rename module/core/{former => former_types}/src/collection/btree_set.rs (100%) rename module/core/{former => former_types}/src/collection/hash_map.rs (100%) rename module/core/{former => former_types}/src/collection/hash_set.rs (100%) rename module/core/{former => former_types}/src/collection/linked_list.rs (100%) rename module/core/{former => former_types}/src/collection/vector.rs (100%) rename module/core/{former => former_types}/src/collection/vector_deque.rs (100%) rename module/core/{former => former_types}/src/component.rs (93%) rename module/core/{former => former_types}/src/definition.rs (100%) rename module/core/{former => former_types}/src/forming.rs (100%) create mode 100644 module/core/former_types/src/lib.rs rename module/core/{former => former_types}/src/storage.rs (100%) create mode 100644 module/core/former_types/tests/inc/mod.rs create mode 100644 module/core/former_types/tests/smoke_test.rs create mode 100644 module/core/former_types/tests/tests.rs diff --git a/Cargo.toml b/Cargo.toml index 2f07b12e04..3084f01f68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -214,6 +214,11 @@ version = "~2.0.0" path = "module/core/former_meta" default-features = false +[workspace.dependencies.former_types] +version = "~2.0.0" +path = "module/core/former_types" +default-features = false + [workspace.dependencies.impls_index] version = "~0.7.0" path = "module/core/impls_index" diff --git a/module/core/former/Cargo.toml b/module/core/former/Cargo.toml index 53808e51af..17aa035a97 100644 --- a/module/core/former/Cargo.toml +++ b/module/core/former/Cargo.toml @@ -26,8 +26,11 @@ all-features = false [features] -no_std = [ "collection_tools/no_std" ] -use_alloc = [ "no_std", "collection_tools/use_alloc" ] +no_std = [ "former_types/no_std", "collection_tools/no_std" ] +use_alloc = [ "no_std", "former_types/use_alloc", "collection_tools/use_alloc" ] + +# no_std = [ "collection_tools/no_std" ] +# use_alloc = [ "no_std", "collection_tools/use_alloc" ] default = [ "enabled", @@ -47,20 +50,22 @@ full = [ "derive_components_assign", "derive_from_components", ] -enabled = [ "former_meta/enabled", "collection_tools/enabled" ] +enabled = [ "former_meta/enabled", "former_types/enabled" ] -derive_former = [ "former_meta/derive_former" ] -derive_components = [ "former_meta/derive_components" ] -derive_component_assign = [ "derive_components", "former_meta/derive_component_assign" ] -derive_components_assign = [ "derive_components", "derive_component_assign", "former_meta/derive_components_assign" ] -derive_component_from = [ "derive_components", "former_meta/derive_component_from" ] -derive_from_components = [ "derive_components", "former_meta/derive_from_components" ] +derive_former = [ "former_meta/derive_former", "former_types/derive_former" ] +derive_components = [ "former_meta/derive_components", "former_types/derive_components" ] +derive_component_assign = [ "derive_components", "former_meta/derive_component_assign", "former_types/derive_component_assign" ] +derive_components_assign = [ "derive_components", "derive_component_assign", "former_meta/derive_components_assign", "former_types/derive_components_assign" ] +derive_component_from = [ "derive_components", "former_meta/derive_component_from", "former_types/derive_component_from" ] +derive_from_components = [ "derive_components", "former_meta/derive_from_components", "former_types/derive_from_components" ] [dependencies] former_meta = { workspace = true } -collection_tools = { workspace = true, features = [ "collection_constructors" ] } +former_types = { workspace = true } +# collection_tools = { workspace = true, features = [ "collection_constructors" ] } [dev-dependencies] test_tools = { workspace = true, features = [ "full" ] } +collection_tools = { workspace = true, features = [ "collection_constructors" ] } \ No newline at end of file diff --git a/module/core/former/src/lib.rs b/module/core/former/src/lib.rs index 85b73f8e13..2eb4e674d2 100644 --- a/module/core/former/src/lib.rs +++ b/module/core/former/src/lib.rs @@ -4,38 +4,39 @@ #![ doc( html_root_url = "https://docs.rs/former/latest/former/" ) ] #![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "Readme.md" ) ) ] -/// Axiomatic things. -#[ cfg( feature = "enabled" ) ] -#[ cfg( feature = "derive_former" ) ] -mod axiomatic; -/// Forming process. -#[ cfg( feature = "enabled" ) ] -#[ cfg( feature = "derive_former" ) ] -mod definition; -/// Forming process. -#[ cfg( feature = "enabled" ) ] -#[ cfg( feature = "derive_former" ) ] -mod forming; -/// Storage. -#[ cfg( feature = "enabled" ) ] -#[ cfg( feature = "derive_former" ) ] -mod storage; - -/// Interface for collections. -#[ cfg( feature = "enabled" ) ] -#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] -#[ cfg( feature = "derive_former" ) ] -mod collection; - -/// Component-based forming. -#[ cfg( feature = "enabled" ) ] -#[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] -mod component; +// /// Axiomatic things. +// #[ cfg( feature = "enabled" ) ] +// #[ cfg( feature = "derive_former" ) ] +// mod axiomatic; +// /// Forming process. +// #[ cfg( feature = "enabled" ) ] +// #[ cfg( feature = "derive_former" ) ] +// mod definition; +// /// Forming process. +// #[ cfg( feature = "enabled" ) ] +// #[ cfg( feature = "derive_former" ) ] +// mod forming; +// /// Storage. +// #[ cfg( feature = "enabled" ) ] +// #[ cfg( feature = "derive_former" ) ] +// mod storage; +// +// /// Interface for collections. +// #[ cfg( feature = "enabled" ) ] +// #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] +// #[ cfg( feature = "derive_former" ) ] +// mod collection; +// +// /// Component-based forming. +// #[ cfg( feature = "enabled" ) ] +// #[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] +// mod component; /// Namespace with dependencies. #[ cfg( feature = "enabled" ) ] pub mod dependency { + pub use former_types; pub use former_meta; } @@ -80,22 +81,24 @@ pub mod exposed #[ doc( inline ) ] #[ allow( unused_imports ) ] - #[ cfg( feature = "enabled" ) ] - #[ cfg( feature = "derive_former" ) ] - pub use super:: - { - axiomatic::*, - definition::*, - forming::*, - storage::*, - }; + pub use former_types::exposed::*; - #[ doc( inline ) ] - #[ allow( unused_imports ) ] - #[ cfg( feature = "enabled" ) ] - #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] - #[ cfg( feature = "derive_former" ) ] - pub use super::collection::*; +// #[ doc( inline ) ] +// #[ allow( unused_imports ) ] +// #[ cfg( feature = "derive_former" ) ] +// pub use super:: +// { +// axiomatic::*, +// definition::*, +// forming::*, +// storage::*, +// }; +// +// #[ doc( inline ) ] +// #[ allow( unused_imports ) ] +// #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] +// #[ cfg( feature = "derive_former" ) ] +// pub use super::collection::*; } @@ -103,9 +106,14 @@ pub mod exposed #[ cfg( feature = "enabled" ) ] pub mod prelude { + + // #[ doc( inline ) ] + // #[ allow( unused_imports ) ] + // #[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] + // pub use super::component::*; + #[ doc( inline ) ] #[ allow( unused_imports ) ] - #[ cfg( feature = "enabled" ) ] - #[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] - pub use super::component::*; + pub use former_types::prelude::*; + } diff --git a/module/core/former/tests/inc/components_tests/component_assign.rs b/module/core/former/tests/inc/components_tests/component_assign.rs index 9ca13cbcba..b2b1fdde8b 100644 --- a/module/core/former/tests/inc/components_tests/component_assign.rs +++ b/module/core/former/tests/inc/components_tests/component_assign.rs @@ -14,4 +14,4 @@ struct Person // -include!( "./only_test/components_component_assign.rs" ); +include!( "./only_test/component_assign.rs" ); diff --git a/module/core/former/tests/inc/components_tests/component_assign_manual.rs b/module/core/former/tests/inc/components_tests/component_assign_manual.rs index d2aff86d2c..d858c5f989 100644 --- a/module/core/former/tests/inc/components_tests/component_assign_manual.rs +++ b/module/core/former/tests/inc/components_tests/component_assign_manual.rs @@ -33,4 +33,4 @@ where // -include!( "./only_test/components_component_assign.rs" ); +include!( "./only_test/component_assign.rs" ); diff --git a/module/core/former/tests/inc/components_tests/component_from.rs b/module/core/former/tests/inc/components_tests/component_from.rs index 965218114f..2151d3d3d7 100644 --- a/module/core/former/tests/inc/components_tests/component_from.rs +++ b/module/core/former/tests/inc/components_tests/component_from.rs @@ -17,4 +17,4 @@ pub struct Options1 // -include!( "./only_test/components_component_from.rs" ); +include!( "./only_test/component_from.rs" ); diff --git a/module/core/former/tests/inc/components_tests/component_from_manual.rs b/module/core/former/tests/inc/components_tests/component_from_manual.rs index 215a1f6ff5..94e854b381 100644 --- a/module/core/former/tests/inc/components_tests/component_from_manual.rs +++ b/module/core/former/tests/inc/components_tests/component_from_manual.rs @@ -42,4 +42,4 @@ impl From< &Options1 > for f32 // -include!( "./only_test/components_component_from.rs" ); +include!( "./only_test/component_from.rs" ); diff --git a/module/core/former/tests/inc/components_tests/components_assign.rs b/module/core/former/tests/inc/components_tests/components_assign.rs index e2dbb6fda4..84f01db2a8 100644 --- a/module/core/former/tests/inc/components_tests/components_assign.rs +++ b/module/core/former/tests/inc/components_tests/components_assign.rs @@ -73,4 +73,4 @@ impl From< &Options2 > for String // -include!( "./only_test/components_components_assign.rs" ); +include!( "./only_test/components_assign.rs" ); diff --git a/module/core/former/tests/inc/components_tests/components_assign_manual.rs b/module/core/former/tests/inc/components_tests/components_assign_manual.rs index 182ad0dacf..9d7907d05f 100644 --- a/module/core/former/tests/inc/components_tests/components_assign_manual.rs +++ b/module/core/former/tests/inc/components_tests/components_assign_manual.rs @@ -192,4 +192,4 @@ where // -include!( "./only_test/components_components_assign.rs" ); +include!( "./only_test/components_assign.rs" ); diff --git a/module/core/former/tests/inc/components_tests/composite.rs b/module/core/former/tests/inc/components_tests/composite.rs index 7105ba0b0e..723f3be16c 100644 --- a/module/core/former/tests/inc/components_tests/composite.rs +++ b/module/core/former/tests/inc/components_tests/composite.rs @@ -72,4 +72,4 @@ pub struct Options2 // -include!( "./only_test/components_composite.rs" ); +include!( "./only_test/composite.rs" ); diff --git a/module/core/former/tests/inc/components_tests/composite_manual.rs b/module/core/former/tests/inc/components_tests/composite_manual.rs index 34e77f09af..03fc1f28f9 100644 --- a/module/core/former/tests/inc/components_tests/composite_manual.rs +++ b/module/core/former/tests/inc/components_tests/composite_manual.rs @@ -209,4 +209,4 @@ where // -include!( "./only_test/components_composite.rs" ); +include!( "./only_test/composite.rs" ); diff --git a/module/core/former/tests/inc/components_tests/from_components.rs b/module/core/former/tests/inc/components_tests/from_components.rs index 9f69aab624..2105667d9f 100644 --- a/module/core/former/tests/inc/components_tests/from_components.rs +++ b/module/core/former/tests/inc/components_tests/from_components.rs @@ -72,4 +72,4 @@ pub struct Options2 // -include!( "./only_test/components_from_components.rs" ); +include!( "./only_test/from_components.rs" ); diff --git a/module/core/former/tests/inc/components_tests/from_components_manual.rs b/module/core/former/tests/inc/components_tests/from_components_manual.rs index 6a6c29e323..edd26c9c80 100644 --- a/module/core/former/tests/inc/components_tests/from_components_manual.rs +++ b/module/core/former/tests/inc/components_tests/from_components_manual.rs @@ -72,4 +72,4 @@ where // -include!( "./only_test/components_from_components.rs" ); +include!( "./only_test/from_components.rs" ); diff --git a/module/core/former/tests/inc/components_tests/only_test/components_component_assign.rs b/module/core/former/tests/inc/components_tests/only_test/component_assign.rs similarity index 100% rename from module/core/former/tests/inc/components_tests/only_test/components_component_assign.rs rename to module/core/former/tests/inc/components_tests/only_test/component_assign.rs diff --git a/module/core/former/tests/inc/components_tests/only_test/components_component_from.rs b/module/core/former/tests/inc/components_tests/only_test/component_from.rs similarity index 100% rename from module/core/former/tests/inc/components_tests/only_test/components_component_from.rs rename to module/core/former/tests/inc/components_tests/only_test/component_from.rs diff --git a/module/core/former/tests/inc/components_tests/only_test/components_components_assign.rs b/module/core/former/tests/inc/components_tests/only_test/components_assign.rs similarity index 96% rename from module/core/former/tests/inc/components_tests/only_test/components_components_assign.rs rename to module/core/former/tests/inc/components_tests/only_test/components_assign.rs index ecba41850c..37d11147aa 100644 --- a/module/core/former/tests/inc/components_tests/only_test/components_components_assign.rs +++ b/module/core/former/tests/inc/components_tests/only_test/components_assign.rs @@ -7,7 +7,7 @@ fn component_assign() let mut o2 = Options2::default(); o2.assign( 42 ); o2.assign( "Hello, world!" ); - println!( "field1: {}, field2: {}", o2.field1, o2.field2 ); + println!( "field1 : {}, field2 : {}", o2.field1, o2.field2 ); let exp = Options2 { field1 : 42, field2 : "Hello, world!".to_string() }; assert_eq!( o2, exp ); diff --git a/module/core/former/tests/inc/components_tests/only_test/components_composite.rs b/module/core/former/tests/inc/components_tests/only_test/composite.rs similarity index 100% rename from module/core/former/tests/inc/components_tests/only_test/components_composite.rs rename to module/core/former/tests/inc/components_tests/only_test/composite.rs diff --git a/module/core/former/tests/inc/components_tests/only_test/components_from_components.rs b/module/core/former/tests/inc/components_tests/only_test/from_components.rs similarity index 100% rename from module/core/former/tests/inc/components_tests/only_test/components_from_components.rs rename to module/core/former/tests/inc/components_tests/only_test/from_components.rs 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 0948bc601a..3a31ff8664 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -596,3 +596,5 @@ impl syn::parse::Parse for AttributeSubformEntrySetter Ok( Self { name, setter, hint } ) } } + +// xxx : continue \ No newline at end of file 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 16de2b5a5d..2dda529b26 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -328,3 +328,5 @@ impl syn::parse::Parse for AttributePerform }) } } + +// xxx : continue diff --git a/module/core/former_types/Cargo.toml b/module/core/former_types/Cargo.toml new file mode 100644 index 0000000000..c886a076bd --- /dev/null +++ b/module/core/former_types/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "former_types" +version = "2.0.0" +edition = "2021" +authors = [ + "Kostiantyn Wandalen ", +] +license = "MIT" +readme = "Readme.md" +documentation = "https://docs.rs/former" +repository = "https://github.com/Wandalen/wTools/tree/master/module/core/former" +homepage = "https://github.com/Wandalen/wTools/tree/master/module/core/former" +description = """ +A flexible and extensible implementation of the builder pattern. Its compile-time structures and traits that are not generated but reused. +""" +categories = [ "algorithms", "development-tools" ] +keywords = [ "fundamental", "general-purpose", "builder-pattern" ] + +[lints] +workspace = true + +[package.metadata.docs.rs] +features = [ "full" ] +all-features = false + +[features] + +no_std = [ "collection_tools/no_std" ] +use_alloc = [ "no_std", "collection_tools/use_alloc" ] + +default = [ + "enabled", + "derive_former", + "derive_components", + "derive_component_from", + "derive_component_assign", + "derive_components_assign", + "derive_from_components", +] +full = [ + "enabled", + "derive_former", + "derive_components", + "derive_component_from", + "derive_component_assign", + "derive_components_assign", + "derive_from_components", +] +enabled = [ "collection_tools/enabled" ] + +derive_former = [] +derive_components = [] +derive_component_assign = [ "derive_components" ] +derive_components_assign = [ "derive_components", "derive_component_assign" ] +derive_component_from = [ "derive_components" ] +derive_from_components = [ "derive_components" ] + + +[dependencies] +collection_tools = { workspace = true, features = [ "collection_constructors" ] } +# qqq : optimize also make sure collection_tools expose enough features + +[dev-dependencies] +test_tools = { workspace = true, features = [ "full" ] } diff --git a/module/core/former_types/License b/module/core/former_types/License new file mode 100644 index 0000000000..e3e9e057cf --- /dev/null +++ b/module/core/former_types/License @@ -0,0 +1,23 @@ +Copyright Kostiantyn W and Out of the Box Systems (c) 2013-2024 + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/module/core/former_types/Readme.md b/module/core/former_types/Readme.md new file mode 100644 index 0000000000..105cb237a2 --- /dev/null +++ b/module/core/former_types/Readme.md @@ -0,0 +1,70 @@ + + +# Module :: former_types + + + [![experimental](https://raster.shields.io/static/v1?label=&message=experimental&color=orange)](https://github.com/emersion/stability-badges#experimental) [![rust-status](https://github.com/Wandalen/wTools/actions/workflows/module_former_types_push.yml/badge.svg)](https://github.com/Wandalen/wTools/actions/workflows/module_former_types_push.yml) [![docs.rs](https://img.shields.io/docsrs/former_types?color=e3e8f0&logo=docs.rs)](https://docs.rs/former_types) [![Open in Gitpod](https://raster.shields.io/static/v1?label=try&message=online&color=eee&logo=gitpod&logoColor=eee)](https://gitpod.io/#RUN_PATH=.,SAMPLE_FILE=module%2Fcore%2Fformer_types%2Fexamples%2Fformer_types_trivial.rs,RUN_POSTFIX=--example%20former_types_trivial/https://github.com/Wandalen/wTools) [![discord](https://img.shields.io/discord/872391416519737405?color=eee&logo=discord&logoColor=eee&label=ask)](https://discord.gg/m3YfbXpUUY) + + +A flexible and extensible implementation of the builder pattern. Its compile-time structures and traits that are not generated but reused. + +## Example: Using Trait ComponentAssign + +Demonstrates setting various components (fields) of a struct. + +The `former_types` crate provides a generic interface for setting components on an object. This example defines a `Person` struct +and implements the `ComponentAssign` trait for its fields. It shows how to use these implementations to set the fields of a `Person` +instance using different types that can be converted into the required types. + +```rust +#[ cfg( any( not( feature = "derive_former" ), not( feature = "enabled" ) ) ) ] +fn main() {} + +#[ cfg( all( feature = "derive_former", feature = "enabled" ) ) ] +fn main() +{ + use former_types::ComponentAssign; + + #[ derive( Default, PartialEq, Debug ) ] + struct Person + { + age : i32, + name : String, + } + + impl< IntoT > ComponentAssign< i32, IntoT > for Person + where + IntoT : Into< i32 >, + { + fn assign( &mut self, component : IntoT ) + { + self.age = component.into(); + } + } + + impl< IntoT > ComponentAssign< String, IntoT > for Person + where + IntoT : Into< String >, + { + fn assign( &mut self, component : IntoT ) + { + self.name = component.into(); + } + } + + let mut got : Person = Default::default(); + got.assign( 13 ); + got.assign( "John" ); + assert_eq!( got, Person { age : 13, name : "John".to_string() } ); + dbg!( got ); + // > Person { + // > age: 13, + // > name: "John", + // > } + +} +``` + +Try out `cargo run --example former_types_trivial`. +
+[See code](./examples/former_types_trivial.rs). diff --git a/module/core/former_types/examples/former_types_trivial.rs b/module/core/former_types/examples/former_types_trivial.rs new file mode 100644 index 0000000000..70d226686d --- /dev/null +++ b/module/core/former_types/examples/former_types_trivial.rs @@ -0,0 +1,68 @@ +//! +//! ## Example: Using Trait ComponentAssign +//! +//! Demonstrates setting various components (fields) of a struct. +//! +//! The `former_types` crate provides a generic interface for setting components on an object. This example defines a `Person` struct +//! and implements the `ComponentAssign` trait for its fields. It shows how to use these implementations to set the fields of a `Person` +//! instance using different types that can be converted into the required types. +//! +//! ## Explanation +//! +//! - **Person Struct**: The `Person` struct has two fields: `age` (an integer) and `name` (a string). The `Default` and `PartialEq` traits are derived to facilitate default construction and comparison. +//! +//! - **ComponentAssign Implementations**: The `ComponentAssign` trait is implemented for the `age` and `name` fields of the `Person` struct. +//! - For `age`: The trait is implemented for any type that can be converted into an `i32`. +//! - For `name`: The trait is implemented for any type that can be converted into a `String`. +//! +//! - **Usage**: An instance of `Person` is created using the default constructor, and then the `assign` method is used to set the `age` and `name` fields. +//! - `got.assign( 13 )`: Assigns the integer `13` to the `age` field. +//! - `got.assign( "John" )`: Assigns the string `"John"` to the `name` field. +//! + +#[ cfg( any( not( feature = "derive_former" ), not( feature = "enabled" ) ) ) ] +fn main() {} + +#[ cfg( all( feature = "derive_former", feature = "enabled" ) ) ] +fn main() +{ + use former_types::ComponentAssign; + + #[ derive( Default, PartialEq, Debug ) ] + struct Person + { + age : i32, + name : String, + } + + impl< IntoT > ComponentAssign< i32, IntoT > for Person + where + IntoT : Into< i32 >, + { + fn assign( &mut self, component : IntoT ) + { + self.age = component.into(); + } + } + + impl< IntoT > ComponentAssign< String, IntoT > for Person + where + IntoT : Into< String >, + { + fn assign( &mut self, component : IntoT ) + { + self.name = component.into(); + } + } + + let mut got : Person = Default::default(); + got.assign( 13 ); + got.assign( "John" ); + assert_eq!( got, Person { age : 13, name : "John".to_string() } ); + dbg!( got ); + // > Person { + // > age: 13, + // > name: "John", + // > } + +} diff --git a/module/core/former/src/axiomatic.rs b/module/core/former_types/src/axiomatic.rs similarity index 100% rename from module/core/former/src/axiomatic.rs rename to module/core/former_types/src/axiomatic.rs diff --git a/module/core/former/src/collection.rs b/module/core/former_types/src/collection.rs similarity index 96% rename from module/core/former/src/collection.rs rename to module/core/former_types/src/collection.rs index a17521e277..eac724c018 100644 --- a/module/core/former/src/collection.rs +++ b/module/core/former_types/src/collection.rs @@ -66,7 +66,7 @@ pub( crate ) mod private /// /// # Example /// ``` - /// use former::CollectionValToEntry; + /// use former_types::CollectionValToEntry; // use crate `former` instead of crate `former_types` unless you need to use crate `former_types` directly /// /// struct PairMap; /// @@ -104,7 +104,7 @@ pub( crate ) mod private /// /// # Example /// ``` - /// use former::ValToEntry; + /// use former_types::ValToEntry; // use crate `former` instead of crate `former_types` unless you need to use crate `former_types` directly /// /// struct PairMap; /// @@ -184,7 +184,7 @@ pub( crate ) mod private /// /// ```rust /// - /// use former::{ Collection, CollectionAdd }; + /// use former_types::{ Collection, CollectionAdd }; // use crate `former` instead of crate `former_types` unless you need to use crate `former_types` directly /// /// struct MyCollection /// { @@ -255,7 +255,7 @@ pub( crate ) mod private /// # Examples /// /// ```rust - /// use former::{ Collection, CollectionAssign }; + /// use former_types::{ Collection, CollectionAssign }; // use crate `former` instead of crate `former_types` unless you need to use crate `former_types` directly /// /// struct MyCollection /// { diff --git a/module/core/former/src/collection/binary_heap.rs b/module/core/former_types/src/collection/binary_heap.rs similarity index 100% rename from module/core/former/src/collection/binary_heap.rs rename to module/core/former_types/src/collection/binary_heap.rs diff --git a/module/core/former/src/collection/btree_map.rs b/module/core/former_types/src/collection/btree_map.rs similarity index 100% rename from module/core/former/src/collection/btree_map.rs rename to module/core/former_types/src/collection/btree_map.rs diff --git a/module/core/former/src/collection/btree_set.rs b/module/core/former_types/src/collection/btree_set.rs similarity index 100% rename from module/core/former/src/collection/btree_set.rs rename to module/core/former_types/src/collection/btree_set.rs diff --git a/module/core/former/src/collection/hash_map.rs b/module/core/former_types/src/collection/hash_map.rs similarity index 100% rename from module/core/former/src/collection/hash_map.rs rename to module/core/former_types/src/collection/hash_map.rs diff --git a/module/core/former/src/collection/hash_set.rs b/module/core/former_types/src/collection/hash_set.rs similarity index 100% rename from module/core/former/src/collection/hash_set.rs rename to module/core/former_types/src/collection/hash_set.rs diff --git a/module/core/former/src/collection/linked_list.rs b/module/core/former_types/src/collection/linked_list.rs similarity index 100% rename from module/core/former/src/collection/linked_list.rs rename to module/core/former_types/src/collection/linked_list.rs diff --git a/module/core/former/src/collection/vector.rs b/module/core/former_types/src/collection/vector.rs similarity index 100% rename from module/core/former/src/collection/vector.rs rename to module/core/former_types/src/collection/vector.rs diff --git a/module/core/former/src/collection/vector_deque.rs b/module/core/former_types/src/collection/vector_deque.rs similarity index 100% rename from module/core/former/src/collection/vector_deque.rs rename to module/core/former_types/src/collection/vector_deque.rs diff --git a/module/core/former/src/component.rs b/module/core/former_types/src/component.rs similarity index 93% rename from module/core/former/src/component.rs rename to module/core/former_types/src/component.rs index 67ea2fdabb..cd82bbebd6 100644 --- a/module/core/former/src/component.rs +++ b/module/core/former_types/src/component.rs @@ -19,7 +19,7 @@ /// Implementing `ComponentAssign` to set a name string on a struct : /// /// ```rust -/// use former::ComponentAssign; +/// use former_types::ComponentAssign; // use crate `former` instead of crate `former_types` unless you need to use crate `former_types` directly /// /// struct MyStruct /// { @@ -66,7 +66,7 @@ where /// ### Example /// /// ```rust -/// use former::{ ComponentAssign, AssignWithType }; +/// use former_types::{ ComponentAssign, AssignWithType }; // use crate `former` instead of crate `former_types` unless you need to use crate `former_types` directly /// /// struct UserProfile /// { diff --git a/module/core/former/src/definition.rs b/module/core/former_types/src/definition.rs similarity index 100% rename from module/core/former/src/definition.rs rename to module/core/former_types/src/definition.rs diff --git a/module/core/former/src/forming.rs b/module/core/former_types/src/forming.rs similarity index 100% rename from module/core/former/src/forming.rs rename to module/core/former_types/src/forming.rs diff --git a/module/core/former_types/src/lib.rs b/module/core/former_types/src/lib.rs new file mode 100644 index 0000000000..03afdfbb7d --- /dev/null +++ b/module/core/former_types/src/lib.rs @@ -0,0 +1,101 @@ +#![ cfg_attr( feature = "no_std", no_std ) ] +#![ doc( html_logo_url = "https://raw.githubusercontent.com/Wandalen/wTools/master/asset/img/logo_v3_trans_square.png" ) ] +#![ doc( html_favicon_url = "https://raw.githubusercontent.com/Wandalen/wTools/alpha/asset/img/logo_v3_trans_square_icon_small_v2.ico" ) ] +#![ doc( html_root_url = "https://docs.rs/former_types/latest/former_types/" ) ] +#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "Readme.md" ) ) ] + +/// Axiomatic things. +#[ cfg( feature = "enabled" ) ] +#[ cfg( feature = "derive_former" ) ] +mod axiomatic; +/// Forming process. +#[ cfg( feature = "enabled" ) ] +#[ cfg( feature = "derive_former" ) ] +mod definition; +/// Forming process. +#[ cfg( feature = "enabled" ) ] +#[ cfg( feature = "derive_former" ) ] +mod forming; +/// Storage. +#[ cfg( feature = "enabled" ) ] +#[ cfg( feature = "derive_former" ) ] +mod storage; + +/// Interface for collections. +#[ cfg( feature = "enabled" ) ] +#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] +#[ cfg( feature = "derive_former" ) ] +mod collection; + +/// Component-based forming. +#[ cfg( feature = "enabled" ) ] +#[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] +mod component; + +/// Namespace with dependencies. +#[ cfg( feature = "enabled" ) ] +pub mod dependency +{ + pub use ::collection_tools; +} + +#[ doc( inline ) ] +#[ allow( unused_imports ) ] +#[ cfg( feature = "enabled" ) ] +pub use protected::*; + +/// Protected namespace of the module. +#[ cfg( feature = "enabled" ) ] +pub mod protected +{ + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::orphan::*; +} + +/// Parented namespace of the module. +#[ cfg( feature = "enabled" ) ] +pub mod orphan +{ + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::exposed::*; +} + +/// Exposed namespace of the module. +#[ cfg( feature = "enabled" ) ] +pub mod exposed +{ + + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::prelude::*; + + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + #[ cfg( feature = "derive_former" ) ] + pub use super:: + { + axiomatic::*, + definition::*, + forming::*, + storage::*, + }; + + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] + #[ cfg( feature = "derive_former" ) ] + pub use super::collection::*; + +} + +/// Prelude to use essentials: `use my_module::prelude::*`. +#[ cfg( feature = "enabled" ) ] +pub mod prelude +{ + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + #[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] + pub use super::component::*; +} diff --git a/module/core/former/src/storage.rs b/module/core/former_types/src/storage.rs similarity index 100% rename from module/core/former/src/storage.rs rename to module/core/former_types/src/storage.rs diff --git a/module/core/former_types/tests/inc/mod.rs b/module/core/former_types/tests/inc/mod.rs new file mode 100644 index 0000000000..22f62f130b --- /dev/null +++ b/module/core/former_types/tests/inc/mod.rs @@ -0,0 +1,51 @@ +// #![ deny( missing_docs ) ] + +#[ allow( unused_imports ) ] +use super::*; + +#[ cfg( feature = "derive_former" ) ] +#[ path = "../../../former/tests/inc/former_tests" ] +mod former_tests +{ + #[ allow( unused_imports ) ] + use super::*; + + // = basic + + #[ cfg( any( feature = "use_alloc", not( feature = "no_std" ) ) ) ] + mod a_basic_manual; + mod a_primitives_manual; + + #[ cfg( any( feature = "use_alloc", not( feature = "no_std" ) ) ) ] + mod subform_collection_basic_manual; + + // = parametrization + + #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] + mod parametrized_struct_manual; + mod parametrized_slice_manual; + +} + +#[ cfg( feature = "derive_components" ) ] +#[ path = "../../../former/tests/inc/components_tests" ] +mod components_tests +{ + use super::*; + + #[ cfg( feature = "derive_component_from" ) ] + mod component_from_manual; + + #[ cfg( feature = "derive_component_assign" ) ] + mod component_assign_manual; + + #[ cfg( all( feature = "derive_component_assign", feature = "derive_components_assign" ) ) ] + mod components_assign_manual; + + #[ cfg( all( feature = "derive_from_components" ) ) ] + mod from_components_manual; + + #[ cfg( all( feature = "derive_component_from", feature = "derive_component_assign", feature = "derive_components_assign", feature = "derive_from_components" ) ) ] + mod composite_manual; + +} diff --git a/module/core/former_types/tests/smoke_test.rs b/module/core/former_types/tests/smoke_test.rs new file mode 100644 index 0000000000..7fd288e61d --- /dev/null +++ b/module/core/former_types/tests/smoke_test.rs @@ -0,0 +1,14 @@ + +// #[ cfg( feature = "default" ) ] +#[ test ] +fn local_smoke_test() +{ + ::test_tools::smoke_test_for_local_run(); +} + +// #[ cfg( feature = "default" ) ] +#[ test ] +fn published_smoke_test() +{ + ::test_tools::smoke_test_for_published_run(); +} diff --git a/module/core/former_types/tests/tests.rs b/module/core/former_types/tests/tests.rs new file mode 100644 index 0000000000..caea26275c --- /dev/null +++ b/module/core/former_types/tests/tests.rs @@ -0,0 +1,12 @@ + +include!( "../../../../module/step/meta/src/module/terminal.rs" ); + +#[ allow( unused_imports ) ] +use test_tools::exposed::*; +#[ allow( unused_imports ) ] +use former_types as the_module; +#[ allow( unused_imports ) ] +use former_types as former; + +#[ cfg( feature = "enabled" ) ] +mod inc; From 7126676f6d17c0ff8175267ca31faec0387483bd Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 12:56:09 +0300 Subject: [PATCH 03/44] collection_tools-v0.7.0 --- Cargo.toml | 2 +- module/core/collection_tools/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3084f01f68..8291efb44c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,7 +104,7 @@ default-features = false features = [ "enabled" ] [workspace.dependencies.collection_tools] -version = "~0.6.0" +version = "~0.7.0" path = "module/core/collection_tools" default-features = false diff --git a/module/core/collection_tools/Cargo.toml b/module/core/collection_tools/Cargo.toml index 066aad99c0..92912400fd 100644 --- a/module/core/collection_tools/Cargo.toml +++ b/module/core/collection_tools/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collection_tools" -version = "0.6.0" +version = "0.7.0" edition = "2021" authors = [ "Kostiantyn Wandalen ", From 9591b8153d68b7e5799ccb8a8270f64563be41a9 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 14:16:57 +0300 Subject: [PATCH 04/44] experimenting --- module/core/collection_tools/src/lib.rs | 2 +- module/core/former/Cargo.toml | 3 ++- module/core/former_meta/Cargo.toml | 3 ++- .../former_meta/src/component/components_assign.rs | 2 +- .../core/former_meta/src/derive_former/field_attrs.rs | 3 +-- .../former_meta/src/derive_former/struct_attrs.rs | 11 ++++++++++- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/module/core/collection_tools/src/lib.rs b/module/core/collection_tools/src/lib.rs index d37a4bcb8f..82654976ee 100644 --- a/module/core/collection_tools/src/lib.rs +++ b/module/core/collection_tools/src/lib.rs @@ -89,7 +89,7 @@ pub mod prelude #[ cfg( any( feature = "use_alloc", not( feature = "no_std" ) ) ) ] #[ doc( inline ) ] #[ allow( unused_imports ) ] - pub use + pub use { HashMap as Map, HashSet as Set, diff --git a/module/core/former/Cargo.toml b/module/core/former/Cargo.toml index 17aa035a97..aef9cb4056 100644 --- a/module/core/former/Cargo.toml +++ b/module/core/former/Cargo.toml @@ -29,6 +29,7 @@ all-features = false no_std = [ "former_types/no_std", "collection_tools/no_std" ] use_alloc = [ "no_std", "former_types/use_alloc", "collection_tools/use_alloc" ] + # no_std = [ "collection_tools/no_std" ] # use_alloc = [ "no_std", "collection_tools/use_alloc" ] @@ -68,4 +69,4 @@ former_types = { workspace = true } [dev-dependencies] test_tools = { workspace = true, features = [ "full" ] } -collection_tools = { workspace = true, features = [ "collection_constructors" ] } \ No newline at end of file +collection_tools = { workspace = true, features = [ "collection_constructors" ] } diff --git a/module/core/former_meta/Cargo.toml b/module/core/former_meta/Cargo.toml index 8eb10e870d..e01438d242 100644 --- a/module/core/former_meta/Cargo.toml +++ b/module/core/former_meta/Cargo.toml @@ -57,7 +57,8 @@ derive_from_components = [ "derive_components" ] proc-macro = true [dependencies] -macro_tools = { workspace = true } +macro_tools = { workspace = true } # qqq : optimize set of features +former_types = { workspace = true } # qqq : optimize set of features iter_tools = { workspace = true } convert_case = { version = "0.6.0", default-features = false, optional = true, features = [] } diff --git a/module/core/former_meta/src/component/components_assign.rs b/module/core/former_meta/src/component/components_assign.rs index 8ceb0f3ad3..4a69425dd3 100644 --- a/module/core/former_meta/src/component/components_assign.rs +++ b/module/core/former_meta/src/component/components_assign.rs @@ -21,7 +21,7 @@ pub fn components_assign( input : proc_macro::TokenStream ) -> Result< proc_macr let trait_ident = syn::Ident::new( &trait_name, item_name.span() ); let method_name = format!( "{}_assign", item_name.to_string().to_case( Case::Snake ) ); let method_ident = syn::Ident::new( &method_name, item_name.span() ); - // xxx : make a macro ident_format!() + // xxx : use macro ident_format!() // fields let ( bounds1, bounds2, component_assigns ) : ( Vec< _ >, Vec< _ >, Vec< _ > ) = parsed.fields.iter().map( | field | 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 3a31ff8664..bb7b776b50 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -549,7 +549,6 @@ impl syn::parse::Parse for AttributeSubformEntrySetter let mut setter : Option< bool > = None; let mut hint = false; - // xxx : qqq for Anton : use match here and for all attributes -- done while !input.is_empty() { let lookahead = input.lookahead1(); @@ -597,4 +596,4 @@ impl syn::parse::Parse for AttributeSubformEntrySetter } } -// xxx : continue \ No newline at end of file +// xxx : continue 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 2dda529b26..1f735995cc 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -12,6 +12,16 @@ pub struct StructAttributes pub perform : Option< AttributePerform >, } +impl< IntoT > ComponentAssign< AttributeStorageFields, IntoT > for StructAttributes +where + IntoT : Into< AttributeStorageFields >, +{ + fn assign( &mut self, component : IntoT ) + { + self.storage_fields = component.into(); + } +} + impl StructAttributes { @@ -238,7 +248,6 @@ impl syn::parse::Parse for AttributeMutator let mut custom = false; let mut hint = false; - // xxx : qqq for Anton : use match here and for all attributes -- done while !input.is_empty() { let lookahead = input.lookahead1(); From 29849af9e20e84b989d21ff9db22139f514db8cf Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 14:19:41 +0300 Subject: [PATCH 05/44] task --- module/core/collection_tools/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/core/collection_tools/src/lib.rs b/module/core/collection_tools/src/lib.rs index 82654976ee..020d82076a 100644 --- a/module/core/collection_tools/src/lib.rs +++ b/module/core/collection_tools/src/lib.rs @@ -4,6 +4,9 @@ #![ doc( html_root_url = "https://docs.rs/collection_tools/latest/collection_tools/" ) ] #![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "Readme.md" ) ) ] +#![ allow( unused_extern_crates ) ] +// qqq : for Anton : remove it + #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] extern crate alloc; From d1cd8b92feddcf1afdfd6c842652adb7d2ca8b18 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 14:43:33 +0300 Subject: [PATCH 06/44] former_meta : use ComponentAssign. former_types : reduce features --- module/core/former/Cargo.toml | 10 ++++----- module/core/former_meta/Cargo.toml | 4 ++-- .../src/derive_former/struct_attrs.rs | 3 ++- module/core/former_types/Cargo.toml | 22 ++++++------------- module/core/former_types/src/component.rs | 6 ++--- module/core/former_types/src/lib.rs | 4 ++-- module/core/former_types/tests/inc/mod.rs | 12 +++++----- 7 files changed, 27 insertions(+), 34 deletions(-) diff --git a/module/core/former/Cargo.toml b/module/core/former/Cargo.toml index aef9cb4056..645deff0c3 100644 --- a/module/core/former/Cargo.toml +++ b/module/core/former/Cargo.toml @@ -54,11 +54,11 @@ full = [ enabled = [ "former_meta/enabled", "former_types/enabled" ] derive_former = [ "former_meta/derive_former", "former_types/derive_former" ] -derive_components = [ "former_meta/derive_components", "former_types/derive_components" ] -derive_component_assign = [ "derive_components", "former_meta/derive_component_assign", "former_types/derive_component_assign" ] -derive_components_assign = [ "derive_components", "derive_component_assign", "former_meta/derive_components_assign", "former_types/derive_components_assign" ] -derive_component_from = [ "derive_components", "former_meta/derive_component_from", "former_types/derive_component_from" ] -derive_from_components = [ "derive_components", "former_meta/derive_from_components", "former_types/derive_from_components" ] +derive_components = [ "former_meta/derive_components", "former_types/types_components" ] +derive_component_assign = [ "derive_components", "former_meta/derive_component_assign", "former_types/types_component_assign" ] +derive_components_assign = [ "derive_components", "derive_component_assign", "former_meta/derive_components_assign" ] +derive_component_from = [ "derive_components", "former_meta/derive_component_from" ] +derive_from_components = [ "derive_components", "former_meta/derive_from_components" ] [dependencies] diff --git a/module/core/former_meta/Cargo.toml b/module/core/former_meta/Cargo.toml index e01438d242..b2e86a29bb 100644 --- a/module/core/former_meta/Cargo.toml +++ b/module/core/former_meta/Cargo.toml @@ -44,7 +44,7 @@ full = [ "derive_components_assign", "derive_from_components", ] -enabled = [ "macro_tools/enabled", "iter_tools/enabled" ] +enabled = [ "macro_tools/enabled", "iter_tools/enabled", "former_types/enabled" ] derive_former = [ "convert_case" ] derive_components = [] @@ -58,7 +58,7 @@ proc-macro = true [dependencies] macro_tools = { workspace = true } # qqq : optimize set of features -former_types = { workspace = true } # qqq : optimize set of features +former_types = { workspace = true, features = [ "types_component_assign" ] } # qqq : optimize set of features iter_tools = { workspace = true } convert_case = { version = "0.6.0", default-features = false, optional = true, features = [] } 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 1f735995cc..c3c03b3494 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -1,6 +1,7 @@ use super::*; use macro_tools::{ attr, Result }; +use former_types::{ ComponentAssign }; /// /// Attributes of a struct. @@ -18,7 +19,7 @@ where { fn assign( &mut self, component : IntoT ) { - self.storage_fields = component.into(); + self.storage_fields = Some( component.into() ); } } diff --git a/module/core/former_types/Cargo.toml b/module/core/former_types/Cargo.toml index c886a076bd..ab104de2fd 100644 --- a/module/core/former_types/Cargo.toml +++ b/module/core/former_types/Cargo.toml @@ -31,34 +31,26 @@ use_alloc = [ "no_std", "collection_tools/use_alloc" ] default = [ "enabled", "derive_former", - "derive_components", - "derive_component_from", - "derive_component_assign", - "derive_components_assign", - "derive_from_components", + "types_components", + "types_component_assign", ] full = [ "enabled", "derive_former", - "derive_components", - "derive_component_from", - "derive_component_assign", - "derive_components_assign", - "derive_from_components", + "types_components", + "types_component_assign", ] enabled = [ "collection_tools/enabled" ] derive_former = [] -derive_components = [] -derive_component_assign = [ "derive_components" ] -derive_components_assign = [ "derive_components", "derive_component_assign" ] -derive_component_from = [ "derive_components" ] -derive_from_components = [ "derive_components" ] +types_components = [] +types_component_assign = [ "types_components" ] [dependencies] collection_tools = { workspace = true, features = [ "collection_constructors" ] } # qqq : optimize also make sure collection_tools expose enough features + [dev-dependencies] test_tools = { workspace = true, features = [ "full" ] } diff --git a/module/core/former_types/src/component.rs b/module/core/former_types/src/component.rs index cd82bbebd6..1edd59bb36 100644 --- a/module/core/former_types/src/component.rs +++ b/module/core/former_types/src/component.rs @@ -38,7 +38,7 @@ /// obj.assign( "New Name" ); /// assert_eq!( obj.name, "New Name" ); /// ``` -#[ cfg( any( feature = "derive_component_assign", feature = "derive_components_assign" ) ) ] +#[ cfg( any( feature = "types_component_assign" ) ) ] pub trait ComponentAssign< T, IntoT > where IntoT : Into< T >, @@ -89,7 +89,7 @@ where /// ``` /// -#[ cfg( any( feature = "derive_component_assign", feature = "derive_components_assign" ) ) ] +#[ cfg( any( feature = "types_component_assign" ) ) ] pub trait AssignWithType { /// Function to set value of a component by its type. @@ -99,7 +99,7 @@ pub trait AssignWithType Self : ComponentAssign< T, IntoT >; } -#[ cfg( any( feature = "derive_component_assign", feature = "derive_components_assign" ) ) ] +#[ cfg( any( feature = "types_component_assign" ) ) ] impl< S > AssignWithType for S { diff --git a/module/core/former_types/src/lib.rs b/module/core/former_types/src/lib.rs index 03afdfbb7d..90b2af5410 100644 --- a/module/core/former_types/src/lib.rs +++ b/module/core/former_types/src/lib.rs @@ -29,7 +29,7 @@ mod collection; /// Component-based forming. #[ cfg( feature = "enabled" ) ] -#[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] +#[ cfg( any( feature = "types_component_assign" ) ) ] mod component; /// Namespace with dependencies. @@ -96,6 +96,6 @@ pub mod prelude { #[ doc( inline ) ] #[ allow( unused_imports ) ] - #[ cfg( any( feature = "derive_component_from", feature = "derive_component_assign" ) ) ] + #[ cfg( any( feature = "types_component_assign" ) ) ] pub use super::component::*; } diff --git a/module/core/former_types/tests/inc/mod.rs b/module/core/former_types/tests/inc/mod.rs index 22f62f130b..59fea4b027 100644 --- a/module/core/former_types/tests/inc/mod.rs +++ b/module/core/former_types/tests/inc/mod.rs @@ -27,25 +27,25 @@ mod former_tests } -#[ cfg( feature = "derive_components" ) ] +#[ cfg( feature = "types_components" ) ] #[ path = "../../../former/tests/inc/components_tests" ] mod components_tests { use super::*; - #[ cfg( feature = "derive_component_from" ) ] + #[ cfg( feature = "types_component_from" ) ] mod component_from_manual; - #[ cfg( feature = "derive_component_assign" ) ] + #[ cfg( feature = "types_component_assign" ) ] mod component_assign_manual; - #[ cfg( all( feature = "derive_component_assign", feature = "derive_components_assign" ) ) ] + #[ cfg( all( feature = "types_component_assign" ) ) ] mod components_assign_manual; - #[ cfg( all( feature = "derive_from_components" ) ) ] + // #[ cfg( all( feature = "derive_from_components" ) ) ] mod from_components_manual; - #[ cfg( all( feature = "derive_component_from", feature = "derive_component_assign", feature = "derive_components_assign", feature = "derive_from_components" ) ) ] + #[ cfg( all( feature = "types_component_assign" ) ) ] mod composite_manual; } From aceb1f16502f4683a87fc01f029f1ab580ab9124 Mon Sep 17 00:00:00 2001 From: Anton Parfonov Date: Tue, 21 May 2024 15:13:54 +0300 Subject: [PATCH 07/44] Add reexports feature to collection_tools --- module/core/former_types/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/core/former_types/Cargo.toml b/module/core/former_types/Cargo.toml index c886a076bd..4ca7bd89f6 100644 --- a/module/core/former_types/Cargo.toml +++ b/module/core/former_types/Cargo.toml @@ -57,7 +57,7 @@ derive_from_components = [ "derive_components" ] [dependencies] -collection_tools = { workspace = true, features = [ "collection_constructors" ] } +collection_tools = { workspace = true, features = [ "collection_constructors", "reexports" ] } # qqq : optimize also make sure collection_tools expose enough features [dev-dependencies] From 04204461e55e147f71f30662f9a53d32939bc005 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 15:44:16 +0300 Subject: [PATCH 08/44] former_meta : use ComponentAssign --- .../src/derive_former/struct_attrs.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) 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 c3c03b3494..c2b6148f4e 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -23,6 +23,26 @@ where } } +impl< IntoT > ComponentAssign< AttributeMutator, IntoT > for StructAttributes +where + IntoT : Into< AttributeMutator >, +{ + fn assign( &mut self, component : IntoT ) + { + self.mutator = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePerform, IntoT > for StructAttributes +where + IntoT : Into< AttributePerform >, +{ + fn assign( &mut self, component : IntoT ) + { + self.perform = Some( component.into() ); + } +} + impl StructAttributes { From 1f7725de5e8c29235ba96dc53657f3c496442546 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 15:50:41 +0300 Subject: [PATCH 09/44] collection_tolls : not prelude, but exposed. rid off feature reexports --- module/core/collection_tools/Cargo.toml | 6 +++--- module/core/collection_tools/src/lib.rs | 28 +++++++++++-------------- module/core/data_type/Cargo.toml | 3 ++- module/core/former_types/Cargo.toml | 2 +- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/module/core/collection_tools/Cargo.toml b/module/core/collection_tools/Cargo.toml index 92912400fd..43e093f943 100644 --- a/module/core/collection_tools/Cargo.toml +++ b/module/core/collection_tools/Cargo.toml @@ -39,20 +39,20 @@ use_alloc = [ default = [ "enabled", - "reexports", + # "reexports", "collection_constructors", "collection_into_constructors", ] full = [ "enabled", - "reexports", + # "reexports", "collection_constructors", "collection_into_constructors", ] enabled = [] -reexports = [] +# reexports = [] # Collection constructors, like `hmap!{ "key" => "val" }` collection_constructors = [] diff --git a/module/core/collection_tools/src/lib.rs b/module/core/collection_tools/src/lib.rs index 020d82076a..2d6428c57d 100644 --- a/module/core/collection_tools/src/lib.rs +++ b/module/core/collection_tools/src/lib.rs @@ -4,16 +4,9 @@ #![ doc( html_root_url = "https://docs.rs/collection_tools/latest/collection_tools/" ) ] #![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "Readme.md" ) ) ] -#![ allow( unused_extern_crates ) ] -// qqq : for Anton : remove it - #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] extern crate alloc; -// qqq : make subdirectory for each container -- done - -// qqq : move out of lib.rs file -- moved to `collections.rs` - /// Module containing all collection macros #[ cfg( feature = "enabled" ) ] #[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ] @@ -61,18 +54,12 @@ pub mod orphan #[ cfg( feature = "enabled" ) ] pub mod exposed { + #[ doc( inline ) ] #[ allow( unused_imports ) ] pub use super::prelude::*; -} - -/// Prelude to use essentials: `use my_module::prelude::*`. -#[ cfg( feature = "enabled" ) ] -pub mod prelude -{ - // qqq : for Anton : uncomment, make it working and cover by tests -- renamed to reexports - #[ cfg( feature = "reexports" ) ] + // #[ cfg( feature = "reexports" ) ] #[ cfg( any( feature = "use_alloc", not( feature = "no_std" ) ) ) ] #[ doc( inline ) ] #[ allow( unused_imports ) ] @@ -88,7 +75,7 @@ pub mod prelude vecd::VecDeque, }; - #[ cfg( feature = "reexports" ) ] + // #[ cfg( feature = "reexports" ) ] #[ cfg( any( feature = "use_alloc", not( feature = "no_std" ) ) ) ] #[ doc( inline ) ] #[ allow( unused_imports ) ] @@ -98,4 +85,13 @@ pub mod prelude HashSet as Set, Vec as DynArray, }; + + // qqq : cover by tests presence of all containers immidiately in collection_tools::* and in collection_tools::exposed::* + +} + +/// Prelude to use essentials: `use my_module::prelude::*`. +#[ cfg( feature = "enabled" ) ] +pub mod prelude +{ } diff --git a/module/core/data_type/Cargo.toml b/module/core/data_type/Cargo.toml index 8b21b92043..cbb30c67f3 100644 --- a/module/core/data_type/Cargo.toml +++ b/module/core/data_type/Cargo.toml @@ -54,7 +54,8 @@ no_std = [] use_alloc = [ "no_std" ] enabled = [] -dt_prelude = [ "collection_tools/reexports" ] +# dt_prelude = [ "collection_tools/reexports" ] +dt_prelude = [] # rid off maybe? dt_interval = [ "interval_adapter/enabled" ] dt_collections = [ "collection_tools/enabled" ] dt_either = [ "either" ] diff --git a/module/core/former_types/Cargo.toml b/module/core/former_types/Cargo.toml index 33cdcbf7d6..ab104de2fd 100644 --- a/module/core/former_types/Cargo.toml +++ b/module/core/former_types/Cargo.toml @@ -48,7 +48,7 @@ types_component_assign = [ "types_components" ] [dependencies] -collection_tools = { workspace = true, features = [ "collection_constructors", "reexports" ] } +collection_tools = { workspace = true, features = [ "collection_constructors" ] } # qqq : optimize also make sure collection_tools expose enough features From 0173ec220a300cf8163a06703d348c5cf54815e5 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 15:52:21 +0300 Subject: [PATCH 10/44] collection_tools-v0.8.0 --- Cargo.toml | 2 +- module/core/collection_tools/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8291efb44c..854b033b75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -104,7 +104,7 @@ default-features = false features = [ "enabled" ] [workspace.dependencies.collection_tools] -version = "~0.7.0" +version = "~0.8.0" path = "module/core/collection_tools" default-features = false diff --git a/module/core/collection_tools/Cargo.toml b/module/core/collection_tools/Cargo.toml index 43e093f943..65a81d7cde 100644 --- a/module/core/collection_tools/Cargo.toml +++ b/module/core/collection_tools/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collection_tools" -version = "0.7.0" +version = "0.8.0" edition = "2021" authors = [ "Kostiantyn Wandalen ", From 0130aae45860305526b2603179b45c152cd29394 Mon Sep 17 00:00:00 2001 From: wandalen Date: Tue, 21 May 2024 15:52:29 +0300 Subject: [PATCH 11/44] former_types-v2.1.0 --- Cargo.toml | 2 +- module/core/former_types/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 854b033b75..2819bbf5ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -215,7 +215,7 @@ path = "module/core/former_meta" default-features = false [workspace.dependencies.former_types] -version = "~2.0.0" +version = "~2.1.0" path = "module/core/former_types" default-features = false diff --git a/module/core/former_types/Cargo.toml b/module/core/former_types/Cargo.toml index ab104de2fd..95ca657ed3 100644 --- a/module/core/former_types/Cargo.toml +++ b/module/core/former_types/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "former_types" -version = "2.0.0" +version = "2.1.0" edition = "2021" authors = [ "Kostiantyn Wandalen ", From 7a1531cb11a4cef8310f819518b0d27fff12e235 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 08:22:37 +0300 Subject: [PATCH 12/44] former : refactor parsing --- module/core/former_meta/Cargo.toml | 2 + .../src/derive_former/field_attrs.rs | 179 ++++++++++++++---- .../src/derive_former/struct_attrs.rs | 106 ++++++++--- module/core/former_meta/src/lib.rs | 1 - 4 files changed, 231 insertions(+), 57 deletions(-) diff --git a/module/core/former_meta/Cargo.toml b/module/core/former_meta/Cargo.toml index b2e86a29bb..770817a07f 100644 --- a/module/core/former_meta/Cargo.toml +++ b/module/core/former_meta/Cargo.toml @@ -61,6 +61,8 @@ macro_tools = { workspace = true } # qqq : optimize set of features former_types = { workspace = true, features = [ "types_component_assign" ] } # qqq : optimize set of features iter_tools = { workspace = true } convert_case = { version = "0.6.0", default-features = false, optional = true, features = [] } +const_format = { version = "0.2.32" } +# zzz : reexport const_format [dev-dependencies] test_tools = { workspace = true, features = [ "full" ] } 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 bb7b776b50..3486a8dc4e 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -1,6 +1,7 @@ use super::*; use macro_tools::{ attr, Result }; +use former_types::{ ComponentAssign }; /// /// Attributes of a field. @@ -15,20 +16,96 @@ pub struct FieldAttributes pub subform_entry : Option< AttributeSubformEntrySetter >, } +impl< IntoT > ComponentAssign< AttributeConfig, IntoT > for FieldAttributes +where + IntoT : Into< AttributeConfig >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.config = Some( component.into() ); + } +} + +impl< IntoT > ComponentAssign< AttributeScalarSetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeScalarSetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.scalar = Some( component.into() ); + } +} + +impl< IntoT > ComponentAssign< AttributeSubformScalarSetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeSubformScalarSetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.subform_scalar = Some( component.into() ); + } +} + +impl< IntoT > ComponentAssign< AttributeSubformCollectionSetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeSubformCollectionSetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.subform_collection = Some( component.into() ); + } +} + +impl< IntoT > ComponentAssign< AttributeSubformEntrySetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeSubformEntrySetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.subform_entry = Some( component.into() ); + } +} + impl FieldAttributes { + pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { - let mut config = None; - let mut scalar = None; - let mut subform_scalar = None; - let mut subform_collection = None; - let mut subform_entry = None; + let mut result = Self::default(); + // let known_attributes = "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`."; + let known_attributes = const_format::concatcp! + ( + "Known attirbutes are : ", + "debug", + ", ", AttributeConfig::KEYWORD, + ", ", AttributeScalarSetter::KEYWORD, + ", ", AttributeSubformScalarSetter::KEYWORD, + ", ", AttributeSubformCollectionSetter::KEYWORD, + ", ", AttributeSubformEntrySetter::KEYWORD, + ".", + ); + + let error = | attr : &syn::Attribute | -> syn::Error + { + syn_err! + ( + attr, + "Expects an attribute of format `#[ attribute( val ) ]`\n {known_attributes}\n But got:\n `{}`", + qt!{ #attr } + ) + }; for attr in attrs { - let key_ident = attr.path().get_ident() - .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( val ) ], but got:\n {}", qt!{ #attr } ) )?; + + // return Err( error( attr ) ); + + let key_ident = attr.path().get_ident().ok_or_else( || error( attr ) )?; let key_str = format!( "{}", key_ident ); if attr::is_standard( &key_str ) @@ -38,37 +115,75 @@ impl FieldAttributes match key_str.as_ref() { - AttributeConfig::KEYWORD => - { - config.replace( AttributeConfig::from_meta( &attr )? ); - } - AttributeScalarSetter::KEYWORD => - { - scalar.replace( AttributeScalarSetter::from_meta( &attr )? ); - } - AttributeSubformScalarSetter::KEYWORD => - { - subform_scalar.replace( AttributeSubformScalarSetter::from_meta( &attr )? ); - } - AttributeSubformCollectionSetter::KEYWORD => - { - subform_collection.replace( AttributeSubformCollectionSetter::from_meta( &attr )? ); - } - AttributeSubformEntrySetter::KEYWORD => - { - subform_entry.replace( AttributeSubformEntrySetter::from_meta( &attr )? ); - } - _ => - { - return Err( syn_err!( attr, "Unknown field attribute {}", qt!{ #attr } ) ); - } + AttributeConfig::KEYWORD => result.assign( AttributeConfig::from_meta( attr )? ), + AttributeScalarSetter::KEYWORD => result.assign( AttributeScalarSetter::from_meta( attr )? ), + AttributeSubformScalarSetter::KEYWORD => result.assign( AttributeSubformScalarSetter::from_meta( attr )? ), + AttributeSubformCollectionSetter::KEYWORD => result.assign( AttributeSubformCollectionSetter::from_meta( attr )? ), + AttributeSubformEntrySetter::KEYWORD => result.assign( AttributeSubformEntrySetter::from_meta( attr )? ), + "debug" => {} + _ => return Err( error( attr ) ), } } - Ok( FieldAttributes { config, scalar, subform_scalar, subform_collection, subform_entry } ) + Ok( result ) } + } +// impl FieldAttributes +// { +// pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > +// { +// let mut config = None; +// let mut scalar = None; +// let mut subform_scalar = None; +// let mut subform_collection = None; +// let mut subform_entry = None; +// +// for attr in attrs +// { +// let key_ident = attr.path().get_ident() +// .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( val ) ], but got:\n {}", qt!{ #attr } ) )?; +// let key_str = format!( "{}", key_ident ); +// +// if attr::is_standard( &key_str ) +// { +// continue; +// } +// +// match key_str.as_ref() +// { +// AttributeConfig::KEYWORD => +// { +// config.replace( AttributeConfig::from_meta( &attr )? ); +// } +// AttributeScalarSetter::KEYWORD => +// { +// scalar.replace( AttributeScalarSetter::from_meta( &attr )? ); +// } +// AttributeSubformScalarSetter::KEYWORD => +// { +// subform_scalar.replace( AttributeSubformScalarSetter::from_meta( &attr )? ); +// } +// AttributeSubformCollectionSetter::KEYWORD => +// { +// subform_collection.replace( AttributeSubformCollectionSetter::from_meta( &attr )? ); +// } +// AttributeSubformEntrySetter::KEYWORD => +// { +// subform_entry.replace( AttributeSubformEntrySetter::from_meta( &attr )? ); +// } +// _ => +// { +// return Err( syn_err!( attr, "Unknown field attribute {}", qt!{ #attr } ) ); +// } +// } +// } +// +// Ok( FieldAttributes { config, scalar, subform_scalar, subform_collection, subform_entry } ) +// } +// } + /// /// Attribute to hold configuration information about the field such as default value. /// 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 c2b6148f4e..1b1bd07090 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -6,6 +6,8 @@ use former_types::{ ComponentAssign }; /// /// Attributes of a struct. /// + +#[ derive( Debug, Default ) ] pub struct StructAttributes { pub storage_fields : Option< AttributeStorageFields >, @@ -17,6 +19,7 @@ impl< IntoT > ComponentAssign< AttributeStorageFields, IntoT > for StructAttribu where IntoT : Into< AttributeStorageFields >, { + #[ inline( always ) ] fn assign( &mut self, component : IntoT ) { self.storage_fields = Some( component.into() ); @@ -27,6 +30,7 @@ impl< IntoT > ComponentAssign< AttributeMutator, IntoT > for StructAttributes where IntoT : Into< AttributeMutator >, { + #[ inline( always ) ] fn assign( &mut self, component : IntoT ) { self.mutator = component.into(); @@ -37,6 +41,7 @@ impl< IntoT > ComponentAssign< AttributePerform, IntoT > for StructAttributes where IntoT : Into< AttributePerform >, { + #[ inline( always ) ] fn assign( &mut self, component : IntoT ) { self.perform = Some( component.into() ); @@ -48,14 +53,35 @@ impl StructAttributes pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { - let mut storage_fields = None; - let mut mutator : AttributeMutator = Default::default(); - let mut perform = None; + let mut result = Self::default(); + // let known_attributes = "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`."; + let known_attributes = const_format::concatcp! + ( + "Known attirbutes are : ", + "debug", + ", ", AttributeStorageFields::KEYWORD, + ", ", AttributeMutator::KEYWORD, + ", ", AttributePerform::KEYWORD, + ".", + ); + + let error = | attr : &syn::Attribute | -> syn::Error + { + syn_err! + ( + attr, + "Expects an attribute of format `#[ attribute( val ) ]`\n {known_attributes}\n But got:\n `{}`", + qt!{ #attr } + ) + }; for attr in attrs { + + // return Err( error( attr ) ); + let key_ident = attr.path().get_ident() - .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( val ) ], but got:\n {}", qt!{ #attr } ) )?; + .ok_or_else( || error( attr ) )?; let key_str = format!( "{}", key_ident ); if attr::is_standard( &key_str ) @@ -65,31 +91,61 @@ impl StructAttributes match key_str.as_ref() { - AttributeStorageFields::KEYWORD => - { - storage_fields.replace( AttributeStorageFields::from_meta( attr )? ); - } - AttributeMutator::KEYWORD => - { - mutator = AttributeMutator::from_meta( attr )?; - } - AttributePerform::KEYWORD => - { - perform.replace( AttributePerform::from_meta( attr )? ); - } - "debug" => - { - } - _ => - { - return Err( syn_err!( attr, "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`.\nUnknown structure attribute : {}", qt!{ #attr } ) ); - } + AttributeStorageFields::KEYWORD => result.assign( AttributeStorageFields::from_meta( attr )? ), + AttributeMutator::KEYWORD => result.assign( AttributeMutator::from_meta( attr )? ), + AttributePerform::KEYWORD => result.assign( AttributePerform::from_meta( attr )? ), + "debug" => {} + _ => return Err( error( attr ) ), } } - Ok( StructAttributes { perform, storage_fields, mutator } ) + Ok( result ) } +// pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > +// { +// let mut storage_fields = None; +// let mut mutator : AttributeMutator = Default::default(); +// let mut perform = None; +// +// for attr in attrs +// { +// let key_ident = attr.path().get_ident() +// .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( val ) ], but got:\n {}", qt!{ #attr } ) )?; +// let key_str = format!( "{}", key_ident ); +// +// if attr::is_standard( &key_str ) +// { +// continue; +// } +// +// match key_str.as_ref() +// { +// AttributeStorageFields::KEYWORD => +// { +// storage_fields.replace( AttributeStorageFields::from_meta( attr )? ); +// } +// AttributeMutator::KEYWORD => +// { +// mutator = AttributeMutator::from_meta( attr )?; +// } +// AttributePerform::KEYWORD => +// { +// perform.replace( AttributePerform::from_meta( attr )? ); +// } +// "debug" => +// { +// } +// _ => +// { +// return Err( syn_err!( attr, "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`.\nUnknown structure attribute : {}", qt!{ #attr } ) ); +// } +// } +// } +// +// Ok( StructAttributes { perform, storage_fields, mutator } ) +// } + /// /// Generate parts, used for generating `perform()`` method. /// @@ -177,6 +233,7 @@ impl StructAttributes /// `#[ storage_fields( a : i32, b : Option< String > ) ]` /// +#[ derive( Debug, Default ) ] pub struct AttributeStorageFields { pub fields : syn::punctuated::Punctuated< syn::Field, syn::token::Comma >, @@ -320,6 +377,7 @@ impl syn::parse::Parse for AttributeMutator /// `#[ perform( fn after1< 'a >() -> Option< &'a str > ) ]` /// +#[ derive( Debug ) ] pub struct AttributePerform { pub signature : syn::Signature, diff --git a/module/core/former_meta/src/lib.rs b/module/core/former_meta/src/lib.rs index f8fbcaef86..da2133f319 100644 --- a/module/core/former_meta/src/lib.rs +++ b/module/core/former_meta/src/lib.rs @@ -613,4 +613,3 @@ pub fn from_components( input : proc_macro::TokenStream ) -> proc_macro::TokenSt Err( err ) => err.to_compile_error().into(), } } - From f2cabae29fb667ed5d8d374cb540a9ee27dabb2b Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 08:25:38 +0300 Subject: [PATCH 13/44] former : refactor parsing --- .../src/derive_former/field_attrs.rs | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) 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 3486a8dc4e..2501c0c583 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -7,6 +7,7 @@ use former_types::{ ComponentAssign }; /// Attributes of a field. /// +#[ derive( Debug, Default ) ] pub struct FieldAttributes { pub config : Option< AttributeConfig >, @@ -16,17 +17,6 @@ pub struct FieldAttributes pub subform_entry : Option< AttributeSubformEntrySetter >, } -impl< IntoT > ComponentAssign< AttributeConfig, IntoT > for FieldAttributes -where - IntoT : Into< AttributeConfig >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.config = Some( component.into() ); - } -} - impl< IntoT > ComponentAssign< AttributeScalarSetter, IntoT > for FieldAttributes where IntoT : Into< AttributeScalarSetter >, @@ -190,6 +180,7 @@ impl FieldAttributes /// `#[ default( 13 ) ]` /// +#[ derive( Debug, Default ) ] pub struct AttributeConfig { @@ -264,6 +255,17 @@ impl syn::parse::Parse for AttributeConfig } } +impl< IntoT > ComponentAssign< AttributeConfig, IntoT > for FieldAttributes +where + IntoT : Into< AttributeConfig >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.config = Some( component.into() ); + } +} + /// /// Attribute to enable/disable scalar setter generation. /// @@ -276,6 +278,7 @@ impl syn::parse::Parse for AttributeConfig /// ``` /// +#[ derive( Debug, Default ) ] pub struct AttributeScalarSetter { /// Optional identifier for naming the setter. @@ -384,6 +387,7 @@ impl syn::parse::Parse for AttributeScalarSetter /// ``` /// +#[ derive( Debug, Default ) ] pub struct AttributeSubformScalarSetter { /// Optional identifier for naming the setter. @@ -493,6 +497,7 @@ impl syn::parse::Parse for AttributeSubformScalarSetter /// ``` /// +#[ derive( Debug, Default ) ] pub struct AttributeSubformCollectionSetter { /// Optional identifier for naming the setter. @@ -614,6 +619,7 @@ impl syn::parse::Parse for AttributeSubformCollectionSetter /// mame = field_name /// ``` +#[ derive( Debug, Default ) ] pub struct AttributeSubformEntrySetter { /// An optional identifier that names the setter. It is parsed from inputs From 209b0713510eb26653a66ee7dcb9088bd1d5b4a7 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 08:28:51 +0300 Subject: [PATCH 14/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) 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 2501c0c583..c6918d95f3 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -17,50 +17,6 @@ pub struct FieldAttributes pub subform_entry : Option< AttributeSubformEntrySetter >, } -impl< IntoT > ComponentAssign< AttributeScalarSetter, IntoT > for FieldAttributes -where - IntoT : Into< AttributeScalarSetter >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.scalar = Some( component.into() ); - } -} - -impl< IntoT > ComponentAssign< AttributeSubformScalarSetter, IntoT > for FieldAttributes -where - IntoT : Into< AttributeSubformScalarSetter >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.subform_scalar = Some( component.into() ); - } -} - -impl< IntoT > ComponentAssign< AttributeSubformCollectionSetter, IntoT > for FieldAttributes -where - IntoT : Into< AttributeSubformCollectionSetter >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.subform_collection = Some( component.into() ); - } -} - -impl< IntoT > ComponentAssign< AttributeSubformEntrySetter, IntoT > for FieldAttributes -where - IntoT : Into< AttributeSubformEntrySetter >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.subform_entry = Some( component.into() ); - } -} - impl FieldAttributes { @@ -212,6 +168,17 @@ impl AttributeConfig } +impl< IntoT > ComponentAssign< AttributeConfig, IntoT > for FieldAttributes +where + IntoT : Into< AttributeConfig >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.config = Some( component.into() ); + } +} + impl syn::parse::Parse for AttributeConfig { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -255,17 +222,6 @@ impl syn::parse::Parse for AttributeConfig } } -impl< IntoT > ComponentAssign< AttributeConfig, IntoT > for FieldAttributes -where - IntoT : Into< AttributeConfig >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.config = Some( component.into() ); - } -} - /// /// Attribute to enable/disable scalar setter generation. /// @@ -320,6 +276,17 @@ impl AttributeScalarSetter } +impl< IntoT > ComponentAssign< AttributeScalarSetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeScalarSetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.scalar = Some( component.into() ); + } +} + impl syn::parse::Parse for AttributeScalarSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -429,6 +396,17 @@ impl AttributeSubformScalarSetter } +impl< IntoT > ComponentAssign< AttributeSubformScalarSetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeSubformScalarSetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.subform_scalar = Some( component.into() ); + } +} + impl syn::parse::Parse for AttributeSubformScalarSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -540,6 +518,17 @@ impl AttributeSubformCollectionSetter } +impl< IntoT > ComponentAssign< AttributeSubformCollectionSetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeSubformCollectionSetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.subform_collection = Some( component.into() ); + } +} + impl syn::parse::Parse for AttributeSubformCollectionSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -662,6 +651,17 @@ impl AttributeSubformEntrySetter } +impl< IntoT > ComponentAssign< AttributeSubformEntrySetter, IntoT > for FieldAttributes +where + IntoT : Into< AttributeSubformEntrySetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.subform_entry = Some( component.into() ); + } +} + impl syn::parse::Parse for AttributeSubformEntrySetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > From 5942deb26f6da9d5bc5baa7cdafe77a13764b1a7 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 08:38:10 +0300 Subject: [PATCH 15/44] former : refactoring parsing --- .../former_meta/src/derive_former/struct_attrs.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) 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 1b1bd07090..f3116fefc7 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -3,6 +3,17 @@ use super::*; use macro_tools::{ attr, Result }; use former_types::{ ComponentAssign }; +pub trait AttributeComponent +where + Self : Sized, +{ + + const KEYWORD : &'static str; + + fn from_meta( attr : &syn::Attribute ) -> Result< Self >; + +} + /// /// Attributes of a struct. /// From 4eb4af93cf6f441c6deec302129f408f7cb02545 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 08:49:10 +0300 Subject: [PATCH 16/44] former : refactoring and documentation --- .../src/derive_former/field_attrs.rs | 2 + .../src/derive_former/struct_attrs.rs | 116 ++++++++++++------ module/core/former_meta/src/lib.rs | 13 +- 3 files changed, 87 insertions(+), 44 deletions(-) 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 c6918d95f3..3739227ab6 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -3,6 +3,8 @@ use super::*; use macro_tools::{ attr, Result }; use former_types::{ ComponentAssign }; +// xxx : document + /// /// Attributes of a field. /// 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 f3116fefc7..b8fd13c23d 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -3,60 +3,68 @@ use super::*; use macro_tools::{ attr, Result }; use former_types::{ ComponentAssign }; +/// Trait for components that can be constructed from a meta attribute. +/// +/// The `AttributeComponent` trait defines the interface for components that can be created +/// from a `syn::Attribute` meta item. Implementors of this trait are required to define +/// a constant `KEYWORD` that identifies the type of the component and a method `from_meta` +/// that handles the construction of the component from the given attribute. +/// +/// # Example +/// +/// ```ignore +/// struct MyComponent; +/// +/// impl AttributeComponent for MyComponent { +/// const KEYWORD: &'static str = "my_component"; +/// +/// fn from_meta(attr: &syn::Attribute) -> Result { +/// // Parsing logic here +/// } +/// } +/// ``` pub trait AttributeComponent where Self : Sized, { - + /// The keyword that identifies the component. + /// + /// This constant is used to match the attribute to the corresponding component. + /// Each implementor of this trait must provide a unique keyword for its type. const KEYWORD : &'static str; + /// Constructs the component from the given meta attribute. + /// + /// This method is responsible for parsing the provided `syn::Attribute` and + /// returning an instance of the component. If the attribute cannot be parsed + /// into the component, an error should be returned. + /// + /// # Parameters + /// + /// - `attr` : A reference to the `syn::Attribute` from which the component is to be constructed. + /// + /// # Returns + /// + /// A `Result` containing the constructed component if successful, or an error if the parsing fails. fn from_meta( attr : &syn::Attribute ) -> Result< Self >; - } -/// -/// Attributes of a struct. -/// +/// Represents the attributes of a struct, including storage fields, mutator, and perform attributes. #[ derive( Debug, Default ) ] pub struct StructAttributes { + /// Optional attribute for storage-specific fields. + /// This field is used to specify fields that should be part of the storage but not the final formed structure. pub storage_fields : Option< AttributeStorageFields >, - pub mutator : AttributeMutator, - pub perform : Option< AttributePerform >, -} - -impl< IntoT > ComponentAssign< AttributeStorageFields, IntoT > for StructAttributes -where - IntoT : Into< AttributeStorageFields >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.storage_fields = Some( component.into() ); - } -} -impl< IntoT > ComponentAssign< AttributeMutator, IntoT > for StructAttributes -where - IntoT : Into< AttributeMutator >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.mutator = component.into(); - } -} + /// Attribute for customizing the mutation process in a forming operation. + /// The `mutator` attribute allows for specifying whether a custom mutator should be used or if a sketch should be provided as a hint. + pub mutator : AttributeMutator, -impl< IntoT > ComponentAssign< AttributePerform, IntoT > for StructAttributes -where - IntoT : Into< AttributePerform >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.perform = Some( component.into() ); - } + /// Optional attribute for specifying a method to call after forming. + /// This attribute can hold information about a method that should be invoked after the form operation is complete. + pub perform : Option< AttributePerform >, } impl StructAttributes @@ -270,6 +278,17 @@ impl AttributeStorageFields } +impl< IntoT > ComponentAssign< AttributeStorageFields, IntoT > for StructAttributes +where + IntoT : Into< AttributeStorageFields >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.storage_fields = Some( component.into() ); + } +} + impl syn::parse::Parse for AttributeStorageFields { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -329,6 +348,16 @@ impl AttributeMutator } +impl< IntoT > ComponentAssign< AttributeMutator, IntoT > for StructAttributes +where + IntoT : Into< AttributeMutator >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.mutator = component.into(); + } +} impl syn::parse::Parse for AttributeMutator { @@ -414,6 +443,17 @@ impl AttributePerform } +impl< IntoT > ComponentAssign< AttributePerform, IntoT > for StructAttributes +where + IntoT : Into< AttributePerform >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.perform = Some( component.into() ); + } +} + impl syn::parse::Parse for AttributePerform { fn parse( input : syn::parse::ParseStream< '_ > ) -> Result< Self > diff --git a/module/core/former_meta/src/lib.rs b/module/core/former_meta/src/lib.rs index da2133f319..e9d2e50279 100644 --- a/module/core/former_meta/src/lib.rs +++ b/module/core/former_meta/src/lib.rs @@ -3,8 +3,14 @@ #![ doc( html_root_url = "https://docs.rs/former_derive_meta/latest/former_derive_meta/" ) ] #![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/", "Readme.md" ) ) ] +#[ allow( unused_imports ) ] +use macro_tools::prelude::*; + +#[ cfg( feature = "derive_former" ) ] +mod derive_former; + #[ cfg( feature = "enabled" ) ] -// #[ cfg( feature = "derive_component_from" ) ] +#[ cfg( feature = "derive_components" ) ] mod component { @@ -26,11 +32,6 @@ mod component } -#[ allow( unused_imports ) ] -use macro_tools::prelude::*; -#[ cfg( feature = "derive_former" ) ] -mod derive_former; - /// Derive macro for generating a `Former` struct, applying a Builder Pattern to the annotated struct. /// /// This macro simplifies the construction of complex objects by automatically generating a builder (former) for From aa775b5b25a8493024cab20748f655f1599720d8 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 09:29:17 +0300 Subject: [PATCH 17/44] macro_tools : fixing mess --- .../src/derive_former/struct_attrs.rs | 12 +- module/core/macro_tools/src/attr.rs | 91 ++++++---- module/core/macro_tools/src/equation.rs | 160 ++++++++++++++++++ module/core/macro_tools/src/lib.rs | 8 +- module/core/macro_tools/src/tokens.rs | 77 --------- module/core/macro_tools/tests/inc/attr.rs | 53 ------ .../core/macro_tools/tests/inc/attr_test.rs | 60 +++++++ .../tests/inc/{basic.rs => basic_test.rs} | 59 ------- .../tests/inc/{derive.rs => derive_test.rs} | 0 .../tests/inc/{drop.rs => drop_test.rs} | 0 .../macro_tools/tests/inc/equation_test.rs | 108 ++++++++++++ .../{generic_args.rs => generic_args_test.rs} | 0 ...neric_params.rs => generic_params_test.rs} | 0 .../{item_struct.rs => item_struct_test.rs} | 0 .../tests/inc/{item.rs => item_test.rs} | 0 module/core/macro_tools/tests/inc/mod.rs | 30 ++-- .../tests/inc/{phantom.rs => phantom_test.rs} | 0 .../inc/{quantifier.rs => quantifier_test.rs} | 0 .../tests/inc/{syntax.rs => syntax_test.rs} | 0 .../tests/inc/{tokens.rs => tokens_test.rs} | 16 -- .../tests/inc/{typ.rs => typ_Test.rs} | 0 21 files changed, 414 insertions(+), 260 deletions(-) create mode 100644 module/core/macro_tools/src/equation.rs delete mode 100644 module/core/macro_tools/tests/inc/attr.rs create mode 100644 module/core/macro_tools/tests/inc/attr_test.rs rename module/core/macro_tools/tests/inc/{basic.rs => basic_test.rs} (89%) rename module/core/macro_tools/tests/inc/{derive.rs => derive_test.rs} (100%) rename module/core/macro_tools/tests/inc/{drop.rs => drop_test.rs} (100%) create mode 100644 module/core/macro_tools/tests/inc/equation_test.rs rename module/core/macro_tools/tests/inc/{generic_args.rs => generic_args_test.rs} (100%) rename module/core/macro_tools/tests/inc/{generic_params.rs => generic_params_test.rs} (100%) rename module/core/macro_tools/tests/inc/{item_struct.rs => item_struct_test.rs} (100%) rename module/core/macro_tools/tests/inc/{item.rs => item_test.rs} (100%) rename module/core/macro_tools/tests/inc/{phantom.rs => phantom_test.rs} (100%) rename module/core/macro_tools/tests/inc/{quantifier.rs => quantifier_test.rs} (100%) rename module/core/macro_tools/tests/inc/{syntax.rs => syntax_test.rs} (100%) rename module/core/macro_tools/tests/inc/{tokens.rs => tokens_test.rs} (51%) rename module/core/macro_tools/tests/inc/{typ.rs => typ_Test.rs} (100%) 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 b8fd13c23d..750d9fb3b9 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -258,12 +258,12 @@ pub struct AttributeStorageFields pub fields : syn::punctuated::Punctuated< syn::Field, syn::token::Comma >, } -impl AttributeStorageFields +impl AttributeComponent for AttributeStorageFields { const KEYWORD : &'static str = "storage_fields"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta { @@ -326,11 +326,11 @@ pub struct AttributeMutator pub hint : bool, } -impl AttributeMutator +impl AttributeComponent for AttributeMutator { const KEYWORD : &'static str = "mutator"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta { @@ -423,11 +423,11 @@ pub struct AttributePerform pub signature : syn::Signature, } -impl AttributePerform +impl AttributeComponent for AttributePerform { const KEYWORD : &'static str = "perform"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta diff --git a/module/core/macro_tools/src/attr.rs b/module/core/macro_tools/src/attr.rs index b39c9b703a..78c05d7de4 100644 --- a/module/core/macro_tools/src/attr.rs +++ b/module/core/macro_tools/src/attr.rs @@ -7,34 +7,6 @@ pub( crate ) mod private { use crate::*; - /// - /// For attribute like `#[former( default = 31 ) ]` return key `default` and value `31`, - /// as well as syn::Meta as the last element of result tuple. - /// - /// ### Basic use-case. - /// - /// ```rust - /// use macro_tools::exposed::*; - /// let attr : syn::Attribute = syn::parse_quote!( #[ former( default = 31 ) ] ); - /// // tree_print!( attr ); - /// let got = equation( &attr ).unwrap(); - /// assert_eq!( code_to_str!( got ), "default = 31".to_string() ); - /// ``` - - pub fn equation( attr : &syn::Attribute ) -> Result< tokens::Equation > - { - let meta = &attr.meta; - return match meta - { - syn::Meta::List( ref meta_list ) => - { - let eq : tokens::Equation = syn::parse2( meta_list.tokens.clone() )?; - Ok( eq ) - } - _ => return Err( syn::Error::new( attr.span(), "Unknown format of attribute, expected syn::Meta::List( meta_list )" ) ), - }; - } - /// Checks if the given iterator of attributes contains an attribute named `debug`. /// /// This function iterates over an input sequence of `syn::Attribute`, typically associated with a struct, @@ -373,6 +345,57 @@ pub( crate ) mod private // } // } + /// Trait for components that can be constructed from a meta attribute. + /// + /// The `AttributeComponent` trait defines the interface for components that can be created + /// from a `syn::Attribute` meta item. Implementors of this trait are required to define + /// a constant `KEYWORD` that identifies the type of the component and a method `from_meta` + /// that handles the construction of the component from the given attribute. + /// + /// # Example + /// + /// ```rust + /// use macro_tools::{ AttributeComponent, Result }; + /// + /// struct MyComponent; + /// + /// impl AttributeComponent for MyComponent + /// { + /// const KEYWORD : &'static str = "my_component"; + /// + /// fn from_meta( attr : &syn::Attribute ) -> Result< Self > + /// { + /// // Parsing logic here + /// Ok( MyComponent ) + /// } + /// } + /// ``` + pub trait AttributeComponent + where + Self : Sized, + { + /// The keyword that identifies the component. + /// + /// This constant is used to match the attribute to the corresponding component. + /// Each implementor of this trait must provide a unique keyword for its type. + const KEYWORD : &'static str; + + /// Constructs the component from the given meta attribute. + /// + /// This method is responsible for parsing the provided `syn::Attribute` and + /// returning an instance of the component. If the attribute cannot be parsed + /// into the component, an error should be returned. + /// + /// # Parameters + /// + /// - `attr` : A reference to the `syn::Attribute` from which the component is to be constructed. + /// + /// # Returns + /// + /// A `Result` containing the constructed component if successful, or an error if the parsing fails. + fn from_meta( attr : &syn::Attribute ) -> Result< Self >; + } + } #[ doc( inline ) ] @@ -385,6 +408,14 @@ pub mod protected #[ doc( inline ) ] #[ allow( unused_imports ) ] pub use super::orphan::*; + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::private:: + { + // equation, + has_debug, + is_standard, + }; } /// Orphan namespace of the module. @@ -406,12 +437,10 @@ pub mod exposed #[ allow( unused_imports ) ] pub use super::private:: { - equation, - has_debug, - is_standard, AttributesInner, AttributesOuter, // AttributedIdent, + AttributeComponent, }; } diff --git a/module/core/macro_tools/src/equation.rs b/module/core/macro_tools/src/equation.rs new file mode 100644 index 0000000000..36bab1ccab --- /dev/null +++ b/module/core/macro_tools/src/equation.rs @@ -0,0 +1,160 @@ +//! +//! Attributes analyzys and manipulation. +//! + +/// Internal namespace. +pub( crate ) mod private +{ + use crate::*; + + /// Represents an equation parsed from a procedural macro input. + /// + /// This struct models an equation consisting of a left-hand side, an operator, + /// and a right-hand side. The `Equation` is typically constructed during the + /// parsing process of macro input, where the `left` and `op` fields are expected + /// to be syntactically represented by `syn::Path` and `syn::BinOp` respectively, + /// indicating the variable and operation involved. The `right` field is a + /// `proc_macro2::TokenStream`, which can represent more complex expressions + /// including, but not limited to, literals, function calls, or further operations. + /// + /// # Fields + /// - `left`: The left-hand side of the equation, represented as a path. + /// This could be a variable or a more complex path in the code being + /// processed by the macro. + /// + /// - `op`: The binary operator used in the equation, such as addition, + /// subtraction, multiplication, etc. + /// + /// - `right`: The right-hand side of the equation. Given the potential + /// complexity of expressions on this side, it is represented as a + /// `proc_macro2::TokenStream` to accommodate any valid Rust expression. + /// + /// # Examples + /// + /// Parsing an equation from macro input: + /// + /// ```rust + /// use macro_tools::equation; + /// let got : equation::Equation = syn::parse_quote!( default = 31 ); + /// macro_tools::tree_print!( got ); + /// assert_eq!( macro_tools::code_to_str!( got ), "default = 31".to_string() ); + /// ``` + #[ derive( Debug ) ] + pub struct Equation + { + /// The LHS of the equation, represented by a syntactic path. + pub left : syn::Path, + // /// The binary operator (e.g., +, -, *, /) of the equation. + // pub op : syn::BinOp, + /// Equality token. + pub op : syn::Token![ = ], + /// The RHS of the equation, capable of holding complex expressions. + pub right : proc_macro2::TokenStream, + } + + impl syn::parse::Parse for Equation + { + fn parse( input : syn::parse::ParseStream< '_ > ) -> Result< Self > + { + let left : syn::Path = input.parse()?; + let op : syn::Token![ = ] = input.parse()?; + let right : proc_macro2::TokenStream = input.parse()?; + Ok( Equation { left, op, right } ) + } + } + + impl quote::ToTokens for Equation + { + fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) + { + self.left.to_tokens( tokens ); + self.op.to_tokens( tokens ); + self.right.to_tokens( tokens ); + } + } + + // impl core::fmt::Display for Equation + // { + // fn fmt( &self, f : &mut core::fmt::Formatter< '_ > ) -> core::fmt::Result + // { + // write!( f, "{}", self.left.to_string() ); + // write!( f, "{}", self.op.to_string() ); + // write!( f, "{}", self.right.to_string() ) + // } + // } + + /// + /// For attribute like `#[former( default = 31 ) ]` return key `default` and value `31`, + /// as well as syn::Meta as the last element of result tuple. + /// + /// ### Basic use-case. + /// + /// ```rust + /// use macro_tools::equation; + /// let attr : syn::Attribute = syn::parse_quote!( #[ former( default = 31 ) ] ); + /// // tree_print!( attr ); + /// let got = equation::from_meta( &attr ).unwrap(); + /// assert_eq!( macro_tools::code_to_str!( got ), "default = 31".to_string() ); + /// ``` + + pub fn from_meta( attr : &syn::Attribute ) -> Result< Equation > + { + let meta = &attr.meta; + return match meta + { + syn::Meta::List( ref meta_list ) => + { + let eq : Equation = syn::parse2( meta_list.tokens.clone() )?; + Ok( eq ) + } + _ => return Err( syn::Error::new( attr.span(), "Unknown format of attribute, expected syn::Meta::List( meta_list )" ) ), + }; + } + +} + +#[ doc( inline ) ] +#[ allow( unused_imports ) ] +pub use protected::*; + +/// Protected namespace of the module. +pub mod protected +{ + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::orphan::*; + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::private:: + { + from_meta, + }; +} + +/// Orphan namespace of the module. +pub mod orphan +{ + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::exposed::*; +} + +/// Exposed namespace of the module. +pub mod exposed +{ + pub use super::protected as equation; + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::prelude::*; + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::private:: + { + Equation, + }; +} + +/// Prelude to use essentials: `use my_module::prelude::*`. +pub mod prelude +{ +} diff --git a/module/core/macro_tools/src/lib.rs b/module/core/macro_tools/src/lib.rs index 67635b450b..fe0ee3655f 100644 --- a/module/core/macro_tools/src/lib.rs +++ b/module/core/macro_tools/src/lib.rs @@ -31,7 +31,7 @@ mod file pub mod derive; pub mod diag; pub mod drop; - // pub mod generic_analyze; + pub mod equation; pub mod generic_args; pub mod generic_params; pub mod item; @@ -83,7 +83,7 @@ pub mod protected derive::orphan::*, diag::orphan::*, drop::orphan::*, - // generic_analyze::orphan::*, + equation::orphan::*, generic_args::orphan::*, generic_params::orphan::*, item::orphan::*, @@ -138,7 +138,7 @@ pub mod exposed derive::orphan::*, diag::exposed::*, drop::exposed::*, - // generic_analyze::exposed::*, + equation::exposed::*, generic_args::exposed::*, generic_params::exposed::*, item::exposed::*, @@ -208,7 +208,7 @@ pub mod prelude derive::orphan::*, diag::prelude::*, drop::prelude::*, - // generic_analyze::prelude::*, + equation::prelude::*, generic_args::prelude::*, generic_params::prelude::*, item::prelude::*, diff --git a/module/core/macro_tools/src/tokens.rs b/module/core/macro_tools/src/tokens.rs index 35c866d2ac..7a09fc4689 100644 --- a/module/core/macro_tools/src/tokens.rs +++ b/module/core/macro_tools/src/tokens.rs @@ -71,82 +71,6 @@ pub( crate ) mod private } } - /// Represents an equation parsed from a procedural macro input. - /// - /// This struct models an equation consisting of a left-hand side, an operator, - /// and a right-hand side. The `Equation` is typically constructed during the - /// parsing process of macro input, where the `left` and `op` fields are expected - /// to be syntactically represented by `syn::Path` and `syn::BinOp` respectively, - /// indicating the variable and operation involved. The `right` field is a - /// `proc_macro2::TokenStream`, which can represent more complex expressions - /// including, but not limited to, literals, function calls, or further operations. - /// - /// # Fields - /// - `left`: The left-hand side of the equation, represented as a path. - /// This could be a variable or a more complex path in the code being - /// processed by the macro. - /// - /// - `op`: The binary operator used in the equation, such as addition, - /// subtraction, multiplication, etc. - /// - /// - `right`: The right-hand side of the equation. Given the potential - /// complexity of expressions on this side, it is represented as a - /// `proc_macro2::TokenStream` to accommodate any valid Rust expression. - /// - /// # Examples - /// - /// Parsing an equation from macro input: - /// - /// ```rust - /// use macro_tools::exposed::*; - /// let got : tokens::Equation = syn::parse_quote!( default = 31 ); - /// tree_print!( got ); - /// assert_eq!( code_to_str!( got ), "default = 31".to_string() ); - /// ``` - #[ derive( Debug ) ] - pub struct Equation - { - /// The LHS of the equation, represented by a syntactic path. - pub left : syn::Path, - // /// The binary operator (e.g., +, -, *, /) of the equation. - // pub op : syn::BinOp, - /// Equality token. - pub op : syn::Token![ = ], - /// The RHS of the equation, capable of holding complex expressions. - pub right : proc_macro2::TokenStream, - } - - impl syn::parse::Parse for Equation - { - fn parse( input : syn::parse::ParseStream< '_ > ) -> Result< Self > - { - let left : syn::Path = input.parse()?; - let op : syn::Token![ = ] = input.parse()?; - let right : proc_macro2::TokenStream = input.parse()?; - Ok( Equation { left, op, right } ) - } - } - - impl quote::ToTokens for Equation - { - fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) - { - self.left.to_tokens( tokens ); - self.op.to_tokens( tokens ); - self.right.to_tokens( tokens ); - } - } - - // impl core::fmt::Display for Equation - // { - // fn fmt( &self, f : &mut core::fmt::Formatter< '_ > ) -> core::fmt::Result - // { - // write!( f, "{}", self.left.to_string() ); - // write!( f, "{}", self.op.to_string() ); - // write!( f, "{}", self.right.to_string() ) - // } - // } - } #[ doc( inline ) ] @@ -181,7 +105,6 @@ pub mod exposed pub use super::private:: { Tokens, - Equation, }; } diff --git a/module/core/macro_tools/tests/inc/attr.rs b/module/core/macro_tools/tests/inc/attr.rs deleted file mode 100644 index 6bba6e98fc..0000000000 --- a/module/core/macro_tools/tests/inc/attr.rs +++ /dev/null @@ -1,53 +0,0 @@ - -use super::*; - -// - -#[ test ] -fn parse() -{ - - let attr : syn::Attribute = syn::parse_quote!( #[ default( 31 ) ] ); - tree_print!( attr ); - - let attr : syn::Attribute = syn::parse_quote!( #[ default[ 31 ] ] ); - tree_print!( attr ); - - let attr : syn::Attribute = syn::parse_quote!( #[ former( default = 31 ) ] ); - // tree_print!( attr ); - let got = equation( &attr ).unwrap(); - a_id!( code_to_str!( got ), "default = 31".to_string() ); - a_id!( got.left, syn::parse_quote!( default ) ); - a_id!( got.op, syn::token::Eq::default() ); - a_id!( code_to_str!( got.right ), "31".to_string() ); - -} - -#[ test ] -fn is_standard_standard() -{ - // Test a selection of attributes known to be standard - assert!( is_standard( "cfg" ), "Expected 'cfg' to be a standard attribute." ); - assert!( is_standard( "derive" ), "Expected 'derive' to be a standard attribute." ); - assert!( is_standard( "inline" ), "Expected 'inline' to be a standard attribute." ); - assert!( is_standard( "test" ), "Expected 'test' to be a standard attribute." ); - assert!( is_standard( "doc" ), "Expected 'doc' to be a standard attribute." ); -} - -#[ test ] -fn is_standard_non_standard() -{ - // Test some made-up attributes that should not be standard - assert!( !is_standard( "custom_attr" ), "Expected 'custom_attr' to not be a standard attribute." ); - assert!( !is_standard( "my_attribute" ), "Expected 'my_attribute' to not be a standard attribute." ); - assert!( !is_standard( "special_feature" ), "Expected 'special_feature' to not be a standard attribute." ); -} - -#[ test ] -fn is_standard_edge_cases() -{ - // Test edge cases like empty strings or unusual input - assert!( !is_standard( "" ), "Expected empty string to not be a standard attribute." ); - assert!( !is_standard( " " ), "Expected a single space to not be a standard attribute." ); - assert!( !is_standard( "cfg_attr_extra" ), "Expected 'cfg_attr_extra' to not be a standard attribute." ); -} diff --git a/module/core/macro_tools/tests/inc/attr_test.rs b/module/core/macro_tools/tests/inc/attr_test.rs new file mode 100644 index 0000000000..fd7e507d31 --- /dev/null +++ b/module/core/macro_tools/tests/inc/attr_test.rs @@ -0,0 +1,60 @@ + +use super::*; + +// + +#[ test ] +fn is_standard_standard() +{ + // Test a selection of attributes known to be standard + assert!( attr::is_standard( "cfg" ), "Expected 'cfg' to be a standard attribute." ); + assert!( attr::is_standard( "derive" ), "Expected 'derive' to be a standard attribute." ); + assert!( attr::is_standard( "inline" ), "Expected 'inline' to be a standard attribute." ); + assert!( attr::is_standard( "test" ), "Expected 'test' to be a standard attribute." ); + assert!( attr::is_standard( "doc" ), "Expected 'doc' to be a standard attribute." ); +} + +#[ test ] +fn is_standard_non_standard() +{ + // Test some made-up attributes that should not be standard + assert!( !attr::is_standard( "custom_attr" ), "Expected 'custom_attr' to not be a standard attribute." ); + assert!( !attr::is_standard( "my_attribute" ), "Expected 'my_attribute' to not be a standard attribute." ); + assert!( !attr::is_standard( "special_feature" ), "Expected 'special_feature' to not be a standard attribute." ); +} + +#[ test ] +fn is_standard_edge_cases() +{ + // Test edge cases like empty strings or unusual input + assert!( !attr::is_standard( "" ), "Expected empty string to not be a standard attribute." ); + assert!( !attr::is_standard( " " ), "Expected a single space to not be a standard attribute." ); + assert!( !attr::is_standard( "cfg_attr_extra" ), "Expected 'cfg_attr_extra' to not be a standard attribute." ); +} + +// xxx +// #[ test ] +// fn attribute_component_from_meta() +// { +// // Define a sample attribute +// let got : Attribute = parse_quote!( #[ my_component = "value" ] ); +// +// // Attempt to construct MyComponent from the attribute +// let result = MyComponent::from_meta( &got ); +// +// // Assert that the construction was successful +// assert!( result.is_ok() ); +// } +// +// #[ test ] +// fn attribute_component_attribute() +// { +// // Define a sample invalid attribute +// let got : Attribute = parse_quote!( #[ other_component = "value" ] ); +// +// // Attempt to construct MyComponent from the invalid attribute +// let result = MyComponent::from_meta( &got ); +// +// // Assert that the construction failed +// assert!( result.is_err() ); +// } diff --git a/module/core/macro_tools/tests/inc/basic.rs b/module/core/macro_tools/tests/inc/basic_test.rs similarity index 89% rename from module/core/macro_tools/tests/inc/basic.rs rename to module/core/macro_tools/tests/inc/basic_test.rs index 6b7500c43b..1b08c4ae3a 100644 --- a/module/core/macro_tools/tests/inc/basic.rs +++ b/module/core/macro_tools/tests/inc/basic_test.rs @@ -343,64 +343,6 @@ TokenStream [ } - // - - #[ test ] - fn attr_pair_single_basic() -> Result< () > - { - use syn::spanned::Spanned; - - // test.case( "basic" ); - let input = qt! - { - #[ derive( Former ) ] - pub struct Struct1 - { - #[former( default = 31 ) ] - pub int_1 : i32, - } - }; - - let ast = match syn::parse2::< syn::DeriveInput >( input ) - { - Ok( syntax_tree ) => syntax_tree, - Err( err ) => return Err( err ), - }; - - let fields = match ast.data - { - syn::Data::Struct( ref data_struct ) => match data_struct.fields - { - syn::Fields::Named( ref fields_named ) => - { - &fields_named.named - }, - _ => return Err( syn::Error::new( ast.span(), "Unknown format of data, expected syn::Fields::Named( ref fields_named )" ) ), - }, - _ => return Err( syn::Error::new( ast.span(), "Unknown format of data, expected syn::Data::Struct( ref data_struct )" ) ), - }; - - let attr = fields.first().ok_or_else( || err( "No field" ) )?.attrs.first().ok_or_else( || err( "No attr" ) )?; - - let exp = Equation - { - left : parse_quote!{ default }, - op : parse_quote!{ = }, - right : parse_quote!{ 31 }, - }; - let got = the_module::equation( &attr )?; - a_id!( got.left, exp.left ); - a_id!( format!( "{:?}", got ), format!( "{:?}", exp ) ); - // a_id!( got.right, exp.right ); - - return Ok( () ); - - fn err( src : &str ) -> syn::Error - { - syn::Error::new( proc_macro2::Span::call_site(), src ) - } - } - } // @@ -413,5 +355,4 @@ tests_index! type_optional_container_kind_basic, type_rightmost_basic, type_parameters_basic, - attr_pair_single_basic, } diff --git a/module/core/macro_tools/tests/inc/derive.rs b/module/core/macro_tools/tests/inc/derive_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/derive.rs rename to module/core/macro_tools/tests/inc/derive_test.rs diff --git a/module/core/macro_tools/tests/inc/drop.rs b/module/core/macro_tools/tests/inc/drop_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/drop.rs rename to module/core/macro_tools/tests/inc/drop_test.rs diff --git a/module/core/macro_tools/tests/inc/equation_test.rs b/module/core/macro_tools/tests/inc/equation_test.rs new file mode 100644 index 0000000000..735d8261fc --- /dev/null +++ b/module/core/macro_tools/tests/inc/equation_test.rs @@ -0,0 +1,108 @@ + +use super::*; + +// + +tests_impls! +{ + + #[ test ] + fn equation_test() -> Result< () > + { + use syn::spanned::Spanned; + + // test.case( "basic" ); + let input = qt! + { + #[ derive( Former ) ] + pub struct Struct1 + { + #[former( default = 31 ) ] + pub int_1 : i32, + } + }; + + let ast = match syn::parse2::< syn::DeriveInput >( input ) + { + Ok( syntax_tree ) => syntax_tree, + Err( err ) => return Err( err ), + }; + + let fields = match ast.data + { + syn::Data::Struct( ref data_struct ) => match data_struct.fields + { + syn::Fields::Named( ref fields_named ) => + { + &fields_named.named + }, + _ => return Err( syn::Error::new( ast.span(), "Unknown format of data, expected syn::Fields::Named( ref fields_named )" ) ), + }, + _ => return Err( syn::Error::new( ast.span(), "Unknown format of data, expected syn::Data::Struct( ref data_struct )" ) ), + }; + + let attr = fields.first().ok_or_else( || err( "No field" ) )?.attrs.first().ok_or_else( || err( "No attr" ) )?; + + let exp = equation::Equation + { + left : parse_quote!{ default }, + op : parse_quote!{ = }, + right : parse_quote!{ 31 }, + }; + let got = equation::from_meta( &attr )?; + a_id!( got.left, exp.left ); + a_id!( format!( "{:?}", got ), format!( "{:?}", exp ) ); + // a_id!( got.right, exp.right ); + + return Ok( () ); + + fn err( src : &str ) -> syn::Error + { + syn::Error::new( proc_macro2::Span::call_site(), src ) + } + } + + fn equation_parse_test() + { + + let got : the_module::Equation = syn::parse_quote!( default = 31 ); + tree_print!( got ); + a_id!( code_to_str!( got ), "default = 31".to_string() ); + + a_id!( got.left, syn::parse_quote!( default ) ); + a_id!( got.op, syn::token::Eq::default() ); + a_id!( code_to_str!( got.right ), "31".to_string() ); + + } + + fn equation_from_meta_test() + { + + let attr1 : syn::Attribute = syn::parse_quote!( #[ default( 31 ) ] ); + tree_print!( attr1 ); + + let attr1 : syn::Attribute = syn::parse_quote!( #[ default[ 31 ] ] ); + tree_print!( attr1 ); + + let attr1 : syn::Attribute = syn::parse_quote!( #[ former( default = 31 ) ] ); + // tree_print!( attr1 ); + let got = equation::from_meta( &attr1 ).unwrap(); + a_id!( code_to_str!( got ), "default = 31".to_string() ); + a_id!( got.left, syn::parse_quote!( default ) ); + a_id!( got.op, syn::token::Eq::default() ); + a_id!( code_to_str!( got.right ), "31".to_string() ); + + } + +} + +// + +// + +tests_index! +{ + equation_test, + equation_parse_test, + equation_from_meta_test, +} diff --git a/module/core/macro_tools/tests/inc/generic_args.rs b/module/core/macro_tools/tests/inc/generic_args_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/generic_args.rs rename to module/core/macro_tools/tests/inc/generic_args_test.rs diff --git a/module/core/macro_tools/tests/inc/generic_params.rs b/module/core/macro_tools/tests/inc/generic_params_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/generic_params.rs rename to module/core/macro_tools/tests/inc/generic_params_test.rs diff --git a/module/core/macro_tools/tests/inc/item_struct.rs b/module/core/macro_tools/tests/inc/item_struct_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/item_struct.rs rename to module/core/macro_tools/tests/inc/item_struct_test.rs diff --git a/module/core/macro_tools/tests/inc/item.rs b/module/core/macro_tools/tests/inc/item_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/item.rs rename to module/core/macro_tools/tests/inc/item_test.rs diff --git a/module/core/macro_tools/tests/inc/mod.rs b/module/core/macro_tools/tests/inc/mod.rs index 4968d3f52f..6214a91f3e 100644 --- a/module/core/macro_tools/tests/inc/mod.rs +++ b/module/core/macro_tools/tests/inc/mod.rs @@ -12,20 +12,22 @@ mod if_enabled use super::*; use the_module::exposed::*; + // xxx : use protected - mod attr; - mod basic; - mod derive; - mod drop; - mod generic_args; - mod generic_params; - mod item; - mod item_struct; - mod phantom; - mod quantifier; - mod struct_like; - mod syntax; - mod tokens; - mod typ; + mod attr_test; + mod basic_test; + mod derive_test; + mod drop_test; + mod equation_test; + mod generic_args_test; + mod generic_params_test; + mod item_test; + mod item_struct_test; + mod phantom_test; + mod quantifier_test; + mod struct_like_test; + mod syntax_test; + mod tokens_test; + mod typ_test; } diff --git a/module/core/macro_tools/tests/inc/phantom.rs b/module/core/macro_tools/tests/inc/phantom_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/phantom.rs rename to module/core/macro_tools/tests/inc/phantom_test.rs diff --git a/module/core/macro_tools/tests/inc/quantifier.rs b/module/core/macro_tools/tests/inc/quantifier_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/quantifier.rs rename to module/core/macro_tools/tests/inc/quantifier_test.rs diff --git a/module/core/macro_tools/tests/inc/syntax.rs b/module/core/macro_tools/tests/inc/syntax_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/syntax.rs rename to module/core/macro_tools/tests/inc/syntax_test.rs diff --git a/module/core/macro_tools/tests/inc/tokens.rs b/module/core/macro_tools/tests/inc/tokens_test.rs similarity index 51% rename from module/core/macro_tools/tests/inc/tokens.rs rename to module/core/macro_tools/tests/inc/tokens_test.rs index aef2707fae..fcae746f5d 100644 --- a/module/core/macro_tools/tests/inc/tokens.rs +++ b/module/core/macro_tools/tests/inc/tokens_test.rs @@ -16,19 +16,3 @@ fn tokens() a_id!( got.to_string(), "# [former (default = 31)]".to_string() ); } - -// - -#[ test ] -fn equation() -{ - - let got : the_module::Equation = syn::parse_quote!( default = 31 ); - tree_print!( got ); - a_id!( code_to_str!( got ), "default = 31".to_string() ); - - a_id!( got.left, syn::parse_quote!( default ) ); - a_id!( got.op, syn::token::Eq::default() ); - a_id!( code_to_str!( got.right ), "31".to_string() ); - -} diff --git a/module/core/macro_tools/tests/inc/typ.rs b/module/core/macro_tools/tests/inc/typ_Test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/typ.rs rename to module/core/macro_tools/tests/inc/typ_Test.rs From c52c776181a294805da89676e77d5bc5f895be09 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 09:29:47 +0300 Subject: [PATCH 18/44] macro_tools : fixing mess --- .../macro_tools/tests/inc/{struct_like.rs => struct_like_test.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename module/core/macro_tools/tests/inc/{struct_like.rs => struct_like_test.rs} (100%) diff --git a/module/core/macro_tools/tests/inc/struct_like.rs b/module/core/macro_tools/tests/inc/struct_like_test.rs similarity index 100% rename from module/core/macro_tools/tests/inc/struct_like.rs rename to module/core/macro_tools/tests/inc/struct_like_test.rs From 1684c35a2e66da199ba535548f1c8f8e7bafae51 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 09:31:00 +0300 Subject: [PATCH 19/44] macro_tools : fixing mess --- module/core/macro_tools/tests/inc/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/core/macro_tools/tests/inc/mod.rs b/module/core/macro_tools/tests/inc/mod.rs index 6214a91f3e..9d0be15aeb 100644 --- a/module/core/macro_tools/tests/inc/mod.rs +++ b/module/core/macro_tools/tests/inc/mod.rs @@ -3,6 +3,8 @@ use super::*; #[ allow( unused_imports ) ] use test_tools::exposed::*; +#[ allow( unused_imports ) ] +use the_module::protected::*; #[ allow( unused_imports ) ] #[ cfg( feature = "enabled" ) ] @@ -11,8 +13,6 @@ mod if_enabled { use super::*; - use the_module::exposed::*; - // xxx : use protected mod attr_test; mod basic_test; From 10f47a6110072165a246c4923460cd0d0f1ad3f6 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 09:47:52 +0300 Subject: [PATCH 20/44] macro_tools : fixing mess --- .../core/macro_tools/tests/inc/attr_test.rs | 68 ++++++++++++------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/module/core/macro_tools/tests/inc/attr_test.rs b/module/core/macro_tools/tests/inc/attr_test.rs index fd7e507d31..dab489f65d 100644 --- a/module/core/macro_tools/tests/inc/attr_test.rs +++ b/module/core/macro_tools/tests/inc/attr_test.rs @@ -32,29 +32,45 @@ fn is_standard_edge_cases() assert!( !attr::is_standard( "cfg_attr_extra" ), "Expected 'cfg_attr_extra' to not be a standard attribute." ); } -// xxx -// #[ test ] -// fn attribute_component_from_meta() -// { -// // Define a sample attribute -// let got : Attribute = parse_quote!( #[ my_component = "value" ] ); -// -// // Attempt to construct MyComponent from the attribute -// let result = MyComponent::from_meta( &got ); -// -// // Assert that the construction was successful -// assert!( result.is_ok() ); -// } -// -// #[ test ] -// fn attribute_component_attribute() -// { -// // Define a sample invalid attribute -// let got : Attribute = parse_quote!( #[ other_component = "value" ] ); -// -// // Attempt to construct MyComponent from the invalid attribute -// let result = MyComponent::from_meta( &got ); -// -// // Assert that the construction failed -// assert!( result.is_err() ); -// } +#[ test ] +fn attribute_component_from_meta() +{ + struct MyComponent; + + impl AttributeComponent for MyComponent + { + const KEYWORD : &'static str = "my_component"; + + fn from_meta( attr : &syn::Attribute ) -> Result< Self > + { + match &attr.meta + { + syn::Meta::NameValue( meta_name_value ) if meta_name_value.path.is_ident( Self::KEYWORD ) => + { + Ok( MyComponent ) + } + _ => Err( syn::Error::new_spanned( attr, "Failed to parse attribute as MyComponent" ) ), + } + } + } + + // Define a sample attribute + let attr : syn::Attribute = syn::parse_quote!( #[ my_component = "value" ] ); + + // Attempt to construct MyComponent from the attribute + let result = MyComponent::from_meta( &attr ); + + // Assert that the construction was successful + assert!( result.is_ok() ); + + // Negative testing + + // Define a sample invalid attribute + let attr : syn::Attribute = syn::parse_quote!( #[ other_component = "value" ] ); + + // Attempt to construct MyComponent from the invalid attribute + let result = MyComponent::from_meta( &attr ); + + // Assert that the construction failed + assert!( result.is_err() ); +} From e4ac9f5e00d4da2b2b7660a0d3e416be2c7736f9 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 09:54:54 +0300 Subject: [PATCH 21/44] macro_tools : fixing mess --- .../core/macro_tools/tests/inc/basic_test.rs | 344 ------------------ .../tests/inc/container_kind_test.rs | 160 ++++++++ .../core/macro_tools/tests/inc/diag_test.rs | 133 +++++++ module/core/macro_tools/tests/inc/mod.rs | 2 + module/core/macro_tools/tests/inc/typ_Test.rs | 67 ++++ 5 files changed, 362 insertions(+), 344 deletions(-) create mode 100644 module/core/macro_tools/tests/inc/container_kind_test.rs create mode 100644 module/core/macro_tools/tests/inc/diag_test.rs diff --git a/module/core/macro_tools/tests/inc/basic_test.rs b/module/core/macro_tools/tests/inc/basic_test.rs index 1b08c4ae3a..78e3dc4460 100644 --- a/module/core/macro_tools/tests/inc/basic_test.rs +++ b/module/core/macro_tools/tests/inc/basic_test.rs @@ -5,354 +5,10 @@ use super::*; tests_impls! { - - fn tree_diagnostics_str_basic() - { - - let exp = r#"code : std :: collections :: HashMap < i32 , i32 > : -TokenStream [ - Ident { - sym: std, - }, - Punct { - char: ':', - spacing: Joint, - }, - Punct { - char: ':', - spacing: Alone, - }, - Ident { - sym: collections, - }, - Punct { - char: ':', - spacing: Joint, - }, - Punct { - char: ':', - spacing: Alone, - }, - Ident { - sym: HashMap, - }, - Punct { - char: '<', - spacing: Alone, - }, - Ident { - sym: i32, - }, - Punct { - char: ',', - spacing: Alone, - }, - Ident { - sym: i32, - }, - Punct { - char: '>', - spacing: Alone, - }, -]"#; - let code = qt!( std::collections::HashMap< i32, i32 > ); - let got = the_module::tree_diagnostics_str!( code ); - // println!( "{}", got ); - a_id!( got, exp ); - let got = the_module::tree_print!( code ); - // println!( "{}", got ); - a_id!( got, exp ); - - } - - // - - fn syn_err_basic() - { - - // test.case( "basic" ); - let err = the_module::syn_err!( "abc" ); - a_id!( err.to_string(), "abc" ); - - // test.case( "basic, trailing comma" ); - let err = the_module::syn_err!( "abc", ); - a_id!( err.to_string(), "abc" ); - - // test.case( "with span" ); - let code = qt!( core::option::Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let err = the_module::syn_err!( tree_type, "abc" ); - a_id!( err.to_string(), "abc" ); - // a_id!( err.span(), syn::spanned::Spanned::span( &tree_type ) ); - - // test.case( "with span, trailing comma" ); - let code = qt!( core::option::Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let err = the_module::syn_err!( tree_type, "abc", ); - a_id!( err.to_string(), "abc" ); - - // test.case( "with span and args" ); - let code = qt!( core::option::Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let err = the_module::syn_err!( tree_type, "abc{}{}", "def", "ghi" ); - a_id!( err.to_string(), "abcdefghi" ); - // a_id!( err.span(), syn::spanned::Spanned::span( &tree_type ) ); - - // test.case( "with span and args, trailing comma" ); - let code = qt!( core::option::Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let err = the_module::syn_err!( tree_type, "abc{}{}", "def", "ghi", ); - a_id!( err.to_string(), "abcdefghi" ); - - // test.case( "without span" ); - let err = the_module::syn_err!( _, "abc" ); - a_id!( err.to_string(), "abc" ); - - // test.case( "without span, trailing comma" ); - let err = the_module::syn_err!( _, "abc", ); - a_id!( err.to_string(), "abc" ); - - // test.case( "without span, but with args" ); - let err = the_module::syn_err!( _, "abc{}{}", "def", "ghi" ); - a_id!( err.to_string(), "abcdefghi" ); - - // test.case( "without span, trailing comma" ); - let err = the_module::syn_err!( _, "abc{}{}", "def", "ghi", ); - a_id!( err.to_string(), "abcdefghi" ); - - } - - // - - fn type_container_kind_basic() - { - use the_module::exposed::container_kind; - - // test.case( "core::option::Option< i32 >" ); - let code = qt!( core::option::Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::No ); - - // test.case( "core::option::Option< Vec >" ); - let code = qt!( core::option::Option< Vec > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::No ); - - // test.case( "alloc::vec::Vec< i32 >" ); - let code = qt!( alloc::vec::Vec< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::Vector ); - - // test.case( "alloc::vec::Vec" ); - let code = qt!( alloc::vec::Vec ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::Vector ); - - // test.case( "std::vec::Vec< i32 >" ); - let code = qt!( std::vec::Vec< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::Vector ); - - // test.case( "std::vec::Vec" ); - let code = qt!( std::vec::Vec ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::Vector ); - - // test.case( "std::Vec< i32 >" ); - let code = qt!( std::Vec< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::Vector ); - - // test.case( "std::Vec" ); - let code = qt!( std::Vec ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::Vector ); - - // test.case( "not vector" ); - let code = qt!( std::SomeVector< i32, i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::No ); - - // test.case( "hash map" ); - let code = qt!( std::collections::HashMap< i32, i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::HashMap ); - - // test.case( "hash set" ); - let code = qt!( std::collections::HashSet< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = container_kind::of_type( &tree_type ); - a_id!( got, the_module::container_kind::ContainerKind::HashSet ); - - } - - // - - fn type_optional_container_kind_basic() - { - - // test.case( "non optional not container" ); - let code = qt!( i32 ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::No, false ) ); - - // test.case( "optional not container" ); - let code = qt!( core::option::Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::No, true ) ); - - // test.case( "optional not container" ); - let code = qt!( Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::No, true ) ); - - - // test.case( "optional vector" ); - let code = qt!( core::option::Option< Vec > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::Vector, true ) ); - - // test.case( "optional vector" ); - let code = qt!( Option< Vec > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::Vector, true ) ); - - // test.case( "non optional vector" ); - let code = qt!( std::Vec< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::Vector, false ) ); - - - // test.case( "optional vector" ); - let code = qt!( core::option::Option< std::collections::HashMap< i32, i32 > > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::HashMap, true ) ); - - // test.case( "optional vector" ); - let code = qt!( Option< HashMap > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::HashMap, true ) ); - - // test.case( "non optional vector" ); - let code = qt!( HashMap< i32, i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::HashMap, false ) ); - - - // test.case( "optional vector" ); - let code = qt!( core::option::Option< std::collections::HashSet< i32, i32 > > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::HashSet, true ) ); - - // test.case( "optional vector" ); - let code = qt!( Option< HashSet > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::HashSet, true ) ); - - // test.case( "non optional vector" ); - let code = qt!( HashSet< i32, i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::container_kind::of_optional( &tree_type ); - a_id!( got, ( the_module::container_kind::ContainerKind::HashSet, false ) ); - - } - - // - - fn type_rightmost_basic() - { - - // test.case( "core::option::Option< i32 >" ); - let code = qt!( core::option::Option< i32 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - let got = the_module::typ::type_rightmost( &tree_type ); - a_id!( got, Some( "Option".to_string() ) ); - - } - - // - - fn type_parameters_basic() - { - - macro_rules! q - { - ( $( $Src : tt )+ ) => - { - syn::parse2::< syn::Type >( qt!( $( $Src )+ ) ).unwrap() - } - } - - // test.case( "core::option::Option< i8, i16, i32, i64 >" ); - let code = qt!( core::option::Option< i8, i16, i32, i64 > ); - let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); - - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..=0 ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ) ]; - a_id!( got, exp ); - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..=1 ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ), q!( i16 ) ]; - a_id!( got, exp ); - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..=2 ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ) ]; - a_id!( got, exp ); - - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..0 ).into_iter().cloned().collect(); - let exp : Vec< syn::Type > = vec![]; - a_id!( got, exp ); - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..1 ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ) ]; - a_id!( got, exp ); - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..2 ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ), q!( i16 ) ]; - a_id!( got, exp ); - - // unbound - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, .. ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ), q!( i64 ) ]; - a_id!( got, exp ); - - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, .. ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ), q!( i64 ) ]; - a_id!( got, exp ); - - let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, .. ).into_iter().cloned().collect(); - let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ), q!( i64 ) ]; - a_id!( got, exp ); - - } - } // tests_index! { - tree_diagnostics_str_basic, - syn_err_basic, - type_container_kind_basic, - type_optional_container_kind_basic, - type_rightmost_basic, - type_parameters_basic, } diff --git a/module/core/macro_tools/tests/inc/container_kind_test.rs b/module/core/macro_tools/tests/inc/container_kind_test.rs new file mode 100644 index 0000000000..e6669410a1 --- /dev/null +++ b/module/core/macro_tools/tests/inc/container_kind_test.rs @@ -0,0 +1,160 @@ + +use super::*; + +// + +#[ test ] +fn type_container_kind_basic() +{ + use the_module::exposed::container_kind; + + // test.case( "core::option::Option< i32 >" ); + let code = qt!( core::option::Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::No ); + + // test.case( "core::option::Option< Vec >" ); + let code = qt!( core::option::Option< Vec > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::No ); + + // test.case( "alloc::vec::Vec< i32 >" ); + let code = qt!( alloc::vec::Vec< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::Vector ); + + // test.case( "alloc::vec::Vec" ); + let code = qt!( alloc::vec::Vec ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::Vector ); + + // test.case( "std::vec::Vec< i32 >" ); + let code = qt!( std::vec::Vec< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::Vector ); + + // test.case( "std::vec::Vec" ); + let code = qt!( std::vec::Vec ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::Vector ); + + // test.case( "std::Vec< i32 >" ); + let code = qt!( std::Vec< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::Vector ); + + // test.case( "std::Vec" ); + let code = qt!( std::Vec ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::Vector ); + + // test.case( "not vector" ); + let code = qt!( std::SomeVector< i32, i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::No ); + + // test.case( "hash map" ); + let code = qt!( std::collections::HashMap< i32, i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::HashMap ); + + // test.case( "hash set" ); + let code = qt!( std::collections::HashSet< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = container_kind::of_type( &tree_type ); + a_id!( got, the_module::container_kind::ContainerKind::HashSet ); + +} + +// + +#[ test ] +fn type_optional_container_kind_basic() +{ + + // test.case( "non optional not container" ); + let code = qt!( i32 ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::No, false ) ); + + // test.case( "optional not container" ); + let code = qt!( core::option::Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::No, true ) ); + + // test.case( "optional not container" ); + let code = qt!( Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::No, true ) ); + + + // test.case( "optional vector" ); + let code = qt!( core::option::Option< Vec > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::Vector, true ) ); + + // test.case( "optional vector" ); + let code = qt!( Option< Vec > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::Vector, true ) ); + + // test.case( "non optional vector" ); + let code = qt!( std::Vec< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::Vector, false ) ); + + + // test.case( "optional vector" ); + let code = qt!( core::option::Option< std::collections::HashMap< i32, i32 > > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::HashMap, true ) ); + + // test.case( "optional vector" ); + let code = qt!( Option< HashMap > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::HashMap, true ) ); + + // test.case( "non optional vector" ); + let code = qt!( HashMap< i32, i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::HashMap, false ) ); + + + // test.case( "optional vector" ); + let code = qt!( core::option::Option< std::collections::HashSet< i32, i32 > > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::HashSet, true ) ); + + // test.case( "optional vector" ); + let code = qt!( Option< HashSet > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::HashSet, true ) ); + + // test.case( "non optional vector" ); + let code = qt!( HashSet< i32, i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::container_kind::of_optional( &tree_type ); + a_id!( got, ( the_module::container_kind::ContainerKind::HashSet, false ) ); + +} diff --git a/module/core/macro_tools/tests/inc/diag_test.rs b/module/core/macro_tools/tests/inc/diag_test.rs new file mode 100644 index 0000000000..e39db7d824 --- /dev/null +++ b/module/core/macro_tools/tests/inc/diag_test.rs @@ -0,0 +1,133 @@ + +use super::*; + +// + +tests_impls! +{ + + fn tree_diagnostics_str_basic() + { + + let exp = r#"code : std :: collections :: HashMap < i32 , i32 > : +TokenStream [ + Ident { + sym: std, + }, + Punct { + char: ':', + spacing: Joint, + }, + Punct { + char: ':', + spacing: Alone, + }, + Ident { + sym: collections, + }, + Punct { + char: ':', + spacing: Joint, + }, + Punct { + char: ':', + spacing: Alone, + }, + Ident { + sym: HashMap, + }, + Punct { + char: '<', + spacing: Alone, + }, + Ident { + sym: i32, + }, + Punct { + char: ',', + spacing: Alone, + }, + Ident { + sym: i32, + }, + Punct { + char: '>', + spacing: Alone, + }, +]"#; + let code = qt!( std::collections::HashMap< i32, i32 > ); + let got = the_module::tree_diagnostics_str!( code ); + // println!( "{}", got ); + a_id!( got, exp ); + let got = the_module::tree_print!( code ); + // println!( "{}", got ); + a_id!( got, exp ); + + } + + // + + fn syn_err_basic() + { + + // test.case( "basic" ); + let err = the_module::syn_err!( "abc" ); + a_id!( err.to_string(), "abc" ); + + // test.case( "basic, trailing comma" ); + let err = the_module::syn_err!( "abc", ); + a_id!( err.to_string(), "abc" ); + + // test.case( "with span" ); + let code = qt!( core::option::Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let err = the_module::syn_err!( tree_type, "abc" ); + a_id!( err.to_string(), "abc" ); + // a_id!( err.span(), syn::spanned::Spanned::span( &tree_type ) ); + + // test.case( "with span, trailing comma" ); + let code = qt!( core::option::Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let err = the_module::syn_err!( tree_type, "abc", ); + a_id!( err.to_string(), "abc" ); + + // test.case( "with span and args" ); + let code = qt!( core::option::Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let err = the_module::syn_err!( tree_type, "abc{}{}", "def", "ghi" ); + a_id!( err.to_string(), "abcdefghi" ); + // a_id!( err.span(), syn::spanned::Spanned::span( &tree_type ) ); + + // test.case( "with span and args, trailing comma" ); + let code = qt!( core::option::Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let err = the_module::syn_err!( tree_type, "abc{}{}", "def", "ghi", ); + a_id!( err.to_string(), "abcdefghi" ); + + // test.case( "without span" ); + let err = the_module::syn_err!( _, "abc" ); + a_id!( err.to_string(), "abc" ); + + // test.case( "without span, trailing comma" ); + let err = the_module::syn_err!( _, "abc", ); + a_id!( err.to_string(), "abc" ); + + // test.case( "without span, but with args" ); + let err = the_module::syn_err!( _, "abc{}{}", "def", "ghi" ); + a_id!( err.to_string(), "abcdefghi" ); + + // test.case( "without span, trailing comma" ); + let err = the_module::syn_err!( _, "abc{}{}", "def", "ghi", ); + a_id!( err.to_string(), "abcdefghi" ); + + } + +} + +// + +tests_index! +{ + tree_diagnostics_str_basic, + syn_err_basic, +} diff --git a/module/core/macro_tools/tests/inc/mod.rs b/module/core/macro_tools/tests/inc/mod.rs index 9d0be15aeb..f1c2bd1c01 100644 --- a/module/core/macro_tools/tests/inc/mod.rs +++ b/module/core/macro_tools/tests/inc/mod.rs @@ -16,7 +16,9 @@ mod if_enabled mod attr_test; mod basic_test; + mod container_kind_test; mod derive_test; + mod diag_test; mod drop_test; mod equation_test; mod generic_args_test; diff --git a/module/core/macro_tools/tests/inc/typ_Test.rs b/module/core/macro_tools/tests/inc/typ_Test.rs index e993156bab..174c2c243b 100644 --- a/module/core/macro_tools/tests/inc/typ_Test.rs +++ b/module/core/macro_tools/tests/inc/typ_Test.rs @@ -126,3 +126,70 @@ fn parameter_first_with_deeply_nested_generics() let expected_type : Type = parse_str( "HashMap< String, Option< i32 > >" ).expect( "Expected type to parse correctly" ); assert_eq!( format!( "{:?}", expected_type ), format!( "{:?}", first_param ), "Extracted type does not match expected" ); } + +// + +#[ test ] +fn type_rightmost_basic() +{ + + // test.case( "core::option::Option< i32 >" ); + let code = qt!( core::option::Option< i32 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + let got = the_module::typ::type_rightmost( &tree_type ); + a_id!( got, Some( "Option".to_string() ) ); + +} + +// + +#[ test ] +fn type_parameters_basic() +{ + + macro_rules! q + { + ( $( $Src : tt )+ ) => + { + syn::parse2::< syn::Type >( qt!( $( $Src )+ ) ).unwrap() + } + } + + // test.case( "core::option::Option< i8, i16, i32, i64 >" ); + let code = qt!( core::option::Option< i8, i16, i32, i64 > ); + let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); + + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..=0 ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ) ]; + a_id!( got, exp ); + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..=1 ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ), q!( i16 ) ]; + a_id!( got, exp ); + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..=2 ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ) ]; + a_id!( got, exp ); + + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..0 ).into_iter().cloned().collect(); + let exp : Vec< syn::Type > = vec![]; + a_id!( got, exp ); + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..1 ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ) ]; + a_id!( got, exp ); + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, 0..2 ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ), q!( i16 ) ]; + a_id!( got, exp ); + + // unbound + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, .. ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ), q!( i64 ) ]; + a_id!( got, exp ); + + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, .. ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ), q!( i64 ) ]; + a_id!( got, exp ); + + let got : Vec< syn::Type > = the_module::typ::type_parameters( &tree_type, .. ).into_iter().cloned().collect(); + let exp = vec![ q!( i8 ), q!( i16 ), q!( i32 ), q!( i64 ) ]; + a_id!( got, exp ); + +} From 004f8fee4c134ac1e1ebc2b346e5dc5b433c52a8 Mon Sep 17 00:00:00 2001 From: wandalen Date: Wed, 22 May 2024 09:57:57 +0300 Subject: [PATCH 22/44] former : refactoring parsing --- .../src/derive_former/struct_attrs.rs | 27 ++++++++++++------- module/core/macro_tools/src/struct_like.rs | 2 -- 2 files changed, 18 insertions(+), 11 deletions(-) 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 750d9fb3b9..e090f12371 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -74,18 +74,27 @@ impl StructAttributes { let mut result = Self::default(); // let known_attributes = "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`."; - let known_attributes = const_format::concatcp! - ( - "Known attirbutes are : ", - "debug", - ", ", AttributeStorageFields::KEYWORD, - ", ", AttributeMutator::KEYWORD, - ", ", AttributePerform::KEYWORD, - ".", - ); + // let known_attributes = const_format::concatcp! + // ( + // "Known attirbutes are : ", + // "debug", + // ", ", AttributeStorageFields::KEYWORD, + // ", ", AttributeMutator::KEYWORD, + // ", ", AttributePerform::KEYWORD, + // ".", + // ); let error = | attr : &syn::Attribute | -> syn::Error { + let known_attributes = const_format::concatcp! + ( + "Known attirbutes are : ", + "debug", + ", ", AttributeStorageFields::KEYWORD, + ", ", AttributeMutator::KEYWORD, + ", ", AttributePerform::KEYWORD, + ".", + ); syn_err! ( attr, diff --git a/module/core/macro_tools/src/struct_like.rs b/module/core/macro_tools/src/struct_like.rs index a2a80e6c5d..55b90ba0eb 100644 --- a/module/core/macro_tools/src/struct_like.rs +++ b/module/core/macro_tools/src/struct_like.rs @@ -245,9 +245,7 @@ pub( crate ) mod private impl StructLike { - // xxx2 : continue /// Returns an iterator over elements of the item. - // pub fn elements< 'a >( &'a self ) -> impl Iterator< Item = FieldOrVariant< 'a > > + 'a pub fn elements< 'a >( &'a self ) -> impl IterTrait< 'a, FieldOrVariant< 'a > > + 'a { match self From ce17faa344d0e85f16a75b4bfabc712ea1489323 Mon Sep 17 00:00:00 2001 From: wandalen Date: Thu, 23 May 2024 00:00:19 +0300 Subject: [PATCH 23/44] former : refactoring parsing --- module/core/former_meta/src/derive_former.rs | 2 +- .../src/derive_former/struct_attrs.rs | 58 +++++++++++++------ module/core/former_types/src/component.rs | 1 + 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/module/core/former_meta/src/derive_former.rs b/module/core/former_meta/src/derive_former.rs index 0a584b0db2..a1ad8c6d82 100644 --- a/module/core/former_meta/src/derive_former.rs +++ b/module/core/former_meta/src/derive_former.rs @@ -71,7 +71,7 @@ pub fn mutator } }; - if mutator.hint + if mutator.hint.into() { let hint = format! ( 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 e090f12371..22ed3ec141 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -73,16 +73,6 @@ impl StructAttributes pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { let mut result = Self::default(); - // let known_attributes = "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`."; - // let known_attributes = const_format::concatcp! - // ( - // "Known attirbutes are : ", - // "debug", - // ", ", AttributeStorageFields::KEYWORD, - // ", ", AttributeMutator::KEYWORD, - // ", ", AttributePerform::KEYWORD, - // ".", - // ); let error = | attr : &syn::Attribute | -> syn::Error { @@ -106,10 +96,7 @@ impl StructAttributes for attr in attrs { - // return Err( error( attr ) ); - - let key_ident = attr.path().get_ident() - .ok_or_else( || error( attr ) )?; + let key_ident = attr.path().get_ident().ok_or_else( || error( attr ) )?; let key_str = format!( "{}", key_ident ); if attr::is_standard( &key_str ) @@ -332,7 +319,7 @@ pub struct AttributeMutator pub custom : bool, /// Specifies whether to provide a sketch of the mutator as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. - pub hint : bool, + pub hint : AttributeEntryHint, } impl AttributeComponent for AttributeMutator @@ -368,6 +355,42 @@ where } } +// xxx2 : qqq : continue and get it implemented for all entries of all attribures + +/// Specifies whether to provide a sketch as a hint. +/// Defaults to `false`, which means no hint is provided unless explicitly requested. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributeEntryHint( bool ); + +impl From< bool > for AttributeEntryHint +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( src ) + } +} + +impl From< AttributeEntryHint > for bool +{ + #[ inline( always ) ] + fn from( src : AttributeEntryHint ) -> Self + { + src.0 + } +} + +impl< IntoT > ComponentAssign< AttributeEntryHint, IntoT > for AttributeMutator +where + IntoT : Into< AttributeEntryHint >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.hint = component.into(); + } +} + impl syn::parse::Parse for AttributeMutator { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -415,7 +438,7 @@ impl syn::parse::Parse for AttributeMutator Ok( Self { custom, - hint, + hint : hint.into(), }) } } @@ -467,11 +490,8 @@ 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/former_types/src/component.rs b/module/core/former_types/src/component.rs index 1edd59bb36..68a5479fce 100644 --- a/module/core/former_types/src/component.rs +++ b/module/core/former_types/src/component.rs @@ -1,3 +1,4 @@ + /// Provides a generic interface for setting a component of a certain type on an object. /// /// This trait abstracts the action of setting or replacing a component, where a component From 42a735fa1cd7bba079db28d431a6c30bc70ddeba Mon Sep 17 00:00:00 2001 From: wandalen Date: Thu, 23 May 2024 00:56:27 +0300 Subject: [PATCH 24/44] former : refactoring parsing --- .../core/derive_tools_meta/src/derive/from.rs | 6 +- module/core/former_meta/src/derive_former.rs | 2 +- .../src/derive_former/field_attrs.rs | 16 +- .../src/derive_former/struct_attrs.rs | 162 ++++++++++++------ 4 files changed, 124 insertions(+), 62 deletions(-) diff --git a/module/core/derive_tools_meta/src/derive/from.rs b/module/core/derive_tools_meta/src/derive/from.rs index e0877b372e..e3f330d149 100644 --- a/module/core/derive_tools_meta/src/derive/from.rs +++ b/module/core/derive_tools_meta/src/derive/from.rs @@ -372,7 +372,7 @@ impl FieldAttributes for attr in attrs { let key_ident = attr.path().get_ident() - .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( val ) ], but got:\n {}", qt!{ #attr } ) )?; + .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( key1 = val1, key2 = val2 ) ], but got:\n {}", qt!{ #attr } ) )?; let key_str = format!( "{}", key_ident ); if attr::is_standard( &key_str ) @@ -518,9 +518,9 @@ impl syn::parse::Parse for AttributeFrom } // Optional comma handling - if input.peek( syn::Token![,] ) + if input.peek( syn::Token![ , ] ) { - input.parse::< syn::Token![,] >()?; + input.parse::< syn::Token![ , ] >()?; } Ok( Self { enabled, hint } ) } diff --git a/module/core/former_meta/src/derive_former.rs b/module/core/former_meta/src/derive_former.rs index a1ad8c6d82..776d639738 100644 --- a/module/core/former_meta/src/derive_former.rs +++ b/module/core/former_meta/src/derive_former.rs @@ -54,7 +54,7 @@ pub fn mutator ) -> Result< TokenStream > { - let former_mutator_code = if mutator.custom + let former_mutator_code = if mutator.custom.into() { qt!{} } 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 3739227ab6..52514c7904 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -43,7 +43,7 @@ impl FieldAttributes syn_err! ( attr, - "Expects an attribute of format `#[ attribute( val ) ]`\n {known_attributes}\n But got:\n `{}`", + "Expects an attribute of format `#[ attribute( key1 = val1, key2 = val2 ) ]`\n {known_attributes}\n But got:\n `{}`", qt!{ #attr } ) }; @@ -91,7 +91,7 @@ impl FieldAttributes // for attr in attrs // { // let key_ident = attr.path().get_ident() -// .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( val ) ], but got:\n {}", qt!{ #attr } ) )?; +// .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( key1 = val1, key2 = val2 ) ], but got:\n {}", qt!{ #attr } ) )?; // let key_str = format!( "{}", key_ident ); // // if attr::is_standard( &key_str ) @@ -334,9 +334,9 @@ impl syn::parse::Parse for AttributeScalarSetter } // Optional comma handling - if input.peek( syn::Token![,] ) + if input.peek( syn::Token![ , ] ) { - input.parse::< syn::Token![,] >()?; + input.parse::< syn::Token![ , ] >()?; } } @@ -454,9 +454,9 @@ impl syn::parse::Parse for AttributeSubformScalarSetter } // Optional comma handling - if input.peek( syn::Token![,] ) + if input.peek( syn::Token![ , ] ) { - input.parse::< syn::Token![,] >()?; + input.parse::< syn::Token![ , ] >()?; } } @@ -709,9 +709,9 @@ impl syn::parse::Parse for AttributeSubformEntrySetter } // Optional comma handling - if input.peek( syn::Token![,] ) + if input.peek( syn::Token![ , ] ) { - input.parse::< syn::Token![,] >()?; + input.parse::< syn::Token![ , ] >()?; } } 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 22ed3ec141..1c23915c26 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -88,7 +88,7 @@ impl StructAttributes syn_err! ( attr, - "Expects an attribute of format `#[ attribute( val ) ]`\n {known_attributes}\n But got:\n `{}`", + "Expects an attribute of format '#[ attribute( key1 = val1, key2 = val2 ) ]'\n {known_attributes}\n But got: '{}'", qt!{ #attr } ) }; @@ -126,7 +126,7 @@ impl StructAttributes // for attr in attrs // { // let key_ident = attr.path().get_ident() -// .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( val ) ], but got:\n {}", qt!{ #attr } ) )?; +// .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( key1 = val1, key2 = val2 ) ], but got:\n {}", qt!{ #attr } ) )?; // let key_str = format!( "{}", key_ident ); // // if attr::is_standard( &key_str ) @@ -290,8 +290,8 @@ impl syn::parse::Parse for AttributeStorageFields fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let fields : syn::punctuated::Punctuated< syn::Field, syn::Token![,] > = - input.parse_terminated( syn::Field::parse_named, Token![,] )?; + let fields : syn::punctuated::Punctuated< syn::Field, syn::Token![ , ] > = + input.parse_terminated( syn::Field::parse_named, Token![ , ] )?; Ok( Self { @@ -316,7 +316,7 @@ pub struct AttributeMutator { /// Indicates whether a custom mutator should be generated. /// Defaults to `false`, meaning no custom mutator is generated unless explicitly requested. - pub custom : bool, + pub custom : AttributeEntryCustom, /// Specifies whether to provide a sketch of the mutator as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. pub hint : AttributeEntryHint, @@ -355,31 +355,6 @@ where } } -// xxx2 : qqq : continue and get it implemented for all entries of all attribures - -/// Specifies whether to provide a sketch as a hint. -/// Defaults to `false`, which means no hint is provided unless explicitly requested. -#[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributeEntryHint( bool ); - -impl From< bool > for AttributeEntryHint -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( src ) - } -} - -impl From< AttributeEntryHint > for bool -{ - #[ inline( always ) ] - fn from( src : AttributeEntryHint ) -> Self - { - src.0 - } -} - impl< IntoT > ComponentAssign< AttributeEntryHint, IntoT > for AttributeMutator where IntoT : Into< AttributeEntryHint >, @@ -395,8 +370,24 @@ impl syn::parse::Parse for AttributeMutator { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let mut custom = false; - let mut hint = false; + let mut result = Self::default(); + + let error = | ident : &syn::Ident | -> syn::Error + { + let known = const_format::concatcp! + ( + "Known entries of attribute ", AttributeMutator::KEYWORD, " are : ", + AttributeEntryCustom::KEYWORD, + ", ", AttributeEntryHint::KEYWORD, + ".", + ); + syn_err! + ( + ident, + "Expects an attribute of format '#[ attribute( key1 = val1, key2 = val2 ) ]' \n {known}\n But got: '{}'", + qt!{ #ident } + ) + }; while !input.is_empty() { @@ -404,22 +395,17 @@ impl syn::parse::Parse for AttributeMutator if lookahead.peek( syn::Ident ) { let ident : syn::Ident = input.parse()?; + + // return Err( error( &ident ) ); + input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - "custom" => - { - let value : syn::LitBool = input.parse()?; - custom = value.value; - } - "hint" => - { - let value : syn::LitBool = input.parse()?; - hint = value.value; - } + AttributeEntryCustom::KEYWORD => result.custom = input.parse()?, + AttributeEntryHint::KEYWORD => result.hint = input.parse()?, _ => { - return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'custom' or 'hint'.", ident ) ) ); + return Err( error( &ident ) ); } } } @@ -429,17 +415,13 @@ impl syn::parse::Parse for AttributeMutator } // Optional comma handling - if input.peek( syn::Token![,] ) + if input.peek( syn::Token![ , ] ) { - input.parse::< syn::Token![,] >()?; + input.parse::< syn::Token![ , ] >()?; } } - Ok( Self - { - custom, - hint : hint.into(), - }) + Ok( result ) } } @@ -497,4 +479,84 @@ impl syn::parse::Parse for AttributePerform } } +// == attribute entries + +// xxx2 : qqq : continue and get it implemented for all entries of all attribures + +/// Specifies whether to provide a sketch as a hint. +/// Defaults to `false`, which means no hint is provided unless explicitly requested. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributeEntryHint( bool ); + +impl AttributeEntryHint +{ + const KEYWORD : &'static str = "mutator"; +} + +impl syn::parse::Parse for AttributeEntryHint +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } +} + +impl From< bool > for AttributeEntryHint +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( src ) + } +} + +impl From< AttributeEntryHint > for bool +{ + #[ inline( always ) ] + fn from( src : AttributeEntryHint ) -> Self + { + src.0 + } +} + +// = + +/// Indicates whether a custom code should be generated. +/// Defaults to `false`, meaning no custom code is generated unless explicitly requested. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributeEntryCustom( bool ); + +impl AttributeEntryCustom +{ + const KEYWORD : &'static str = "custom"; +} + +impl syn::parse::Parse for AttributeEntryCustom +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } +} + +impl From< bool > for AttributeEntryCustom +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( src ) + } +} + +impl From< AttributeEntryCustom > for bool +{ + #[ inline( always ) ] + fn from( src : AttributeEntryCustom ) -> Self + { + src.0 + } +} + // xxx : continue From 364fbb7aa1d081e93e4d38a09300371608ad1acc Mon Sep 17 00:00:00 2001 From: wandalen Date: Thu, 23 May 2024 08:08:41 +0300 Subject: [PATCH 25/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 146 ++++++++++++++++++ .../src/derive_former/struct_attrs.rs | 4 +- 2 files changed, 147 insertions(+), 3 deletions(-) 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 52514c7904..c9c79dc241 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -719,4 +719,150 @@ impl syn::parse::Parse for AttributeSubformEntrySetter } } +// == attribute entries + +// = AttributeEntryHint + +/// Specifies whether to provide a sketch as a hint. +/// Defaults to `false`, which means no hint is provided unless explicitly requested. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributeEntryHint( bool ); + +impl AttributeEntryHint +{ + const KEYWORD : &'static str = "hint"; +} + +impl syn::parse::Parse for AttributeEntryHint +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } +} + +impl From< bool > for AttributeEntryHint +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( src ) + } +} + +impl From< AttributeEntryHint > for bool +{ + #[ inline( always ) ] + fn from( src : AttributeEntryHint ) -> Self + { + src.0 + } +} + +// = AttributeEntrySetter + +/// Disable generation of setter. +/// Attributes still might generate some helper methods to reuse by custom setter. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributeEntrySetter( Option< bool > ); + +impl AttributeEntrySetter +{ + const KEYWORD : &'static str = "setter"; +} + +impl syn::parse::Parse for AttributeEntrySetter +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } +} + +impl From< bool > for AttributeEntrySetter +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( Some( src ) ) + } +} + +impl From< Option< bool > > for AttributeEntrySetter +{ + #[ inline( always ) ] + fn from( src : Option< bool > ) -> Self + { + Self( src ) + } +} + +impl From< AttributeEntrySetter > for Option< bool > +{ + #[ inline( always ) ] + fn from( src : AttributeEntrySetter ) -> Self + { + src.0 + } +} + +// = AttributeEntryName + +/// An optional identifier that names the setter. It is parsed from inputs +/// like `name = my_field`. +#[ derive( Debug, Default, Clone ) ] +pub struct AttributeEntryName( Option< syn::Ident > ); + +impl AttributeEntryName +{ + const KEYWORD : &'static str = "name"; +} + +impl syn::parse::Parse for AttributeEntryName +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::Ident = input.parse()?; + Ok( value.into() ) + } +} + +impl From< syn::Ident > for AttributeEntryName +{ + #[ inline( always ) ] + fn from( src : syn::Ident ) -> Self + { + Self( Some( src ) ) + } +} + +impl From< Option< syn::Ident > > for AttributeEntryName +{ + #[ inline( always ) ] + fn from( src : Option< syn::Ident > ) -> Self + { + Self( src ) + } +} + +impl From< AttributeEntryName > for Option< syn::Ident > +{ + #[ inline( always ) ] + fn from( src : AttributeEntryName ) -> Self + { + src.0 + } +} + +impl< 'a > From< &'a AttributeEntryName > for Option< &'a syn::Ident > +{ + #[ inline( always ) ] + fn from( src : &'a AttributeEntryName ) -> Self + { + src.0.as_ref() + } +} + // xxx : continue 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 1c23915c26..93856f1af8 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -396,8 +396,6 @@ impl syn::parse::Parse for AttributeMutator { let ident : syn::Ident = input.parse()?; - // return Err( error( &ident ) ); - input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { @@ -490,7 +488,7 @@ pub struct AttributeEntryHint( bool ); impl AttributeEntryHint { - const KEYWORD : &'static str = "mutator"; + const KEYWORD : &'static str = "hint"; } impl syn::parse::Parse for AttributeEntryHint From 2d4a4d826aa01a9c161b74792c981d50576f24dc Mon Sep 17 00:00:00 2001 From: wandalen Date: Fri, 24 May 2024 00:39:47 +0300 Subject: [PATCH 26/44] former : refactoring parsing --- .../former_meta/src/derive_former/field.rs | 4 +- .../src/derive_former/field_attrs.rs | 140 ++++++++++++++---- .../src/derive_former/struct_attrs.rs | 2 + 3 files changed, 116 insertions(+), 30 deletions(-) diff --git a/module/core/former_meta/src/derive_former/field.rs b/module/core/former_meta/src/derive_former/field.rs index b6bf5a9ce3..0288bf9cb2 100644 --- a/module/core/former_meta/src/derive_former/field.rs +++ b/module/core/former_meta/src/derive_former/field.rs @@ -975,7 +975,7 @@ allowing for dynamic and flexible construction of the `{stru}` entity's {field_i setters_code }; - if attr.hint + if attr.hint.into() { let hint = format! ( @@ -1506,7 +1506,7 @@ Essentially, this end action integrates the individually formed scalar value bac { if attr.setter() { - if let Some( ref name ) = attr.name + if let Some( ref name ) = attr.name.as_ref() { return Some( &name ) } 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 c9c79dc241..9059695d88 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -615,13 +615,16 @@ pub struct AttributeSubformEntrySetter { /// An optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. - pub name : Option< syn::Ident >, + // pub name : Option< syn::Ident >, + pub name : AttributeEntryName, /// Disable generation of setter. /// It still generate `_field_subform_entry` method, so it could be used to make a setter with custom arguments. - pub setter : Option< bool >, + // pub setter : Option< bool >, + pub setter : AttributeEntrySetter, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. - pub hint : bool, + // pub hint : bool, + pub hint : AttributeEntryHint, } impl AttributeSubformEntrySetter @@ -648,7 +651,7 @@ impl AttributeSubformEntrySetter /// Should setter be generated or not? pub fn setter( &self ) -> bool { - self.setter.is_none() || self.setter.unwrap() + self.setter.as_ref().is_none() || self.setter.as_ref().unwrap() } } @@ -664,13 +667,33 @@ where } } + impl syn::parse::Parse for AttributeSubformEntrySetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let mut name : Option< syn::Ident > = None; - let mut setter : Option< bool > = None; - let mut hint = false; + let mut result = Self::default(); + + let error = | ident : &syn::Ident | -> syn::Error + { + let known = const_format::concatcp! + ( + "Known entries of attribute ", AttributeSubformEntrySetter::KEYWORD, " are : ", + AttributeEntryName::KEYWORD, + ", ", AttributeEntrySetter::KEYWORD, + ", ", AttributeEntryHint::KEYWORD, + ".", + ); + syn_err! + ( + ident, + r#"Expects an attribute of format '#[ subform( name = myName, setter = true ) ]' + {known} + But got: '{}' +"#, + qt!{ #ident } + ) + }; while !input.is_empty() { @@ -678,34 +701,22 @@ impl syn::parse::Parse for AttributeSubformEntrySetter if lookahead.peek( syn::Ident ) { let ident : syn::Ident = input.parse()?; + + input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - "name" => - { - input.parse::< syn::Token![ = ] >()?; - name = Some( input.parse()? ); - } - "setter" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - setter = Some( value.value() ); - } - "hint" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - hint = value.value; - } + AttributeEntryName::KEYWORD => result.name = input.parse()?, + AttributeEntrySetter::KEYWORD => result.setter = input.parse()?, + AttributeEntryHint::KEYWORD => result.hint = input.parse()?, _ => { - return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `subform( name = myName, setter = true )`", ident ) ) ); + return Err( error( &ident ) ); } } } else { - return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `subform( name = myName, setter = true )`" ) ); + return Err( lookahead.error() ); } // Optional comma handling @@ -715,10 +726,65 @@ impl syn::parse::Parse for AttributeSubformEntrySetter } } - Ok( Self { name, setter, hint } ) + Ok( result ) } } +// impl syn::parse::Parse for AttributeSubformEntrySetter +// { +// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +// { +// let mut name : Option< syn::Ident > = None; +// let mut setter : Option< bool > = None; +// let mut hint = false; +// +// while !input.is_empty() +// { +// let lookahead = input.lookahead1(); +// if lookahead.peek( syn::Ident ) +// { +// let ident : syn::Ident = input.parse()?; +// match ident.to_string().as_str() +// { +// "name" => +// { +// input.parse::< syn::Token![ = ] >()?; +// name = Some( input.parse()? ); +// } +// "setter" => +// { +// input.parse::< syn::Token![ = ] >()?; +// let value : syn::LitBool = input.parse()?; +// setter = Some( value.value() ); +// } +// "hint" => +// { +// input.parse::< syn::Token![ = ] >()?; +// let value : syn::LitBool = input.parse()?; +// hint = value.value; +// } +// _ => +// { +// return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `subform( name = myName, setter = true )`", ident ) ) ); +// } +// } +// } +// else +// { +// return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `subform( name = myName, setter = true )`" ) ); +// } +// +// // Optional comma handling +// if input.peek( syn::Token![ , ] ) +// { +// input.parse::< syn::Token![ , ] >()?; +// } +// } +// +// Ok( Self { name, setter, hint } ) +// } +// } + // == attribute entries // = AttributeEntryHint @@ -781,6 +847,15 @@ impl syn::parse::Parse for AttributeEntrySetter } } +impl AsRef< Option< bool > > for AttributeEntrySetter +{ + #[ inline( always ) ] + fn as_ref( &self ) -> &Option< bool > + { + &self.0 + } +} + impl From< bool > for AttributeEntrySetter { #[ inline( always ) ] @@ -829,6 +904,15 @@ impl syn::parse::Parse for AttributeEntryName } } +impl AsRef< Option< syn::Ident > > for AttributeEntryName +{ + #[ inline( always ) ] + fn as_ref( &self ) -> &Option< syn::Ident > + { + &self.0 + } +} + impl From< syn::Ident > for AttributeEntryName { #[ inline( always ) ] @@ -865,4 +949,4 @@ impl< 'a > From< &'a AttributeEntryName > for Option< &'a syn::Ident > } } -// xxx : continue +// xxx2 : continue 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 93856f1af8..3583bb88ce 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -381,6 +381,7 @@ impl syn::parse::Parse for AttributeMutator ", ", AttributeEntryHint::KEYWORD, ".", ); + // xxx : improve hint syn_err! ( ident, @@ -399,6 +400,7 @@ impl syn::parse::Parse for AttributeMutator input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { + // xxx : use assign AttributeEntryCustom::KEYWORD => result.custom = input.parse()?, AttributeEntryHint::KEYWORD => result.hint = input.parse()?, _ => From 0fd80d6519e85f9f4e8dfd71fb045b6dfbe5e941 Mon Sep 17 00:00:00 2001 From: wandalen Date: Fri, 24 May 2024 00:41:41 +0300 Subject: [PATCH 27/44] former : refactoring parsing --- .../former_meta/src/derive_former/field_attrs.rs | 6 ++---- .../former_meta/src/derive_former/struct_attrs.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) 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 9059695d88..4d251aec28 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -684,6 +684,7 @@ impl syn::parse::Parse for AttributeSubformEntrySetter ", ", AttributeEntryHint::KEYWORD, ".", ); + // xxx : test syn_err! ( ident, @@ -708,10 +709,7 @@ impl syn::parse::Parse for AttributeSubformEntrySetter AttributeEntryName::KEYWORD => result.name = input.parse()?, AttributeEntrySetter::KEYWORD => result.setter = input.parse()?, AttributeEntryHint::KEYWORD => result.hint = input.parse()?, - _ => - { - return Err( error( &ident ) ); - } + _ => return Err( error( &ident ) ), } } else 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 3583bb88ce..416ec40ec1 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -381,11 +381,14 @@ impl syn::parse::Parse for AttributeMutator ", ", AttributeEntryHint::KEYWORD, ".", ); - // xxx : improve hint + // xxx : test syn_err! ( ident, - "Expects an attribute of format '#[ attribute( key1 = val1, key2 = val2 ) ]' \n {known}\n But got: '{}'", + r#"Expects an attribute of format '#[ mutator( custom = false, hint = false ) ]' + {known} + But got: '{}' +"#, qt!{ #ident } ) }; @@ -403,10 +406,7 @@ impl syn::parse::Parse for AttributeMutator // xxx : use assign AttributeEntryCustom::KEYWORD => result.custom = input.parse()?, AttributeEntryHint::KEYWORD => result.hint = input.parse()?, - _ => - { - return Err( error( &ident ) ); - } + _ => return Err( error( &ident ) ), } } else From 461055a6635eeaaecdedc0963381e45dcd670f49 Mon Sep 17 00:00:00 2001 From: wandalen Date: Fri, 24 May 2024 07:30:10 +0300 Subject: [PATCH 28/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 105 ++++++++++++------ .../src/derive_former/struct_attrs.rs | 55 +++++---- 2 files changed, 99 insertions(+), 61 deletions(-) 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 4d251aec28..1b6b3ff1c0 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -616,15 +616,15 @@ pub struct AttributeSubformEntrySetter /// An optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. // pub name : Option< syn::Ident >, - pub name : AttributeEntryName, + pub name : AttributePropertyName, /// Disable generation of setter. /// It still generate `_field_subform_entry` method, so it could be used to make a setter with custom arguments. // pub setter : Option< bool >, - pub setter : AttributeEntrySetter, + pub setter : AttributePropertySetter, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. // pub hint : bool, - pub hint : AttributeEntryHint, + pub hint : AttributePropertyHint, } impl AttributeSubformEntrySetter @@ -667,6 +667,38 @@ where } } +impl< IntoT > ComponentAssign< AttributePropertyName, IntoT > for AttributeSubformEntrySetter +where + IntoT : Into< AttributePropertyName >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.name = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertySetter, IntoT > for AttributeSubformEntrySetter +where + IntoT : Into< AttributePropertySetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.setter = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertyHint, IntoT > for AttributeSubformEntrySetter +where + IntoT : Into< AttributePropertyHint >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.hint = component.into(); + } +} impl syn::parse::Parse for AttributeSubformEntrySetter { @@ -679,12 +711,11 @@ impl syn::parse::Parse for AttributeSubformEntrySetter let known = const_format::concatcp! ( "Known entries of attribute ", AttributeSubformEntrySetter::KEYWORD, " are : ", - AttributeEntryName::KEYWORD, - ", ", AttributeEntrySetter::KEYWORD, - ", ", AttributeEntryHint::KEYWORD, + AttributePropertyName::KEYWORD, + ", ", AttributePropertySetter::KEYWORD, + ", ", AttributePropertyHint::KEYWORD, ".", ); - // xxx : test syn_err! ( ident, @@ -706,9 +737,9 @@ impl syn::parse::Parse for AttributeSubformEntrySetter input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - AttributeEntryName::KEYWORD => result.name = input.parse()?, - AttributeEntrySetter::KEYWORD => result.setter = input.parse()?, - AttributeEntryHint::KEYWORD => result.hint = input.parse()?, + AttributePropertyName::KEYWORD => result.assign( AttributePropertyName::parse( input )? ), + AttributePropertySetter::KEYWORD => result.assign( AttributePropertySetter::parse( input )? ), + AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), _ => return Err( error( &ident ) ), } } @@ -785,19 +816,19 @@ impl syn::parse::Parse for AttributeSubformEntrySetter // == attribute entries -// = AttributeEntryHint +// = AttributePropertyHint /// Specifies whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributeEntryHint( bool ); +pub struct AttributePropertyHint( bool ); -impl AttributeEntryHint +impl AttributePropertyHint { const KEYWORD : &'static str = "hint"; } -impl syn::parse::Parse for AttributeEntryHint +impl syn::parse::Parse for AttributePropertyHint { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { @@ -806,7 +837,7 @@ impl syn::parse::Parse for AttributeEntryHint } } -impl From< bool > for AttributeEntryHint +impl From< bool > for AttributePropertyHint { #[ inline( always ) ] fn from( src : bool ) -> Self @@ -815,28 +846,28 @@ impl From< bool > for AttributeEntryHint } } -impl From< AttributeEntryHint > for bool +impl From< AttributePropertyHint > for bool { #[ inline( always ) ] - fn from( src : AttributeEntryHint ) -> Self + fn from( src : AttributePropertyHint ) -> Self { src.0 } } -// = AttributeEntrySetter +// = AttributePropertySetter /// Disable generation of setter. /// Attributes still might generate some helper methods to reuse by custom setter. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributeEntrySetter( Option< bool > ); +pub struct AttributePropertySetter( Option< bool > ); -impl AttributeEntrySetter +impl AttributePropertySetter { const KEYWORD : &'static str = "setter"; } -impl syn::parse::Parse for AttributeEntrySetter +impl syn::parse::Parse for AttributePropertySetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { @@ -845,7 +876,7 @@ impl syn::parse::Parse for AttributeEntrySetter } } -impl AsRef< Option< bool > > for AttributeEntrySetter +impl AsRef< Option< bool > > for AttributePropertySetter { #[ inline( always ) ] fn as_ref( &self ) -> &Option< bool > @@ -854,7 +885,7 @@ impl AsRef< Option< bool > > for AttributeEntrySetter } } -impl From< bool > for AttributeEntrySetter +impl From< bool > for AttributePropertySetter { #[ inline( always ) ] fn from( src : bool ) -> Self @@ -863,7 +894,7 @@ impl From< bool > for AttributeEntrySetter } } -impl From< Option< bool > > for AttributeEntrySetter +impl From< Option< bool > > for AttributePropertySetter { #[ inline( always ) ] fn from( src : Option< bool > ) -> Self @@ -872,28 +903,28 @@ impl From< Option< bool > > for AttributeEntrySetter } } -impl From< AttributeEntrySetter > for Option< bool > +impl From< AttributePropertySetter > for Option< bool > { #[ inline( always ) ] - fn from( src : AttributeEntrySetter ) -> Self + fn from( src : AttributePropertySetter ) -> Self { src.0 } } -// = AttributeEntryName +// = AttributePropertyName /// An optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. #[ derive( Debug, Default, Clone ) ] -pub struct AttributeEntryName( Option< syn::Ident > ); +pub struct AttributePropertyName( Option< syn::Ident > ); -impl AttributeEntryName +impl AttributePropertyName { const KEYWORD : &'static str = "name"; } -impl syn::parse::Parse for AttributeEntryName +impl syn::parse::Parse for AttributePropertyName { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { @@ -902,7 +933,7 @@ impl syn::parse::Parse for AttributeEntryName } } -impl AsRef< Option< syn::Ident > > for AttributeEntryName +impl AsRef< Option< syn::Ident > > for AttributePropertyName { #[ inline( always ) ] fn as_ref( &self ) -> &Option< syn::Ident > @@ -911,7 +942,7 @@ impl AsRef< Option< syn::Ident > > for AttributeEntryName } } -impl From< syn::Ident > for AttributeEntryName +impl From< syn::Ident > for AttributePropertyName { #[ inline( always ) ] fn from( src : syn::Ident ) -> Self @@ -920,7 +951,7 @@ impl From< syn::Ident > for AttributeEntryName } } -impl From< Option< syn::Ident > > for AttributeEntryName +impl From< Option< syn::Ident > > for AttributePropertyName { #[ inline( always ) ] fn from( src : Option< syn::Ident > ) -> Self @@ -929,19 +960,19 @@ impl From< Option< syn::Ident > > for AttributeEntryName } } -impl From< AttributeEntryName > for Option< syn::Ident > +impl From< AttributePropertyName > for Option< syn::Ident > { #[ inline( always ) ] - fn from( src : AttributeEntryName ) -> Self + fn from( src : AttributePropertyName ) -> Self { src.0 } } -impl< 'a > From< &'a AttributeEntryName > for Option< &'a syn::Ident > +impl< 'a > From< &'a AttributePropertyName > for Option< &'a syn::Ident > { #[ inline( always ) ] - fn from( src : &'a AttributeEntryName ) -> Self + fn from( src : &'a AttributePropertyName ) -> Self { src.0.as_ref() } 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 416ec40ec1..ca80649cc3 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -316,10 +316,10 @@ pub struct AttributeMutator { /// Indicates whether a custom mutator should be generated. /// Defaults to `false`, meaning no custom mutator is generated unless explicitly requested. - pub custom : AttributeEntryCustom, + pub custom : AttributePropertyCustom, /// Specifies whether to provide a sketch of the mutator as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. - pub hint : AttributeEntryHint, + pub hint : AttributePropertyHint, } impl AttributeComponent for AttributeMutator @@ -355,9 +355,9 @@ where } } -impl< IntoT > ComponentAssign< AttributeEntryHint, IntoT > for AttributeMutator +impl< IntoT > ComponentAssign< AttributePropertyHint, IntoT > for AttributeMutator where - IntoT : Into< AttributeEntryHint >, + IntoT : Into< AttributePropertyHint >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -366,6 +366,17 @@ where } } +impl< IntoT > ComponentAssign< AttributePropertyCustom, IntoT > for AttributeMutator +where + IntoT : Into< AttributePropertyCustom >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.custom = component.into(); + } +} + impl syn::parse::Parse for AttributeMutator { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -377,11 +388,10 @@ impl syn::parse::Parse for AttributeMutator let known = const_format::concatcp! ( "Known entries of attribute ", AttributeMutator::KEYWORD, " are : ", - AttributeEntryCustom::KEYWORD, - ", ", AttributeEntryHint::KEYWORD, + AttributePropertyCustom::KEYWORD, + ", ", AttributePropertyHint::KEYWORD, ".", ); - // xxx : test syn_err! ( ident, @@ -403,9 +413,8 @@ impl syn::parse::Parse for AttributeMutator input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - // xxx : use assign - AttributeEntryCustom::KEYWORD => result.custom = input.parse()?, - AttributeEntryHint::KEYWORD => result.hint = input.parse()?, + AttributePropertyCustom::KEYWORD => result.assign( AttributePropertyCustom::parse( input )? ), + AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), _ => return Err( error( &ident ) ), } } @@ -486,14 +495,14 @@ impl syn::parse::Parse for AttributePerform /// Specifies whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributeEntryHint( bool ); +pub struct AttributePropertyHint( bool ); -impl AttributeEntryHint +impl AttributePropertyHint { const KEYWORD : &'static str = "hint"; } -impl syn::parse::Parse for AttributeEntryHint +impl syn::parse::Parse for AttributePropertyHint { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { @@ -502,7 +511,7 @@ impl syn::parse::Parse for AttributeEntryHint } } -impl From< bool > for AttributeEntryHint +impl From< bool > for AttributePropertyHint { #[ inline( always ) ] fn from( src : bool ) -> Self @@ -511,10 +520,10 @@ impl From< bool > for AttributeEntryHint } } -impl From< AttributeEntryHint > for bool +impl From< AttributePropertyHint > for bool { #[ inline( always ) ] - fn from( src : AttributeEntryHint ) -> Self + fn from( src : AttributePropertyHint ) -> Self { src.0 } @@ -525,14 +534,14 @@ impl From< AttributeEntryHint > for bool /// Indicates whether a custom code should be generated. /// Defaults to `false`, meaning no custom code is generated unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributeEntryCustom( bool ); +pub struct AttributePropertyCustom( bool ); -impl AttributeEntryCustom +impl AttributePropertyCustom { const KEYWORD : &'static str = "custom"; } -impl syn::parse::Parse for AttributeEntryCustom +impl syn::parse::Parse for AttributePropertyCustom { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { @@ -541,7 +550,7 @@ impl syn::parse::Parse for AttributeEntryCustom } } -impl From< bool > for AttributeEntryCustom +impl From< bool > for AttributePropertyCustom { #[ inline( always ) ] fn from( src : bool ) -> Self @@ -550,13 +559,11 @@ impl From< bool > for AttributeEntryCustom } } -impl From< AttributeEntryCustom > for bool +impl From< AttributePropertyCustom > for bool { #[ inline( always ) ] - fn from( src : AttributeEntryCustom ) -> Self + fn from( src : AttributePropertyCustom ) -> Self { src.0 } } - -// xxx : continue From 47897109547dc5c9396333b98cd3218c2c22bf99 Mon Sep 17 00:00:00 2001 From: wandalen Date: Fri, 24 May 2024 08:18:41 +0300 Subject: [PATCH 29/44] former : refactoring parsing --- .../former_meta/src/derive_former/field.rs | 2 +- .../src/derive_former/field_attrs.rs | 341 ++++++++++++++++-- 2 files changed, 308 insertions(+), 35 deletions(-) diff --git a/module/core/former_meta/src/derive_former/field.rs b/module/core/former_meta/src/derive_former/field.rs index 0288bf9cb2..2bb6a09d6a 100644 --- a/module/core/former_meta/src/derive_former/field.rs +++ b/module/core/former_meta/src/derive_former/field.rs @@ -184,7 +184,7 @@ scalar_setter_required let ident = self.ident; let ty = self.ty; let default : Option< &syn::Expr > = self.attrs.config.as_ref() - .and_then( | attr | attr.default.as_ref() ); + .and_then( | attr | attr.default.into().as_ref() ); let tokens = if self.is_optional { 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 1b6b3ff1c0..4814a293d6 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -142,8 +142,9 @@ impl FieldAttributes pub struct AttributeConfig { - /// Default value to use for the field. - pub default : Option< syn::Expr >, + /// Default value to use for a field. + pub default : AttributePropertyOptionalSyn< syn::Expr >, + // pub default : Option< syn::Expr >, } @@ -181,6 +182,17 @@ where } } +impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Expr >, IntoT > for AttributeConfig +where + IntoT : Into< AttributePropertyOptionalSyn< syn::Expr > >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.default = component.into(); + } +} + impl syn::parse::Parse for AttributeConfig { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -240,12 +252,12 @@ impl syn::parse::Parse for AttributeConfig pub struct AttributeScalarSetter { /// Optional identifier for naming the setter. - pub name : Option< syn::Ident >, + pub name : AttributePropertyOptionalSyn< syn::Ident >, /// Controls the generation of a setter method. If false, a setter method is not generated. - pub setter : Option< bool >, + pub setter : AttributePropertySetter, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. - pub hint : bool, + pub hint : AttributePropertyHint, } #[ allow( dead_code ) ] @@ -289,6 +301,39 @@ where } } +impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeScalarSetter +where + IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.name = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertySetter, IntoT > for AttributeScalarSetter +where + IntoT : Into< AttributePropertySetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.setter = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertyHint, IntoT > for AttributeScalarSetter +where + IntoT : Into< AttributePropertyHint >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.hint = component.into(); + } +} + impl syn::parse::Parse for AttributeScalarSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -357,15 +402,16 @@ impl syn::parse::Parse for AttributeScalarSetter /// #[ derive( Debug, Default ) ] + pub struct AttributeSubformScalarSetter { /// Optional identifier for naming the setter. - pub name : Option< syn::Ident >, + pub name : AttributePropertyOptionalSyn< syn::Ident >, /// Controls the generation of a setter method. If false, a setter method is not generated. - pub setter : Option< bool >, + pub setter : AttributePropertySetter, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. - pub hint : bool, + pub hint : AttributePropertyHint, } #[ allow( dead_code ) ] @@ -409,6 +455,39 @@ where } } +impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeSubformScalarSetter +where + IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.name = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertySetter, IntoT > for AttributeSubformScalarSetter +where + IntoT : Into< AttributePropertySetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.setter = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertyHint, IntoT > for AttributeSubformScalarSetter +where + IntoT : Into< AttributePropertyHint >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.hint = component.into(); + } +} + impl syn::parse::Parse for AttributeSubformScalarSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -481,16 +560,17 @@ impl syn::parse::Parse for AttributeSubformScalarSetter pub struct AttributeSubformCollectionSetter { /// Optional identifier for naming the setter. - pub name : Option< syn::Ident >, + pub name : AttributePropertyOptionalSyn< syn::Ident >, /// Controls the generation of a setter method. If false, a setter method is not generated. - pub setter : Option< bool >, + pub setter : AttributePropertySetter, /// Definition of the collection former to use, e.g., `former::VectorFormer`. - pub definition : Option< syn::Type >, + pub definition : AttributePropertyOptionalSyn< syn::Type >, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. - pub hint : bool, + pub hint : AttributePropertyHint, } +// xxx impl AttributeSubformCollectionSetter { @@ -531,6 +611,50 @@ where } } +impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeSubformCollectionSetter +where + IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.name = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertySetter, IntoT > for AttributeSubformCollectionSetter +where + IntoT : Into< AttributePropertySetter >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.setter = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Type >, IntoT > for AttributeSubformCollectionSetter +where + IntoT : Into< AttributePropertyOptionalSyn< syn::Type > >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.definition = component.into(); + } +} + +impl< IntoT > ComponentAssign< AttributePropertyHint, IntoT > for AttributeSubformCollectionSetter +where + IntoT : Into< AttributePropertyHint >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.hint = component.into(); + } +} + impl syn::parse::Parse for AttributeSubformCollectionSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -616,7 +740,7 @@ pub struct AttributeSubformEntrySetter /// An optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. // pub name : Option< syn::Ident >, - pub name : AttributePropertyName, + pub name : AttributePropertyOptionalSyn< syn::Ident >, /// Disable generation of setter. /// It still generate `_field_subform_entry` method, so it could be used to make a setter with custom arguments. // pub setter : Option< bool >, @@ -667,9 +791,9 @@ where } } -impl< IntoT > ComponentAssign< AttributePropertyName, IntoT > for AttributeSubformEntrySetter +impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeSubformEntrySetter where - IntoT : Into< AttributePropertyName >, + IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -711,7 +835,7 @@ impl syn::parse::Parse for AttributeSubformEntrySetter let known = const_format::concatcp! ( "Known entries of attribute ", AttributeSubformEntrySetter::KEYWORD, " are : ", - AttributePropertyName::KEYWORD, + AttributePropertyOptionalSyn::< syn::Ident >::KEYWORD, ", ", AttributePropertySetter::KEYWORD, ", ", AttributePropertyHint::KEYWORD, ".", @@ -737,7 +861,8 @@ impl syn::parse::Parse for AttributeSubformEntrySetter input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - AttributePropertyName::KEYWORD => result.assign( AttributePropertyName::parse( input )? ), + // xxx + AttributePropertyOptionalSyn::< syn::Ident >::KEYWORD => result.assign( AttributePropertyOptionalSyn::< syn::Ident >::parse( input )? ), AttributePropertySetter::KEYWORD => result.assign( AttributePropertySetter::parse( input )? ), AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), _ => return Err( error( &ident ) ), @@ -912,67 +1037,215 @@ impl From< AttributePropertySetter > for Option< bool > } } -// = AttributePropertyName +// // = AttributePropertyName +// +// /// An optional identifier that names the setter. It is parsed from inputs +// /// like `name = my_field`. +// #[ derive( Debug, Default, Clone ) ] +// pub struct AttributePropertyName( Option< syn::Ident > ); +// +// impl AttributePropertyName +// { +// const KEYWORD : &'static str = "name"; +// } +// +// impl syn::parse::Parse for AttributePropertyName +// { +// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +// { +// let value : syn::Ident = input.parse()?; +// Ok( value.into() ) +// } +// } +// +// impl AsRef< Option< syn::Ident > > for AttributePropertyName +// { +// #[ inline( always ) ] +// fn as_ref( &self ) -> &Option< syn::Ident > +// { +// &self.0 +// } +// } +// +// impl From< syn::Ident > for AttributePropertyName +// { +// #[ inline( always ) ] +// fn from( src : syn::Ident ) -> Self +// { +// Self( Some( src ) ) +// } +// } +// +// impl From< Option< syn::Ident > > for AttributePropertyName +// { +// #[ inline( always ) ] +// fn from( src : Option< syn::Ident > ) -> Self +// { +// Self( src ) +// } +// } +// +// impl From< AttributePropertyName > for Option< syn::Ident > +// { +// #[ inline( always ) ] +// fn from( src : AttributePropertyName ) -> Self +// { +// src.0 +// } +// } +// +// impl< 'a > From< &'a AttributePropertyName > for Option< &'a syn::Ident > +// { +// #[ inline( always ) ] +// fn from( src : &'a AttributePropertyName ) -> Self +// { +// src.0.as_ref() +// } +// } +// +// // = AttributePropertyDefault +// +// /// Default value to use for a field. +// #[ derive( Debug, Default, Clone ) ] +// pub struct AttributePropertyDefault( Option< syn::Expr > ); +// +// impl AttributePropertyDefault +// { +// const KEYWORD : &'static str = "name"; +// } +// +// impl syn::parse::Parse for AttributePropertyDefault +// { +// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +// { +// let value : syn::Expr = input.parse()?; +// Ok( value.into() ) +// } +// } +// +// impl AsRef< Option< syn::Expr > > for AttributePropertyDefault +// { +// #[ inline( always ) ] +// fn as_ref( &self ) -> &Option< syn::Expr > +// { +// &self.0 +// } +// } +// +// impl From< syn::Expr > for AttributePropertyDefault +// { +// #[ inline( always ) ] +// fn from( src : syn::Expr ) -> Self +// { +// Self( Some( src ) ) +// } +// } +// +// impl From< Option< syn::Expr > > for AttributePropertyDefault +// { +// #[ inline( always ) ] +// fn from( src : Option< syn::Expr > ) -> Self +// { +// Self( src ) +// } +// } +// +// impl From< AttributePropertyDefault > for Option< syn::Expr > +// { +// #[ inline( always ) ] +// fn from( src : AttributePropertyDefault ) -> Self +// { +// src.0 +// } +// } +// +// impl< 'a > From< &'a AttributePropertyDefault > for Option< &'a syn::Expr > +// { +// #[ inline( always ) ] +// fn from( src : &'a AttributePropertyDefault ) -> Self +// { +// src.0.as_ref() +// } +// } + +// = AttributePropertyOptionalSyn -/// An optional identifier that names the setter. It is parsed from inputs -/// like `name = my_field`. +/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. #[ derive( Debug, Default, Clone ) ] -pub struct AttributePropertyName( Option< syn::Ident > ); +pub struct AttributePropertyOptionalSyn< T >( Option< T > ) +where T : syn::parse::Parse + quote::ToTokens; -impl AttributePropertyName +impl< T > AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens { const KEYWORD : &'static str = "name"; } -impl syn::parse::Parse for AttributePropertyName +impl< T > syn::parse::Parse for AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let value : syn::Ident = input.parse()?; + let value : T = input.parse()?; Ok( value.into() ) } } -impl AsRef< Option< syn::Ident > > for AttributePropertyName +// xxx +impl< T > quote::ToTokens for AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens +{ + fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) + { + self.0.to_tokens( tokens ); + } +} + +impl< T > AsRef< Option< T > > for AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens { #[ inline( always ) ] - fn as_ref( &self ) -> &Option< syn::Ident > + fn as_ref( &self ) -> &Option< T > { &self.0 } } -impl From< syn::Ident > for AttributePropertyName +impl< T > From< T > for AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens { #[ inline( always ) ] - fn from( src : syn::Ident ) -> Self + fn from( src : T ) -> Self { Self( Some( src ) ) } } -impl From< Option< syn::Ident > > for AttributePropertyName +impl< T > From< Option< T > > for AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens { #[ inline( always ) ] - fn from( src : Option< syn::Ident > ) -> Self + fn from( src : Option< T > ) -> Self { Self( src ) } } -impl From< AttributePropertyName > for Option< syn::Ident > +impl< T > From< AttributePropertyOptionalSyn< T > > for Option< T > +where T : syn::parse::Parse + quote::ToTokens { #[ inline( always ) ] - fn from( src : AttributePropertyName ) -> Self + fn from( src : AttributePropertyOptionalSyn< T > ) -> Self { src.0 } } -impl< 'a > From< &'a AttributePropertyName > for Option< &'a syn::Ident > +impl< 'a, T > From< &'a AttributePropertyOptionalSyn< T > > for Option< &'a T > +where T : syn::parse::Parse + quote::ToTokens { #[ inline( always ) ] - fn from( src : &'a AttributePropertyName ) -> Self + fn from( src : &'a AttributePropertyOptionalSyn< T > ) -> Self { src.0.as_ref() } From 2c06be23ac4ebc28287d8f405a5f62f50f08d6ce Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 09:45:54 +0300 Subject: [PATCH 30/44] former : refactoring parsing --- .../former_meta/src/derive_former/field.rs | 20 +- .../src/derive_former/field_attrs.rs | 206 ++++++------------ .../src/derive_former/struct_attrs.rs | 10 + 3 files changed, 90 insertions(+), 146 deletions(-) diff --git a/module/core/former_meta/src/derive_former/field.rs b/module/core/former_meta/src/derive_former/field.rs index 2bb6a09d6a..015eba4a1c 100644 --- a/module/core/former_meta/src/derive_former/field.rs +++ b/module/core/former_meta/src/derive_former/field.rs @@ -184,7 +184,7 @@ scalar_setter_required let ident = self.ident; let ty = self.ty; let default : Option< &syn::Expr > = self.attrs.config.as_ref() - .and_then( | attr | attr.default.into().as_ref() ); + .and_then( | attr | attr.default.ref_internal() ); let tokens = if self.is_optional { @@ -456,7 +456,7 @@ scalar_setter_required let setter_name = self.scalar_setter_name(); let attr = self.attrs.scalar.as_ref(); - if attr.is_some() && attr.unwrap().hint + if attr.is_some() && attr.unwrap().hint.into() { let hint = format! ( @@ -682,7 +682,7 @@ field : {field_ident}"#, qt!{} }; - if attr.hint + if attr.hint.into() { let hint = format! ( @@ -725,7 +725,7 @@ field : {field_ident}"#, }; // example : `former::VectorDefinition`` - let subformer_definition = &self.attrs.subform_collection.as_ref().unwrap().definition; + let subformer_definition = self.attrs.subform_collection.as_ref().unwrap().definition.ref_internal(); let subform_collection_end_doc = format! ( @@ -1285,7 +1285,7 @@ former and end action types, ensuring a seamless developer experience when formi setters_code }; - if attr.hint + if attr.hint.into() { let hint = format! ( @@ -1451,7 +1451,7 @@ Essentially, this end action integrates the individually formed scalar value bac { if let Some( ref attr ) = self.attrs.scalar { - if let Some( ref name ) = attr.name + if let Some( ref name ) = attr.name.ref_internal() { return name } @@ -1466,7 +1466,7 @@ Essentially, this end action integrates the individually formed scalar value bac { if attr.setter() { - if let Some( ref name ) = attr.name + if let Some( ref name ) = attr.name.ref_internal() { return Some( &name ) } @@ -1486,7 +1486,7 @@ Essentially, this end action integrates the individually formed scalar value bac { if attr.setter() { - if let Some( ref name ) = attr.name + if let Some( ref name ) = attr.name.ref_internal() { return Some( &name ) } @@ -1526,7 +1526,7 @@ Essentially, this end action integrates the individually formed scalar value bac let mut explicit = false; if let Some( ref attr ) = self.attrs.scalar { - if let Some( setter ) = attr.setter + if let Some( setter ) = attr.setter.internal() { if setter == false { @@ -1534,7 +1534,7 @@ Essentially, this end action integrates the individually formed scalar value bac } explicit = true; } - if let Some( ref _name ) = attr.name + if let Some( ref _name ) = attr.name.ref_internal() { explicit = true; } 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 4814a293d6..353682b1ce 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -232,7 +232,7 @@ impl syn::parse::Parse for AttributeConfig } } - Ok( Self { default } ) + Ok( Self { default : default.into() } ) } } @@ -385,7 +385,7 @@ impl syn::parse::Parse for AttributeScalarSetter } } - Ok( Self { name, setter, hint } ) + Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into() } ) } } @@ -539,7 +539,7 @@ impl syn::parse::Parse for AttributeSubformScalarSetter } } - Ok( Self { name, setter, hint } ) + Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into() } ) } } @@ -712,7 +712,7 @@ impl syn::parse::Parse for AttributeSubformCollectionSetter } } - Ok( Self { name, setter, hint, definition } ) + Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into(), definition : definition.into() } ) } } @@ -951,6 +951,13 @@ pub struct AttributePropertyHint( bool ); impl AttributePropertyHint { const KEYWORD : &'static str = "hint"; + + /// Just unwrap, returning internal data. + pub fn internal( self ) -> bool + { + self.0 + } + } impl syn::parse::Parse for AttributePropertyHint @@ -990,6 +997,19 @@ pub struct AttributePropertySetter( Option< bool > ); impl AttributePropertySetter { const KEYWORD : &'static str = "setter"; + + /// Just unwrap, returning internal data. + pub fn internal( self ) -> Option< bool > + { + self.0 + } + + /// Returns Option< &bool > instead of &Option< bool > + pub fn ref_internal( &self ) -> Option< &bool > + { + self.0.as_ref() + } + } impl syn::parse::Parse for AttributePropertySetter @@ -1001,6 +1021,16 @@ impl syn::parse::Parse for AttributePropertySetter } } +impl core::ops::Deref for AttributePropertySetter +{ + type Target = Option< bool >; + #[ inline( always ) ] + fn deref( &self ) -> &Option< bool > + { + &self.0 + } +} + impl AsRef< Option< bool > > for AttributePropertySetter { #[ inline( always ) ] @@ -1037,144 +1067,37 @@ impl From< AttributePropertySetter > for Option< bool > } } -// // = AttributePropertyName -// -// /// An optional identifier that names the setter. It is parsed from inputs -// /// like `name = my_field`. -// #[ derive( Debug, Default, Clone ) ] -// pub struct AttributePropertyName( Option< syn::Ident > ); -// -// impl AttributePropertyName -// { -// const KEYWORD : &'static str = "name"; -// } -// -// impl syn::parse::Parse for AttributePropertyName -// { -// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > -// { -// let value : syn::Ident = input.parse()?; -// Ok( value.into() ) -// } -// } -// -// impl AsRef< Option< syn::Ident > > for AttributePropertyName -// { -// #[ inline( always ) ] -// fn as_ref( &self ) -> &Option< syn::Ident > -// { -// &self.0 -// } -// } -// -// impl From< syn::Ident > for AttributePropertyName -// { -// #[ inline( always ) ] -// fn from( src : syn::Ident ) -> Self -// { -// Self( Some( src ) ) -// } -// } -// -// impl From< Option< syn::Ident > > for AttributePropertyName -// { -// #[ inline( always ) ] -// fn from( src : Option< syn::Ident > ) -> Self -// { -// Self( src ) -// } -// } -// -// impl From< AttributePropertyName > for Option< syn::Ident > -// { -// #[ inline( always ) ] -// fn from( src : AttributePropertyName ) -> Self -// { -// src.0 -// } -// } -// -// impl< 'a > From< &'a AttributePropertyName > for Option< &'a syn::Ident > -// { -// #[ inline( always ) ] -// fn from( src : &'a AttributePropertyName ) -> Self -// { -// src.0.as_ref() -// } -// } -// -// // = AttributePropertyDefault -// -// /// Default value to use for a field. -// #[ derive( Debug, Default, Clone ) ] -// pub struct AttributePropertyDefault( Option< syn::Expr > ); -// -// impl AttributePropertyDefault -// { -// const KEYWORD : &'static str = "name"; -// } -// -// impl syn::parse::Parse for AttributePropertyDefault -// { -// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > -// { -// let value : syn::Expr = input.parse()?; -// Ok( value.into() ) -// } -// } -// -// impl AsRef< Option< syn::Expr > > for AttributePropertyDefault -// { -// #[ inline( always ) ] -// fn as_ref( &self ) -> &Option< syn::Expr > -// { -// &self.0 -// } -// } -// -// impl From< syn::Expr > for AttributePropertyDefault -// { -// #[ inline( always ) ] -// fn from( src : syn::Expr ) -> Self -// { -// Self( Some( src ) ) -// } -// } -// -// impl From< Option< syn::Expr > > for AttributePropertyDefault -// { -// #[ inline( always ) ] -// fn from( src : Option< syn::Expr > ) -> Self -// { -// Self( src ) -// } -// } -// -// impl From< AttributePropertyDefault > for Option< syn::Expr > -// { -// #[ inline( always ) ] -// fn from( src : AttributePropertyDefault ) -> Self -// { -// src.0 -// } -// } -// -// impl< 'a > From< &'a AttributePropertyDefault > for Option< &'a syn::Expr > -// { -// #[ inline( always ) ] -// fn from( src : &'a AttributePropertyDefault ) -> Self -// { -// src.0.as_ref() -// } -// } - // = AttributePropertyOptionalSyn /// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. -#[ derive( Debug, Default, Clone ) ] +#[ derive( Debug, Clone ) ] pub struct AttributePropertyOptionalSyn< T >( Option< T > ) where T : syn::parse::Parse + quote::ToTokens; +impl< T > Default for AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens +{ + fn default() -> Self + { + Self( None ) + } +} + +impl< T > AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens +{ + /// Just unwrap, returning internal data. + pub fn internal( self ) -> Option< T > + { + self.0 + } + /// Returns Option< &T > instead of &Option< T > + pub fn ref_internal( &self ) -> Option< &T > + { + self.0.as_ref() + } +} + impl< T > AttributePropertyOptionalSyn< T > where T : syn::parse::Parse + quote::ToTokens { @@ -1201,6 +1124,17 @@ where T : syn::parse::Parse + quote::ToTokens } } +impl< T > core::ops::Deref for AttributePropertyOptionalSyn< T > +where T : syn::parse::Parse + quote::ToTokens +{ + type Target = Option< T >; + #[ inline( always ) ] + fn deref( &self ) -> &Option< T > + { + &self.0 + } +} + impl< T > AsRef< Option< T > > for AttributePropertyOptionalSyn< T > where T : syn::parse::Parse + quote::ToTokens { 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 ca80649cc3..4cc2182769 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -440,6 +440,7 @@ impl syn::parse::Parse for AttributeMutator /// `#[ perform( fn after1< 'a >() -> Option< &'a str > ) ]` /// +// xxx : reuse more generic structure #[ derive( Debug ) ] pub struct AttributePerform { @@ -492,6 +493,8 @@ impl syn::parse::Parse for AttributePerform // xxx2 : qqq : continue and get it implemented for all entries of all attribures +// xxx : reuse more generic structure + /// Specifies whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] @@ -500,6 +503,13 @@ pub struct AttributePropertyHint( bool ); impl AttributePropertyHint { const KEYWORD : &'static str = "hint"; + + /// Just unwrap, returning internal data. + pub fn internal( self ) -> bool + { + self.0 + } + } impl syn::parse::Parse for AttributePropertyHint From e19102bf64a583873b7d6a33cdd67b25db2249bb Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 09:51:41 +0300 Subject: [PATCH 31/44] former : refactoring parsing --- module/core/former_meta/src/derive_former/struct_attrs.rs | 6 ++++++ 1 file changed, 6 insertions(+) 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 4cc2182769..51e22654fa 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -577,3 +577,9 @@ impl From< AttributePropertyCustom > for bool src.0 } } + +// = + +// xxx +// #[ derive( Debug, Default, Clone, Copy ) ] +// pub struct AttributePropertyBoolean< const KEYWORD : &'static str >( bool ); From d82ea1ca6e8b2f16e9dd35548f6b87c14dfb443a Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 11:30:37 +0300 Subject: [PATCH 32/44] former : refactoring parsing --- .../src/derive_former/struct_attrs.rs | 87 +++++++++---------- module/core/macro_tools/src/attr.rs | 26 +----- 2 files changed, 41 insertions(+), 72 deletions(-) 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 51e22654fa..3c0a7ffae1 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -1,54 +1,8 @@ use super::*; -use macro_tools::{ attr, Result }; +use macro_tools::{ attr, Result, AttributeComponent }; use former_types::{ ComponentAssign }; -/// Trait for components that can be constructed from a meta attribute. -/// -/// The `AttributeComponent` trait defines the interface for components that can be created -/// from a `syn::Attribute` meta item. Implementors of this trait are required to define -/// a constant `KEYWORD` that identifies the type of the component and a method `from_meta` -/// that handles the construction of the component from the given attribute. -/// -/// # Example -/// -/// ```ignore -/// struct MyComponent; -/// -/// impl AttributeComponent for MyComponent { -/// const KEYWORD: &'static str = "my_component"; -/// -/// fn from_meta(attr: &syn::Attribute) -> Result { -/// // Parsing logic here -/// } -/// } -/// ``` -pub trait AttributeComponent -where - Self : Sized, -{ - /// The keyword that identifies the component. - /// - /// This constant is used to match the attribute to the corresponding component. - /// Each implementor of this trait must provide a unique keyword for its type. - const KEYWORD : &'static str; - - /// Constructs the component from the given meta attribute. - /// - /// This method is responsible for parsing the provided `syn::Attribute` and - /// returning an instance of the component. If the attribute cannot be parsed - /// into the component, an error should be returned. - /// - /// # Parameters - /// - /// - `attr` : A reference to the `syn::Attribute` from which the component is to be constructed. - /// - /// # Returns - /// - /// A `Result` containing the constructed component if successful, or an error if the parsing fails. - fn from_meta( attr : &syn::Attribute ) -> Result< Self >; -} - /// Represents the attributes of a struct, including storage fields, mutator, and perform attributes. #[ derive( Debug, Default ) ] @@ -583,3 +537,42 @@ impl From< AttributePropertyCustom > for bool // xxx // #[ derive( Debug, Default, Clone, Copy ) ] // pub struct AttributePropertyBoolean< const KEYWORD : &'static str >( bool ); + +// = + +/// Generics bolean attirbute property. +/// Defaults to `false`. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributePropertyBoolean< const T : i32 >( bool ); + +impl< const T : i32 > AttributePropertyBoolean< T > +{ + const KEYWORD : &'static str = "custom"; +} + +impl< const T : i32 > syn::parse::Parse for AttributePropertyBoolean< T > +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } +} + +impl< const T : i32 > From< bool > for AttributePropertyBoolean< T > +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( src ) + } +} + +impl< const T : i32 > From< AttributePropertyBoolean< T > > for bool +{ + #[ inline( always ) ] + fn from( src : AttributePropertyBoolean< T > ) -> Self + { + src.0 + } +} diff --git a/module/core/macro_tools/src/attr.rs b/module/core/macro_tools/src/attr.rs index 78c05d7de4..243ce69cf2 100644 --- a/module/core/macro_tools/src/attr.rs +++ b/module/core/macro_tools/src/attr.rs @@ -321,31 +321,7 @@ pub( crate ) mod private } } -// /// -// /// Attribute and ident. -// /// -// -// // qqq : example? -// -// pub type AttributedIdent = Pair< Many< AttributesInner >, syn::Ident >; -// -// impl From< syn::Ident > for AttributedIdent -// { -// fn from( src : syn::Ident ) -> Self -// { -// Self( Vec::< AttributesInner >::new().into(), src ) -// } -// } -// -// impl From< AttributedIdent > for syn::Ident -// { -// fn from( src : AttributedIdent ) -> Self -// { -// src.1 -// } -// } - - /// Trait for components that can be constructed from a meta attribute. + /// Trait for components of strcuture aggregating attributes that can be constructed from a meta attribute. /// /// The `AttributeComponent` trait defines the interface for components that can be created /// from a `syn::Attribute` meta item. Implementors of this trait are required to define From 58f94986a55b48500eaae075c7c0a3aa37205cbc Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 12:23:26 +0300 Subject: [PATCH 33/44] former : refactoring parsing --- module/core/former_meta/src/derive_former.rs | 7 +- .../src/derive_former/attr_prop.rs | 59 ++++++++ .../src/derive_former/struct_attrs.rs | 130 ++---------------- module/core/macro_tools/src/attr.rs | 16 ++- 4 files changed, 89 insertions(+), 123 deletions(-) create mode 100644 module/core/former_meta/src/derive_former/attr_prop.rs diff --git a/module/core/former_meta/src/derive_former.rs b/module/core/former_meta/src/derive_former.rs index 776d639738..54e40ad182 100644 --- a/module/core/former_meta/src/derive_former.rs +++ b/module/core/former_meta/src/derive_former.rs @@ -6,11 +6,12 @@ use proc_macro2::TokenStream; // qqq : implement interfaces for other collections - -mod field; -use field::*; +mod attr_prop; +use attr_prop::*; mod field_attrs; use field_attrs::*; +mod field; +use field::*; mod struct_attrs; use struct_attrs::*; diff --git a/module/core/former_meta/src/derive_former/attr_prop.rs b/module/core/former_meta/src/derive_former/attr_prop.rs new file mode 100644 index 0000000000..16fb30ecde --- /dev/null +++ b/module/core/former_meta/src/derive_former/attr_prop.rs @@ -0,0 +1,59 @@ + +use super::*; +use macro_tools::{ AttributePropertyComponent }; + +/// Generics bolean attirbute property. +/// Defaults to `false`. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributePropertyBoolean< T >( bool, core::marker::PhantomData< T > ); + +impl< T > AttributePropertyComponent for AttributePropertyBoolean< T > +{ + const KEYWORD : &'static str = "custom"; +} + +impl< T > syn::parse::Parse for AttributePropertyBoolean< T > +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } +} + +impl< T > From< bool > for AttributePropertyBoolean< T > +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( src, Default::default() ) + } +} + +impl< T > From< AttributePropertyBoolean< T > > for bool +{ + #[ inline( always ) ] + fn from( src : AttributePropertyBoolean< T > ) -> Self + { + src.0 + } +} + +impl< T > core::ops::Deref for AttributePropertyBoolean< T > +{ + type Target = bool; + #[ inline( always ) ] + fn deref( &self ) -> &bool + { + &self.0 + } +} + +impl< T > AsRef< bool > for AttributePropertyBoolean< T > +{ + #[ inline( always ) ] + fn as_ref( &self ) -> &bool + { + &self.0 + } +} 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 3c0a7ffae1..8a4d1f0f72 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -1,6 +1,6 @@ use super::*; -use macro_tools::{ attr, Result, AttributeComponent }; +use macro_tools::{ attr, Result, AttributeComponent, AttributePropertyComponent }; use former_types::{ ComponentAssign }; /// Represents the attributes of a struct, including storage fields, mutator, and perform attributes. @@ -449,130 +449,22 @@ impl syn::parse::Parse for AttributePerform // xxx : reuse more generic structure -/// Specifies whether to provide a sketch as a hint. +/// Marker type for to attribute property to specify whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertyHint( bool ); - -impl AttributePropertyHint -{ - const KEYWORD : &'static str = "hint"; - - /// Just unwrap, returning internal data. - pub fn internal( self ) -> bool - { - self.0 - } - -} - -impl syn::parse::Parse for AttributePropertyHint -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : syn::LitBool = input.parse()?; - Ok( value.value.into() ) - } -} - -impl From< bool > for AttributePropertyHint -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( src ) - } -} +pub struct Hint; -impl From< AttributePropertyHint > for bool -{ - #[ inline( always ) ] - fn from( src : AttributePropertyHint ) -> Self - { - src.0 - } -} +/// Specifies whether to provide a sketch as a hint. +/// Defaults to `false`, which means no hint is provided unless explicitly requested. +pub type AttributePropertyHint = AttributePropertyBoolean< Hint >; // = -/// Indicates whether a custom code should be generated. +/// Marker type for to attribute property to indicates whether a custom code should be generated. /// Defaults to `false`, meaning no custom code is generated unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertyCustom( bool ); - -impl AttributePropertyCustom -{ - const KEYWORD : &'static str = "custom"; -} - -impl syn::parse::Parse for AttributePropertyCustom -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : syn::LitBool = input.parse()?; - Ok( value.value.into() ) - } -} - -impl From< bool > for AttributePropertyCustom -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( src ) - } -} - -impl From< AttributePropertyCustom > for bool -{ - #[ inline( always ) ] - fn from( src : AttributePropertyCustom ) -> Self - { - src.0 - } -} - -// = - -// xxx -// #[ derive( Debug, Default, Clone, Copy ) ] -// pub struct AttributePropertyBoolean< const KEYWORD : &'static str >( bool ); - -// = - -/// Generics bolean attirbute property. -/// Defaults to `false`. -#[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertyBoolean< const T : i32 >( bool ); - -impl< const T : i32 > AttributePropertyBoolean< T > -{ - const KEYWORD : &'static str = "custom"; -} +pub struct Custom; -impl< const T : i32 > syn::parse::Parse for AttributePropertyBoolean< T > -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : syn::LitBool = input.parse()?; - Ok( value.value.into() ) - } -} - -impl< const T : i32 > From< bool > for AttributePropertyBoolean< T > -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( src ) - } -} - -impl< const T : i32 > From< AttributePropertyBoolean< T > > for bool -{ - #[ inline( always ) ] - fn from( src : AttributePropertyBoolean< T > ) -> Self - { - src.0 - } -} +/// Indicates whether a custom code should be generated. +/// Defaults to `false`, meaning no custom code is generated unless explicitly requested. +pub type AttributePropertyCustom = AttributePropertyBoolean< Custom >; diff --git a/module/core/macro_tools/src/attr.rs b/module/core/macro_tools/src/attr.rs index 243ce69cf2..a0bb4fbd30 100644 --- a/module/core/macro_tools/src/attr.rs +++ b/module/core/macro_tools/src/attr.rs @@ -346,6 +346,7 @@ pub( crate ) mod private /// } /// } /// ``` + /// xxx : improve documentation pub trait AttributeComponent where Self : Sized, @@ -372,6 +373,18 @@ pub( crate ) mod private fn from_meta( attr : &syn::Attribute ) -> Result< Self >; } + /// xxx : write documentation + pub trait AttributePropertyComponent + where + Self : Sized, + { + /// The keyword that identifies the component. + /// + /// This constant is used to match the attribute to the corresponding component. + /// Each implementor of this trait must provide a unique keyword for its type. + const KEYWORD : &'static str; + } + } #[ doc( inline ) ] @@ -415,8 +428,9 @@ pub mod exposed { AttributesInner, AttributesOuter, - // AttributedIdent, + AttributeComponent, + AttributePropertyComponent, }; } From f69a3f8644437c1632092a19384d1654bc9e2625 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 14:13:17 +0300 Subject: [PATCH 34/44] former : refactoring parsing --- .../src/derive_former/attr_prop.rs | 134 +++++++++++++- .../src/derive_former/field_attrs.rs | 173 +++++------------- 2 files changed, 169 insertions(+), 138 deletions(-) diff --git a/module/core/former_meta/src/derive_former/attr_prop.rs b/module/core/former_meta/src/derive_former/attr_prop.rs index 16fb30ecde..bd7179f042 100644 --- a/module/core/former_meta/src/derive_former/attr_prop.rs +++ b/module/core/former_meta/src/derive_former/attr_prop.rs @@ -5,14 +5,14 @@ use macro_tools::{ AttributePropertyComponent }; /// Generics bolean attirbute property. /// Defaults to `false`. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertyBoolean< T >( bool, core::marker::PhantomData< T > ); +pub struct AttributePropertyBoolean< Marker >( bool, ::core::marker::PhantomData< Marker > ); -impl< T > AttributePropertyComponent for AttributePropertyBoolean< T > +impl< Marker > AttributePropertyComponent for AttributePropertyBoolean< Marker > { const KEYWORD : &'static str = "custom"; } -impl< T > syn::parse::Parse for AttributePropertyBoolean< T > +impl< Marker > syn::parse::Parse for AttributePropertyBoolean< Marker > { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { @@ -21,7 +21,7 @@ impl< T > syn::parse::Parse for AttributePropertyBoolean< T > } } -impl< T > From< bool > for AttributePropertyBoolean< T > +impl< Marker > From< bool > for AttributePropertyBoolean< Marker > { #[ inline( always ) ] fn from( src : bool ) -> Self @@ -30,16 +30,16 @@ impl< T > From< bool > for AttributePropertyBoolean< T > } } -impl< T > From< AttributePropertyBoolean< T > > for bool +impl< Marker > From< AttributePropertyBoolean< Marker > > for bool { #[ inline( always ) ] - fn from( src : AttributePropertyBoolean< T > ) -> Self + fn from( src : AttributePropertyBoolean< Marker > ) -> Self { src.0 } } -impl< T > core::ops::Deref for AttributePropertyBoolean< T > +impl< Marker > core::ops::Deref for AttributePropertyBoolean< Marker > { type Target = bool; #[ inline( always ) ] @@ -49,7 +49,7 @@ impl< T > core::ops::Deref for AttributePropertyBoolean< T > } } -impl< T > AsRef< bool > for AttributePropertyBoolean< T > +impl< Marker > AsRef< bool > for AttributePropertyBoolean< Marker > { #[ inline( always ) ] fn as_ref( &self ) -> &bool @@ -57,3 +57,121 @@ impl< T > AsRef< bool > for AttributePropertyBoolean< T > &self.0 } } + +// = AttributePropertyOptionalSyn + +/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. +#[ derive( Debug, Clone ) ] +pub struct AttributePropertyOptionalSyn< T, Marker >( Option< T >, ::core::marker::PhantomData< Marker > ) +where T : syn::parse::Parse + quote::ToTokens; + +impl< T, Marker > Default for AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + fn default() -> Self + { + Self( None, Default::default() ) + } +} + +impl< T, Marker > AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + /// Just unwrap, returning internal data. + pub fn internal( self ) -> Option< T > + { + self.0 + } + /// Returns Option< &T > instead of &Option< T > + pub fn ref_internal( &self ) -> Option< &T > + { + self.0.as_ref() + } +} + +// impl< T, Marker > AttributePropertyOptionalSyn< T, Marker > +// where T : syn::parse::Parse + quote::ToTokens +// { +// const KEYWORD : &'static str = "name"; +// } + +impl< T, Marker > syn::parse::Parse for AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : T = input.parse()?; + Ok( value.into() ) + } +} + +// xxx +impl< T, Marker > quote::ToTokens for AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) + { + self.0.to_tokens( tokens ); + } +} + +impl< T, Marker > core::ops::Deref for AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + type Target = Option< T >; + #[ inline( always ) ] + fn deref( &self ) -> &Option< T > + { + &self.0 + } +} + +impl< T, Marker > AsRef< Option< T > > for AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + #[ inline( always ) ] + fn as_ref( &self ) -> &Option< T > + { + &self.0 + } +} + +impl< T, Marker > From< T > for AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + #[ inline( always ) ] + fn from( src : T ) -> Self + { + Self( Some( src ), Default::default() ) + } +} + +impl< T, Marker > From< Option< T > > for AttributePropertyOptionalSyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + #[ inline( always ) ] + fn from( src : Option< T > ) -> Self + { + Self( src, Default::default() ) + } +} + +impl< T, Marker > From< AttributePropertyOptionalSyn< T, Marker > > for Option< T > +where T : syn::parse::Parse + quote::ToTokens +{ + #[ inline( always ) ] + fn from( src : AttributePropertyOptionalSyn< T, Marker > ) -> Self + { + src.0 + } +} + +impl< 'a, T, Marker > From< &'a AttributePropertyOptionalSyn< T, Marker > > for Option< &'a T > +where T : syn::parse::Parse + quote::ToTokens +{ + #[ inline( always ) ] + fn from( src : &'a AttributePropertyOptionalSyn< T, Marker > ) -> Self + { + src.0.as_ref() + } +} 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 353682b1ce..dc7ab434ab 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -1,6 +1,6 @@ use super::*; -use macro_tools::{ attr, Result }; +use macro_tools::{ attr, Result, AttributePropertyComponent }; use former_types::{ ComponentAssign }; // xxx : document @@ -143,8 +143,7 @@ pub struct AttributeConfig { /// Default value to use for a field. - pub default : AttributePropertyOptionalSyn< syn::Expr >, - // pub default : Option< syn::Expr >, + pub default : AttributePropertyDefault, } @@ -182,9 +181,9 @@ where } } -impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Expr >, IntoT > for AttributeConfig +impl< IntoT > ComponentAssign< AttributePropertyDefault, IntoT > for AttributeConfig where - IntoT : Into< AttributePropertyOptionalSyn< syn::Expr > >, + IntoT : Into< AttributePropertyDefault >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -252,7 +251,7 @@ impl syn::parse::Parse for AttributeConfig pub struct AttributeScalarSetter { /// Optional identifier for naming the setter. - pub name : AttributePropertyOptionalSyn< syn::Ident >, + pub name : AttributePropertyName, /// Controls the generation of a setter method. If false, a setter method is not generated. pub setter : AttributePropertySetter, /// Specifies whether to provide a sketch of the subform setter as a hint. @@ -301,9 +300,9 @@ where } } -impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeScalarSetter +impl< IntoT > ComponentAssign< AttributePropertyName, IntoT > for AttributeScalarSetter where - IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, + IntoT : Into< AttributePropertyName >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -406,7 +405,7 @@ impl syn::parse::Parse for AttributeScalarSetter pub struct AttributeSubformScalarSetter { /// Optional identifier for naming the setter. - pub name : AttributePropertyOptionalSyn< syn::Ident >, + pub name : AttributePropertyName, /// Controls the generation of a setter method. If false, a setter method is not generated. pub setter : AttributePropertySetter, /// Specifies whether to provide a sketch of the subform setter as a hint. @@ -455,9 +454,9 @@ where } } -impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeSubformScalarSetter +impl< IntoT > ComponentAssign< AttributePropertyName, IntoT > for AttributeSubformScalarSetter where - IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, + IntoT : Into< AttributePropertyName >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -560,11 +559,11 @@ impl syn::parse::Parse for AttributeSubformScalarSetter pub struct AttributeSubformCollectionSetter { /// Optional identifier for naming the setter. - pub name : AttributePropertyOptionalSyn< syn::Ident >, + pub name : AttributePropertyName, /// Controls the generation of a setter method. If false, a setter method is not generated. pub setter : AttributePropertySetter, /// Definition of the collection former to use, e.g., `former::VectorFormer`. - pub definition : AttributePropertyOptionalSyn< syn::Type >, + pub definition : AttributePropertyDefinition, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. pub hint : AttributePropertyHint, @@ -611,9 +610,9 @@ where } } -impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeSubformCollectionSetter +impl< IntoT > ComponentAssign< AttributePropertyName, IntoT > for AttributeSubformCollectionSetter where - IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, + IntoT : Into< AttributePropertyName >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -633,9 +632,9 @@ where } } -impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Type >, IntoT > for AttributeSubformCollectionSetter +impl< IntoT > ComponentAssign< AttributePropertyDefinition, IntoT > for AttributeSubformCollectionSetter where - IntoT : Into< AttributePropertyOptionalSyn< syn::Type > >, + IntoT : Into< AttributePropertyDefinition >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -739,15 +738,12 @@ pub struct AttributeSubformEntrySetter { /// An optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. - // pub name : Option< syn::Ident >, - pub name : AttributePropertyOptionalSyn< syn::Ident >, + pub name : AttributePropertyName, /// Disable generation of setter. /// It still generate `_field_subform_entry` method, so it could be used to make a setter with custom arguments. - // pub setter : Option< bool >, pub setter : AttributePropertySetter, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. - // pub hint : bool, pub hint : AttributePropertyHint, } @@ -791,9 +787,9 @@ where } } -impl< IntoT > ComponentAssign< AttributePropertyOptionalSyn< syn::Ident >, IntoT > for AttributeSubformEntrySetter +impl< IntoT > ComponentAssign< AttributePropertyName, IntoT > for AttributeSubformEntrySetter where - IntoT : Into< AttributePropertyOptionalSyn< syn::Ident > >, + IntoT : Into< AttributePropertyName >, { #[ inline( always ) ] fn assign( &mut self, component : IntoT ) @@ -835,7 +831,7 @@ impl syn::parse::Parse for AttributeSubformEntrySetter let known = const_format::concatcp! ( "Known entries of attribute ", AttributeSubformEntrySetter::KEYWORD, " are : ", - AttributePropertyOptionalSyn::< syn::Ident >::KEYWORD, + AttributePropertyName::KEYWORD, ", ", AttributePropertySetter::KEYWORD, ", ", AttributePropertyHint::KEYWORD, ".", @@ -862,7 +858,7 @@ impl syn::parse::Parse for AttributeSubformEntrySetter match ident.to_string().as_str() { // xxx - AttributePropertyOptionalSyn::< syn::Ident >::KEYWORD => result.assign( AttributePropertyOptionalSyn::< syn::Ident >::parse( input )? ), + AttributePropertyName::KEYWORD => result.assign( AttributePropertyName::parse( input )? ), AttributePropertySetter::KEYWORD => result.assign( AttributePropertySetter::parse( input )? ), AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), _ => return Err( error( &ident ) ), @@ -1067,122 +1063,39 @@ impl From< AttributePropertySetter > for Option< bool > } } -// = AttributePropertyOptionalSyn +// = -/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. -#[ derive( Debug, Clone ) ] -pub struct AttributePropertyOptionalSyn< T >( Option< T > ) -where T : syn::parse::Parse + quote::ToTokens; - -impl< T > Default for AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - fn default() -> Self - { - Self( None ) - } -} +/// Marker type for attribute property of optional identifier that names the setter. It is parsed from inputs +/// like `name = my_field`. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct Name; -impl< T > AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - /// Just unwrap, returning internal data. - pub fn internal( self ) -> Option< T > - { - self.0 - } - /// Returns Option< &T > instead of &Option< T > - pub fn ref_internal( &self ) -> Option< &T > - { - self.0.as_ref() - } -} +/// An optional identifier that names the setter. It is parsed from inputs +/// like `name = my_field`. +pub type AttributePropertyName = AttributePropertyOptionalSyn< syn::Ident, Name >; -impl< T > AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens +impl AttributePropertyComponent for AttributePropertyOptionalSyn< syn::Ident, Name > { const KEYWORD : &'static str = "name"; } -impl< T > syn::parse::Parse for AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : T = input.parse()?; - Ok( value.into() ) - } -} - -// xxx -impl< T > quote::ToTokens for AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) - { - self.0.to_tokens( tokens ); - } -} - -impl< T > core::ops::Deref for AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - type Target = Option< T >; - #[ inline( always ) ] - fn deref( &self ) -> &Option< T > - { - &self.0 - } -} +// = -impl< T > AsRef< Option< T > > for AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn as_ref( &self ) -> &Option< T > - { - &self.0 - } -} +/// Marker type for default value to use for a field. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct DefaultValue; -impl< T > From< T > for AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : T ) -> Self - { - Self( Some( src ) ) - } -} +/// An optional identifier that names the setter. It is parsed from inputs +/// like `name = my_field`. +pub type AttributePropertyDefault = AttributePropertyOptionalSyn< syn::Expr, DefaultValue >; -impl< T > From< Option< T > > for AttributePropertyOptionalSyn< T > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : Option< T > ) -> Self - { - Self( src ) - } -} +// = -impl< T > From< AttributePropertyOptionalSyn< T > > for Option< T > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : AttributePropertyOptionalSyn< T > ) -> Self - { - src.0 - } -} +/// Marker type for definition of the collection former to use, e.g., `former::VectorFormer`. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct Definition; -impl< 'a, T > From< &'a AttributePropertyOptionalSyn< T > > for Option< &'a T > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : &'a AttributePropertyOptionalSyn< T > ) -> Self - { - src.0.as_ref() - } -} +/// Definition of the collection former to use, e.g., `former::VectorFormer`. +pub type AttributePropertyDefinition = AttributePropertyOptionalSyn< syn::Type, Definition >; // xxx2 : continue From 9020dc2a469f1649bbdfcac6f863b8ddd3434feb Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 17:35:05 +0300 Subject: [PATCH 35/44] former : refactoring parsing --- .../src/derive_former/attr_prop.rs | 153 +++++++++++++-- .../src/derive_former/field_attrs.rs | 178 ++++++++++-------- .../src/derive_former/struct_attrs.rs | 18 +- 3 files changed, 250 insertions(+), 99 deletions(-) diff --git a/module/core/former_meta/src/derive_former/attr_prop.rs b/module/core/former_meta/src/derive_former/attr_prop.rs index bd7179f042..0544ee2197 100644 --- a/module/core/former_meta/src/derive_former/attr_prop.rs +++ b/module/core/former_meta/src/derive_former/attr_prop.rs @@ -2,14 +2,40 @@ use super::*; use macro_tools::{ AttributePropertyComponent }; +/* + +AttributePropertyBoolean +AttributePropertyOptionalBoolean +AttributePropertyOptionalSyn + +*/ + +// = AttributePropertyBoolean + /// Generics bolean attirbute property. /// Defaults to `false`. #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyBoolean< Marker >( bool, ::core::marker::PhantomData< Marker > ); +impl< Marker > AttributePropertyBoolean< Marker > +{ + /// Just unwrap, returning internal data. + pub fn internal( self ) -> bool + { + self.0 + } + /// Returns Option< &T > instead of &Option< T > + pub fn ref_internal( &self ) -> &bool + { + &self.0 + } +} + impl< Marker > AttributePropertyComponent for AttributePropertyBoolean< Marker > +where + Marker : AttributePropertyComponent, { - const KEYWORD : &'static str = "custom"; + const KEYWORD : &'static str = Marker::KEYWORD; } impl< Marker > syn::parse::Parse for AttributePropertyBoolean< Marker > @@ -58,24 +84,101 @@ impl< Marker > AsRef< bool > for AttributePropertyBoolean< Marker > } } -// = AttributePropertyOptionalSyn +// = AttributePropertyOptionalBoolean -/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. -#[ derive( Debug, Clone ) ] -pub struct AttributePropertyOptionalSyn< T, Marker >( Option< T >, ::core::marker::PhantomData< Marker > ) -where T : syn::parse::Parse + quote::ToTokens; +/// Generics optional bolean attirbute property: `Option< bool >`. +/// Defaults to `false`. +#[ derive( Debug, Default, Clone, Copy ) ] +pub struct AttributePropertyOptionalBoolean< Marker >( Option< bool >, ::core::marker::PhantomData< Marker > ); -impl< T, Marker > Default for AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens +impl< Marker > AttributePropertyOptionalBoolean< Marker > { - fn default() -> Self + /// Just unwrap, returning internal data. + pub fn internal( self ) -> Option< bool > { - Self( None, Default::default() ) + self.0 + } + /// Returns Option< &T > instead of &Option< T > + pub fn ref_internal( &self ) -> Option< &bool > + { + self.0.as_ref() + } +} + +impl< Marker > AttributePropertyComponent for AttributePropertyOptionalBoolean< Marker > +where + Marker : AttributePropertyComponent, +{ + const KEYWORD : &'static str = Marker::KEYWORD; +} + +impl< Marker > syn::parse::Parse for AttributePropertyOptionalBoolean< Marker > +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) } } +impl< Marker > From< bool > for AttributePropertyOptionalBoolean< Marker > +{ + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( Some( src ), Default::default() ) + } +} + +impl< Marker > From< Option< bool > > for AttributePropertyOptionalBoolean< Marker > +{ + #[ inline( always ) ] + fn from( src : Option< bool > ) -> Self + { + Self( src, Default::default() ) + } +} + +impl< Marker > From< AttributePropertyOptionalBoolean< Marker > > for Option< bool > +{ + #[ inline( always ) ] + fn from( src : AttributePropertyOptionalBoolean< Marker > ) -> Self + { + src.0 + } +} + +impl< Marker > core::ops::Deref for AttributePropertyOptionalBoolean< Marker > +{ + type Target = Option< bool >; + #[ inline( always ) ] + fn deref( &self ) -> &Option< bool > + { + &self.0 + } +} + +impl< Marker > AsRef< Option< bool > > for AttributePropertyOptionalBoolean< Marker > +{ + #[ inline( always ) ] + fn as_ref( &self ) -> &Option< bool > + { + &self.0 + } +} + +// = AttributePropertyOptionalSyn + +/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. +#[ derive( Debug, Clone ) ] +pub struct AttributePropertyOptionalSyn< T, Marker >( Option< T >, ::core::marker::PhantomData< Marker > ) +where + T : syn::parse::Parse + quote::ToTokens, +; + impl< T, Marker > AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens +where + T : syn::parse::Parse + quote::ToTokens, { /// Just unwrap, returning internal data. pub fn internal( self ) -> Option< T > @@ -89,14 +192,27 @@ where T : syn::parse::Parse + quote::ToTokens } } -// impl< T, Marker > AttributePropertyOptionalSyn< T, Marker > -// where T : syn::parse::Parse + quote::ToTokens -// { -// const KEYWORD : &'static str = "name"; -// } +impl< T, Marker > AttributePropertyComponent for AttributePropertyOptionalSyn< T, Marker > +where + T : syn::parse::Parse + quote::ToTokens, + Marker : AttributePropertyComponent, +{ + const KEYWORD : &'static str = Marker::KEYWORD; +} + +impl< T, Marker > Default for AttributePropertyOptionalSyn< T, Marker > +where + T : syn::parse::Parse + quote::ToTokens, +{ + fn default() -> Self + { + Self( None, Default::default() ) + } +} impl< T, Marker > syn::parse::Parse for AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens +where + T : syn::parse::Parse + quote::ToTokens, { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { @@ -107,7 +223,8 @@ where T : syn::parse::Parse + quote::ToTokens // xxx impl< T, Marker > quote::ToTokens for AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens +where + T : syn::parse::Parse + quote::ToTokens, { fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) { 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 dc7ab434ab..1764dac821 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -983,98 +983,112 @@ impl From< AttributePropertyHint > for bool } } -// = AttributePropertySetter +// = Marker type for AttributePropertySetter /// Disable generation of setter. /// Attributes still might generate some helper methods to reuse by custom setter. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertySetter( Option< bool > ); +pub struct AttributePropertySetterMarker; -impl AttributePropertySetter -{ - const KEYWORD : &'static str = "setter"; - - /// Just unwrap, returning internal data. - pub fn internal( self ) -> Option< bool > - { - self.0 - } - - /// Returns Option< &bool > instead of &Option< bool > - pub fn ref_internal( &self ) -> Option< &bool > - { - self.0.as_ref() - } - -} - -impl syn::parse::Parse for AttributePropertySetter -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : syn::LitBool = input.parse()?; - Ok( value.value.into() ) - } -} - -impl core::ops::Deref for AttributePropertySetter -{ - type Target = Option< bool >; - #[ inline( always ) ] - fn deref( &self ) -> &Option< bool > - { - &self.0 - } -} - -impl AsRef< Option< bool > > for AttributePropertySetter -{ - #[ inline( always ) ] - fn as_ref( &self ) -> &Option< bool > - { - &self.0 - } -} - -impl From< bool > for AttributePropertySetter -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( Some( src ) ) - } -} +/// Disable generation of setter. +/// Attributes still might generate some helper methods to reuse by custom setter. +pub type AttributePropertySetter = AttributePropertyOptionalBoolean< AttributePropertySetterMarker >; -impl From< Option< bool > > for AttributePropertySetter +impl AttributePropertyComponent for AttributePropertySetter { - #[ inline( always ) ] - fn from( src : Option< bool > ) -> Self - { - Self( src ) - } + const KEYWORD : &'static str = "setter"; } -impl From< AttributePropertySetter > for Option< bool > -{ - #[ inline( always ) ] - fn from( src : AttributePropertySetter ) -> Self - { - src.0 - } -} +// /// Disable generation of setter. +// /// Attributes still might generate some helper methods to reuse by custom setter. +// #[ derive( Debug, Default, Clone, Copy ) ] +// pub struct AttributePropertySetter( Option< bool > ); +// +// impl AttributePropertySetter +// { +// const KEYWORD : &'static str = "setter"; +// +// /// Just unwrap, returning internal data. +// pub fn internal( self ) -> Option< bool > +// { +// self.0 +// } +// +// /// Returns Option< &bool > instead of &Option< bool > +// pub fn ref_internal( &self ) -> Option< &bool > +// { +// self.0.as_ref() +// } +// +// } +// +// impl syn::parse::Parse for AttributePropertySetter +// { +// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +// { +// let value : syn::LitBool = input.parse()?; +// Ok( value.value.into() ) +// } +// } +// +// impl core::ops::Deref for AttributePropertySetter +// { +// type Target = Option< bool >; +// #[ inline( always ) ] +// fn deref( &self ) -> &Option< bool > +// { +// &self.0 +// } +// } +// +// impl AsRef< Option< bool > > for AttributePropertySetter +// { +// #[ inline( always ) ] +// fn as_ref( &self ) -> &Option< bool > +// { +// &self.0 +// } +// } +// +// impl From< bool > for AttributePropertySetter +// { +// #[ inline( always ) ] +// fn from( src : bool ) -> Self +// { +// Self( Some( src ) ) +// } +// } +// +// impl From< Option< bool > > for AttributePropertySetter +// { +// #[ inline( always ) ] +// fn from( src : Option< bool > ) -> Self +// { +// Self( src ) +// } +// } +// +// impl From< AttributePropertySetter > for Option< bool > +// { +// #[ inline( always ) ] +// fn from( src : AttributePropertySetter ) -> Self +// { +// src.0 +// } +// } // = /// Marker type for attribute property of optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct Name; +pub struct AttributePropertyNameMarker; /// An optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. -pub type AttributePropertyName = AttributePropertyOptionalSyn< syn::Ident, Name >; +pub type AttributePropertyName = AttributePropertyOptionalSyn< syn::Ident, AttributePropertyNameMarker >; -impl AttributePropertyComponent for AttributePropertyOptionalSyn< syn::Ident, Name > +impl AttributePropertyComponent for AttributePropertyName { const KEYWORD : &'static str = "name"; } @@ -1083,19 +1097,29 @@ impl AttributePropertyComponent for AttributePropertyOptionalSyn< syn::Ident, Na /// Marker type for default value to use for a field. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct DefaultValue; +pub struct AttributePropertyDefaultMarker; /// An optional identifier that names the setter. It is parsed from inputs /// like `name = my_field`. -pub type AttributePropertyDefault = AttributePropertyOptionalSyn< syn::Expr, DefaultValue >; +pub type AttributePropertyDefault = AttributePropertyOptionalSyn< syn::Expr, AttributePropertyDefaultMarker >; + +impl AttributePropertyComponent for AttributePropertyDefault +{ + const KEYWORD : &'static str = "default"; +} // = /// Marker type for definition of the collection former to use, e.g., `former::VectorFormer`. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct Definition; +pub struct AttributePropertyDefinitionMarker; /// Definition of the collection former to use, e.g., `former::VectorFormer`. -pub type AttributePropertyDefinition = AttributePropertyOptionalSyn< syn::Type, Definition >; +pub type AttributePropertyDefinition = AttributePropertyOptionalSyn< syn::Type, AttributePropertyDefinitionMarker >; + +impl AttributePropertyComponent for AttributePropertyDefinition +{ + const KEYWORD : &'static str = "component"; +} // xxx2 : continue 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 8a4d1f0f72..3bd95a5360 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -452,19 +452,29 @@ impl syn::parse::Parse for AttributePerform /// Marker type for to attribute property to specify whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct Hint; +pub struct AttributePropertyHintMarker; + +impl AttributePropertyComponent for AttributePropertyHintMarker +{ + const KEYWORD : &'static str = "hint"; +} /// Specifies whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. -pub type AttributePropertyHint = AttributePropertyBoolean< Hint >; +pub type AttributePropertyHint = AttributePropertyBoolean< AttributePropertyHintMarker >; // = /// Marker type for to attribute property to indicates whether a custom code should be generated. /// Defaults to `false`, meaning no custom code is generated unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct Custom; +pub struct AttributePropertyCustomMarker; + +impl AttributePropertyComponent for AttributePropertyCustomMarker +{ + const KEYWORD : &'static str = "custom"; +} /// Indicates whether a custom code should be generated. /// Defaults to `false`, meaning no custom code is generated unless explicitly requested. -pub type AttributePropertyCustom = AttributePropertyBoolean< Custom >; +pub type AttributePropertyCustom = AttributePropertyBoolean< AttributePropertyCustomMarker >; From 7f72f90ecf76a9387e2f0e6e3aebff6632c6b590 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 17:46:00 +0300 Subject: [PATCH 36/44] former : refactoring parsing --- .../src/derive_former/attr_prop.rs | 118 +++++++++++++++++- .../src/derive_former/field_attrs.rs | 114 +++-------------- 2 files changed, 135 insertions(+), 97 deletions(-) diff --git a/module/core/former_meta/src/derive_former/attr_prop.rs b/module/core/former_meta/src/derive_former/attr_prop.rs index 0544ee2197..9af98f61f1 100644 --- a/module/core/former_meta/src/derive_former/attr_prop.rs +++ b/module/core/former_meta/src/derive_former/attr_prop.rs @@ -6,6 +6,7 @@ use macro_tools::{ AttributePropertyComponent }; AttributePropertyBoolean AttributePropertyOptionalBoolean +AttributePropertySyn AttributePropertyOptionalSyn */ @@ -167,6 +168,122 @@ impl< Marker > AsRef< Option< bool > > for AttributePropertyOptionalBoolean< Mar } } +// = AttributePropertySyn + +/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. +#[ derive( Debug, Clone ) ] +pub struct AttributePropertySyn< T, Marker >( T, ::core::marker::PhantomData< Marker > ) +where + T : syn::parse::Parse + quote::ToTokens, +; + +impl< T, Marker > AttributePropertySyn< T, Marker > +where + T : syn::parse::Parse + quote::ToTokens, +{ + /// Just unwrap, returning internal data. + pub fn internal( self ) -> T + { + self.0 + } + /// Returns Option< &T > instead of &Option< T > + pub fn ref_internal( &self ) -> &T + { + &self.0 + } +} + +impl< T, Marker > AttributePropertyComponent for AttributePropertySyn< T, Marker > +where + T : syn::parse::Parse + quote::ToTokens, + Marker : AttributePropertyComponent, +{ + const KEYWORD : &'static str = Marker::KEYWORD; +} + +// xxx +// impl< T, Marker > Default for AttributePropertySyn< T, Marker > +// where +// T : syn::parse::Parse + quote::ToTokens, +// { +// fn default() -> Self +// { +// Self( Default::default(), Default::default() ) +// } +// } + +impl< T, Marker > syn::parse::Parse for AttributePropertySyn< T, Marker > +where + T : syn::parse::Parse + quote::ToTokens, +{ + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : T = input.parse()?; + Ok( value.into() ) + } +} + +impl< T, Marker > quote::ToTokens for AttributePropertySyn< T, Marker > +where + T : syn::parse::Parse + quote::ToTokens, +{ + fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) + { + self.0.to_tokens( tokens ); + } +} + +impl< T, Marker > core::ops::Deref for AttributePropertySyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + type Target = T; + #[ inline( always ) ] + fn deref( &self ) -> &T + { + &self.0 + } +} + +impl< T, Marker > AsRef< T > for AttributePropertySyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + #[ inline( always ) ] + fn as_ref( &self ) -> &T + { + &self.0 + } +} + +impl< T, Marker > From< T > for AttributePropertySyn< T, Marker > +where T : syn::parse::Parse + quote::ToTokens +{ + #[ inline( always ) ] + fn from( src : T ) -> Self + { + Self( src, Default::default() ) + } +} + +// impl< T, Marker > From< AttributePropertySyn< T, Marker > > for T +// where T : syn::parse::Parse + quote::ToTokens +// { +// #[ inline( always ) ] +// fn from( src : AttributePropertySyn< T, Marker > ) -> Self +// { +// src.0 +// } +// } + +// impl< 'a, T, Marker > From< &'a AttributePropertySyn< T, Marker > > for Option< &'a T > +// where T : syn::parse::Parse + quote::ToTokens +// { +// #[ inline( always ) ] +// fn from( src : &'a AttributePropertySyn< T, Marker > ) -> Self +// { +// &src.0 +// } +// } + // = AttributePropertyOptionalSyn /// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. @@ -221,7 +338,6 @@ where } } -// xxx impl< T, Marker > quote::ToTokens for AttributePropertyOptionalSyn< T, Marker > where T : syn::parse::Parse + quote::ToTokens, 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 1764dac821..6e11ac4ec9 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -990,92 +990,14 @@ impl From< AttributePropertyHint > for bool #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertySetterMarker; -/// Disable generation of setter. -/// Attributes still might generate some helper methods to reuse by custom setter. -pub type AttributePropertySetter = AttributePropertyOptionalBoolean< AttributePropertySetterMarker >; - -impl AttributePropertyComponent for AttributePropertySetter +impl AttributePropertyComponent for AttributePropertySetterMarker { const KEYWORD : &'static str = "setter"; } -// /// Disable generation of setter. -// /// Attributes still might generate some helper methods to reuse by custom setter. -// #[ derive( Debug, Default, Clone, Copy ) ] -// pub struct AttributePropertySetter( Option< bool > ); -// -// impl AttributePropertySetter -// { -// const KEYWORD : &'static str = "setter"; -// -// /// Just unwrap, returning internal data. -// pub fn internal( self ) -> Option< bool > -// { -// self.0 -// } -// -// /// Returns Option< &bool > instead of &Option< bool > -// pub fn ref_internal( &self ) -> Option< &bool > -// { -// self.0.as_ref() -// } -// -// } -// -// impl syn::parse::Parse for AttributePropertySetter -// { -// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > -// { -// let value : syn::LitBool = input.parse()?; -// Ok( value.value.into() ) -// } -// } -// -// impl core::ops::Deref for AttributePropertySetter -// { -// type Target = Option< bool >; -// #[ inline( always ) ] -// fn deref( &self ) -> &Option< bool > -// { -// &self.0 -// } -// } -// -// impl AsRef< Option< bool > > for AttributePropertySetter -// { -// #[ inline( always ) ] -// fn as_ref( &self ) -> &Option< bool > -// { -// &self.0 -// } -// } -// -// impl From< bool > for AttributePropertySetter -// { -// #[ inline( always ) ] -// fn from( src : bool ) -> Self -// { -// Self( Some( src ) ) -// } -// } -// -// impl From< Option< bool > > for AttributePropertySetter -// { -// #[ inline( always ) ] -// fn from( src : Option< bool > ) -> Self -// { -// Self( src ) -// } -// } -// -// impl From< AttributePropertySetter > for Option< bool > -// { -// #[ inline( always ) ] -// fn from( src : AttributePropertySetter ) -> Self -// { -// src.0 -// } -// } +/// Disable generation of setter. +/// Attributes still might generate some helper methods to reuse by custom setter. +pub type AttributePropertySetter = AttributePropertyOptionalBoolean< AttributePropertySetterMarker >; // = @@ -1084,42 +1006,42 @@ impl AttributePropertyComponent for AttributePropertySetter #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyNameMarker; -/// An optional identifier that names the setter. It is parsed from inputs -/// like `name = my_field`. -pub type AttributePropertyName = AttributePropertyOptionalSyn< syn::Ident, AttributePropertyNameMarker >; - -impl AttributePropertyComponent for AttributePropertyName +impl AttributePropertyComponent for AttributePropertyNameMarker { const KEYWORD : &'static str = "name"; } +/// An optional identifier that names the setter. It is parsed from inputs +/// like `name = my_field`. +pub type AttributePropertyName = AttributePropertyOptionalSyn< syn::Ident, AttributePropertyNameMarker >; + // = /// Marker type for default value to use for a field. #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyDefaultMarker; -/// An optional identifier that names the setter. It is parsed from inputs -/// like `name = my_field`. -pub type AttributePropertyDefault = AttributePropertyOptionalSyn< syn::Expr, AttributePropertyDefaultMarker >; - -impl AttributePropertyComponent for AttributePropertyDefault +impl AttributePropertyComponent for AttributePropertyDefaultMarker { const KEYWORD : &'static str = "default"; } +/// An optional identifier that names the setter. It is parsed from inputs +/// like `name = my_field`. +pub type AttributePropertyDefault = AttributePropertyOptionalSyn< syn::Expr, AttributePropertyDefaultMarker >; + // = /// Marker type for definition of the collection former to use, e.g., `former::VectorFormer`. #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyDefinitionMarker; -/// Definition of the collection former to use, e.g., `former::VectorFormer`. -pub type AttributePropertyDefinition = AttributePropertyOptionalSyn< syn::Type, AttributePropertyDefinitionMarker >; - -impl AttributePropertyComponent for AttributePropertyDefinition +impl AttributePropertyComponent for AttributePropertyDefinitionMarker { const KEYWORD : &'static str = "component"; } +/// Definition of the collection former to use, e.g., `former::VectorFormer`. +pub type AttributePropertyDefinition = AttributePropertyOptionalSyn< syn::Type, AttributePropertyDefinitionMarker >; + // xxx2 : continue From c028fa435ed68c548f5e426dd08b49520f414ce5 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 17:47:56 +0300 Subject: [PATCH 37/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 42 +++---------------- .../src/derive_former/struct_attrs.rs | 4 +- 2 files changed, 7 insertions(+), 39 deletions(-) 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 6e11ac4ec9..0e13203e64 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -939,48 +939,16 @@ impl syn::parse::Parse for AttributeSubformEntrySetter // = AttributePropertyHint -/// Specifies whether to provide a sketch as a hint. +/// Marker type for attribute property to specify whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertyHint( bool ); +pub struct AttributePropertyHintMarker; -impl AttributePropertyHint +/// Specifies whether to provide a sketch as a hint. +/// Defaults to `false`, which means no hint is provided unless explicitly requested. +impl AttributePropertyComponent for AttributePropertyHintMarker { const KEYWORD : &'static str = "hint"; - - /// Just unwrap, returning internal data. - pub fn internal( self ) -> bool - { - self.0 - } - -} - -impl syn::parse::Parse for AttributePropertyHint -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : syn::LitBool = input.parse()?; - Ok( value.value.into() ) - } -} - -impl From< bool > for AttributePropertyHint -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( src ) - } -} - -impl From< AttributePropertyHint > for bool -{ - #[ inline( always ) ] - fn from( src : AttributePropertyHint ) -> Self - { - src.0 - } } // = Marker type for AttributePropertySetter 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 3bd95a5360..dc6936809b 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -449,7 +449,7 @@ impl syn::parse::Parse for AttributePerform // xxx : reuse more generic structure -/// Marker type for to attribute property to specify whether to provide a sketch as a hint. +/// Marker type for attribute property to specify whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyHintMarker; @@ -465,7 +465,7 @@ pub type AttributePropertyHint = AttributePropertyBoolean< AttributePropertyHint // = -/// Marker type for to attribute property to indicates whether a custom code should be generated. +/// Marker type for attribute property to indicates whether a custom code should be generated. /// Defaults to `false`, meaning no custom code is generated unless explicitly requested. #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyCustomMarker; From 56b62a3c83e0e327a84dc165aad60b6ad8dd3fea Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 17:53:58 +0300 Subject: [PATCH 38/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 194 +++++++++--------- 1 file changed, 102 insertions(+), 92 deletions(-) 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 0e13203e64..6dfbf7346f 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -562,14 +562,14 @@ pub struct AttributeSubformCollectionSetter pub name : AttributePropertyName, /// Controls the generation of a setter method. If false, a setter method is not generated. pub setter : AttributePropertySetter, - /// Definition of the collection former to use, e.g., `former::VectorFormer`. - pub definition : AttributePropertyDefinition, /// Specifies whether to provide a sketch of the subform setter as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. pub hint : AttributePropertyHint, + /// Definition of the collection former to use, e.g., `former::VectorFormer`. + pub definition : AttributePropertyDefinition, } -// xxx +// xxx : use trait impl AttributeSubformCollectionSetter { @@ -658,10 +658,29 @@ impl syn::parse::Parse for AttributeSubformCollectionSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let mut name : Option< syn::Ident > = None; - let mut setter : Option< bool > = None; // Default is to generate a setter - let mut hint = false; - let mut definition : Option< syn::Type > = None; + let mut result = Self::default(); + + let error = | ident : &syn::Ident | -> syn::Error + { + let known = const_format::concatcp! + ( + "Known entries of attribute ", AttributeSubformCollectionSetter::KEYWORD, " are : ", + AttributePropertyName::KEYWORD, + ", ", AttributePropertySetter::KEYWORD, + ", ", AttributePropertyHint::KEYWORD, + ", ", AttributePropertyDefinition::KEYWORD, + ".", + ); + syn_err! + ( + ident, + r#"Expects an attribute of format '#[ subform_collection( name = myName, setter = true, hint = false, definition = MyDefinition ) ]' + {known} + But got: '{}' +"#, + qt!{ #ident } + ) + }; while !input.is_empty() { @@ -669,39 +688,20 @@ impl syn::parse::Parse for AttributeSubformCollectionSetter if lookahead.peek( syn::Ident ) { let ident : syn::Ident = input.parse()?; + + input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - "name" => - { - input.parse::< syn::Token![ = ] >()?; - name = Some( input.parse()? ); - } - "setter" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - setter = Some( value.value ); - } - "hint" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - hint = value.value; - } - "definition" => - { - input.parse::< syn::Token![ = ] >()?; - definition = Some( input.parse()? ); - } - _ => - { - return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `collection( name = myName, setter = true, definition = MyDefinition )`", ident ) ) ); - } + AttributePropertyName::KEYWORD => result.assign( AttributePropertyName::parse( input )? ), + AttributePropertySetter::KEYWORD => result.assign( AttributePropertySetter::parse( input )? ), + AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), + AttributePropertyDefinition::KEYWORD => result.assign( AttributePropertyDefinition::parse( input )? ), + _ => return Err( error( &ident ) ), } } else { - return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `collection( name = myName, setter = true, definition = MyDefinition )`" ) ); + return Err( lookahead.error() ); } // Optional comma handling @@ -711,10 +711,71 @@ impl syn::parse::Parse for AttributeSubformCollectionSetter } } - Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into(), definition : definition.into() } ) + Ok( result ) } } +// impl syn::parse::Parse for AttributeSubformCollectionSetter +// { +// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +// { +// let mut name : Option< syn::Ident > = None; +// let mut setter : Option< bool > = None; // Default is to generate a setter +// let mut hint = false; +// let mut definition : Option< syn::Type > = None; +// +// while !input.is_empty() +// { +// let lookahead = input.lookahead1(); +// if lookahead.peek( syn::Ident ) +// { +// let ident : syn::Ident = input.parse()?; +// match ident.to_string().as_str() +// { +// "name" => +// { +// input.parse::< syn::Token![ = ] >()?; +// name = Some( input.parse()? ); +// } +// "setter" => +// { +// input.parse::< syn::Token![ = ] >()?; +// let value : syn::LitBool = input.parse()?; +// setter = Some( value.value ); +// } +// "hint" => +// { +// input.parse::< syn::Token![ = ] >()?; +// let value : syn::LitBool = input.parse()?; +// hint = value.value; +// } +// "definition" => +// { +// input.parse::< syn::Token![ = ] >()?; +// definition = Some( input.parse()? ); +// } +// _ => +// { +// return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `collection( name = myName, setter = true, definition = MyDefinition )`", ident ) ) ); +// } +// } +// } +// else +// { +// return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `subform_collection( name = myName, setter = true, hint = false, definition = MyDefinition )`" ) ); +// } +// +// // Optional comma handling +// if input.peek( syn::Token![ , ] ) +// { +// input.parse::< syn::Token![ , ] >()?; +// } +// } +// +// Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into(), definition : definition.into() } ) +// } +// } + /// Represents a subform attribute to control subform setter generation. /// Used to specify extra options for using one former as subformer of another one. /// For example name of setter could be customized. @@ -747,6 +808,7 @@ pub struct AttributeSubformEntrySetter pub hint : AttributePropertyHint, } +// xxx : use trait impl AttributeSubformEntrySetter { @@ -857,7 +919,6 @@ impl syn::parse::Parse for AttributeSubformEntrySetter input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - // xxx AttributePropertyName::KEYWORD => result.assign( AttributePropertyName::parse( input )? ), AttributePropertySetter::KEYWORD => result.assign( AttributePropertySetter::parse( input )? ), AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), @@ -880,61 +941,6 @@ impl syn::parse::Parse for AttributeSubformEntrySetter } } -// impl syn::parse::Parse for AttributeSubformEntrySetter -// { -// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > -// { -// let mut name : Option< syn::Ident > = None; -// let mut setter : Option< bool > = None; -// let mut hint = false; -// -// while !input.is_empty() -// { -// let lookahead = input.lookahead1(); -// if lookahead.peek( syn::Ident ) -// { -// let ident : syn::Ident = input.parse()?; -// match ident.to_string().as_str() -// { -// "name" => -// { -// input.parse::< syn::Token![ = ] >()?; -// name = Some( input.parse()? ); -// } -// "setter" => -// { -// input.parse::< syn::Token![ = ] >()?; -// let value : syn::LitBool = input.parse()?; -// setter = Some( value.value() ); -// } -// "hint" => -// { -// input.parse::< syn::Token![ = ] >()?; -// let value : syn::LitBool = input.parse()?; -// hint = value.value; -// } -// _ => -// { -// return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `subform( name = myName, setter = true )`", ident ) ) ); -// } -// } -// } -// else -// { -// return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `subform( name = myName, setter = true )`" ) ); -// } -// -// // Optional comma handling -// if input.peek( syn::Token![ , ] ) -// { -// input.parse::< syn::Token![ , ] >()?; -// } -// } -// -// Ok( Self { name, setter, hint } ) -// } -// } - // == attribute entries // = AttributePropertyHint @@ -951,6 +957,10 @@ impl AttributePropertyComponent for AttributePropertyHintMarker const KEYWORD : &'static str = "hint"; } +/// Specifies whether to provide a sketch as a hint. +/// Defaults to `false`, which means no hint is provided unless explicitly requested. +pub type AttributePropertyHint = AttributePropertyBoolean< AttributePropertyHintMarker >; + // = Marker type for AttributePropertySetter /// Disable generation of setter. @@ -1006,7 +1016,7 @@ pub struct AttributePropertyDefinitionMarker; impl AttributePropertyComponent for AttributePropertyDefinitionMarker { - const KEYWORD : &'static str = "component"; + const KEYWORD : &'static str = "definition"; } /// Definition of the collection former to use, e.g., `former::VectorFormer`. From ae44ab6569a632a8469d7a23d005142947672aca Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 17:59:52 +0300 Subject: [PATCH 39/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 312 +++++++++++------- 1 file changed, 185 insertions(+), 127 deletions(-) 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 6dfbf7346f..8e80e957b3 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -192,12 +192,31 @@ where } } + impl syn::parse::Parse for AttributeConfig { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let mut default : Option< syn::Expr > = None; - // let mut only_storage : Option< bool > = None; + let mut result = Self::default(); + + let error = | ident : &syn::Ident | -> syn::Error + { + let known = const_format::concatcp! + ( + "Known entries of attribute ", AttributeConfig::KEYWORD, " are : ", + AttributePropertyDefault::KEYWORD, + ".", + ); + syn_err! + ( + ident, + r#"Expects an attribute of format '#[ former( default = 13 ) ]' + {known} + But got: '{}' +"#, + qt!{ #ident } + ) + }; while !input.is_empty() { @@ -205,23 +224,17 @@ impl syn::parse::Parse for AttributeConfig if lookahead.peek( syn::Ident ) { let ident : syn::Ident = input.parse()?; + + input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - "default" => - { - input.parse::< syn::Token![ = ] >()?; - default = Some( input.parse()? ); - } - _ => - { - return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'default'. For example: `former( default = 13 )`", ident ) ) ); - } + AttributePropertyDefault::KEYWORD => result.assign( AttributePropertyDefault::parse( input )? ), + _ => return Err( error( &ident ) ), } } - else { - return Err( syn::Error::new( input.span(), "Expected 'default'. For example: `former( default = 13 )`" ) ); + return Err( lookahead.error() ); } // Optional comma handling @@ -231,10 +244,53 @@ impl syn::parse::Parse for AttributeConfig } } - Ok( Self { default : default.into() } ) + Ok( result ) } } +// impl syn::parse::Parse for AttributeConfig +// { +// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +// { +// let mut default : Option< syn::Expr > = None; +// // let mut only_storage : Option< bool > = None; +// +// while !input.is_empty() +// { +// let lookahead = input.lookahead1(); +// if lookahead.peek( syn::Ident ) +// { +// let ident : syn::Ident = input.parse()?; +// match ident.to_string().as_str() +// { +// "default" => +// { +// input.parse::< syn::Token![ = ] >()?; +// default = Some( input.parse()? ); +// } +// _ => +// { +// return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'default'. For example: `former( default = 13 )`", ident ) ) ); +// } +// } +// } +// +// else +// { +// return Err( syn::Error::new( input.span(), "Expected 'default'. For example: `former( default = 13 )`" ) ); +// } +// +// // Optional comma handling +// if input.peek( syn::Token![ , ] ) +// { +// input.parse::< syn::Token![ , ] >()?; +// } +// } +// +// Ok( Self { default : default.into() } ) +// } +// } + /// /// Attribute to enable/disable scalar setter generation. /// @@ -337,9 +393,28 @@ impl syn::parse::Parse for AttributeScalarSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let mut name : Option< syn::Ident > = None; - let mut setter : Option< bool > = None; - let mut hint = false; + let mut result = Self::default(); + + let error = | ident : &syn::Ident | -> syn::Error + { + let known = const_format::concatcp! + ( + "Known entries of attribute ", AttributeScalarSetter::KEYWORD, " are : ", + AttributePropertyName::KEYWORD, + ", ", AttributePropertySetter::KEYWORD, + ", ", AttributePropertyHint::KEYWORD, + ".", + ); + syn_err! + ( + ident, + r#"Expects an attribute of format '#[ scalar( name = myName, setter = true, hint = false ) ]' + {known} + But got: '{}' +"#, + qt!{ #ident } + ) + }; while !input.is_empty() { @@ -347,34 +422,19 @@ impl syn::parse::Parse for AttributeScalarSetter if lookahead.peek( syn::Ident ) { let ident : syn::Ident = input.parse()?; + + input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - "name" => - { - input.parse::< syn::Token![ = ] >()?; - name = Some( input.parse()? ); - } - "setter" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - setter = Some( value.value() ); - } - "hint" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - hint = value.value; - } - _ => - { - return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `scalar( name = myName, setter = true )`", ident ) ) ); - } + AttributePropertyName::KEYWORD => result.assign( AttributePropertyName::parse( input )? ), + AttributePropertySetter::KEYWORD => result.assign( AttributePropertySetter::parse( input )? ), + AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), + _ => return Err( error( &ident ) ), } } else { - return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `scalar( name = myName, setter = true )`" ) ); + return Err( lookahead.error() ); } // Optional comma handling @@ -384,7 +444,7 @@ impl syn::parse::Parse for AttributeScalarSetter } } - Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into() } ) + Ok( result ) } } @@ -491,9 +551,28 @@ impl syn::parse::Parse for AttributeSubformScalarSetter { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > { - let mut name : Option< syn::Ident > = None; - let mut setter : Option< bool > = None; - let mut hint = false; + let mut result = Self::default(); + + let error = | ident : &syn::Ident | -> syn::Error + { + let known = const_format::concatcp! + ( + "Known entries of attribute ", AttributeSubformScalarSetter::KEYWORD, " are : ", + AttributePropertyName::KEYWORD, + ", ", AttributePropertySetter::KEYWORD, + ", ", AttributePropertyHint::KEYWORD, + ".", + ); + syn_err! + ( + ident, + r#"Expects an attribute of format '#[ subform_scalar( name = myName, setter = true, hint = false ) ]' + {known} + But got: '{}' +"#, + qt!{ #ident } + ) + }; while !input.is_empty() { @@ -501,34 +580,19 @@ impl syn::parse::Parse for AttributeSubformScalarSetter if lookahead.peek( syn::Ident ) { let ident : syn::Ident = input.parse()?; + + input.parse::< syn::Token![=] >()?; match ident.to_string().as_str() { - "name" => - { - input.parse::< syn::Token![ = ] >()?; - name = Some( input.parse()? ); - } - "setter" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - setter = Some( value.value() ); - } - "hint" => - { - input.parse::< syn::Token![ = ] >()?; - let value : syn::LitBool = input.parse()?; - hint = value.value; - } - _ => - { - return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `subform_scalar( name = myName, setter = true )`", ident ) ) ); - } + AttributePropertyName::KEYWORD => result.assign( AttributePropertyName::parse( input )? ), + AttributePropertySetter::KEYWORD => result.assign( AttributePropertySetter::parse( input )? ), + AttributePropertyHint::KEYWORD => result.assign( AttributePropertyHint::parse( input )? ), + _ => return Err( error( &ident ) ), } } else { - return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `subform_scalar( name = myName, setter = true )`" ) ); + return Err( lookahead.error() ); } // Optional comma handling @@ -538,10 +602,65 @@ impl syn::parse::Parse for AttributeSubformScalarSetter } } - Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into() } ) + Ok( result ) } } +// impl syn::parse::Parse for AttributeSubformScalarSetter +// { +// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +// { +// let mut name : Option< syn::Ident > = None; +// let mut setter : Option< bool > = None; +// let mut hint = false; +// +// while !input.is_empty() +// { +// let lookahead = input.lookahead1(); +// if lookahead.peek( syn::Ident ) +// { +// let ident : syn::Ident = input.parse()?; +// match ident.to_string().as_str() +// { +// "name" => +// { +// input.parse::< syn::Token![ = ] >()?; +// name = Some( input.parse()? ); +// } +// "setter" => +// { +// input.parse::< syn::Token![ = ] >()?; +// let value : syn::LitBool = input.parse()?; +// setter = Some( value.value() ); +// } +// "hint" => +// { +// input.parse::< syn::Token![ = ] >()?; +// let value : syn::LitBool = input.parse()?; +// hint = value.value; +// } +// _ => +// { +// return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `subform_scalar( name = myName, setter = true )`", ident ) ) ); +// } +// } +// } +// else +// { +// return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `subform_scalar( name = myName, setter = true )`" ) ); +// } +// +// // Optional comma handling +// if input.peek( syn::Token![ , ] ) +// { +// input.parse::< syn::Token![ , ] >()?; +// } +// } +// +// Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into() } ) +// } +// } + /// Represents an attribute for configuring collection setter generation. /// /// This struct is part of a meta-programming approach to enable detailed configuration of nested structs or collections such as `Vec< E >, HashMap< K, E >` and so on. @@ -715,67 +834,6 @@ impl syn::parse::Parse for AttributeSubformCollectionSetter } } -// impl syn::parse::Parse for AttributeSubformCollectionSetter -// { -// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > -// { -// let mut name : Option< syn::Ident > = None; -// let mut setter : Option< bool > = None; // Default is to generate a setter -// let mut hint = false; -// let mut definition : Option< syn::Type > = None; -// -// while !input.is_empty() -// { -// let lookahead = input.lookahead1(); -// if lookahead.peek( syn::Ident ) -// { -// let ident : syn::Ident = input.parse()?; -// match ident.to_string().as_str() -// { -// "name" => -// { -// input.parse::< syn::Token![ = ] >()?; -// name = Some( input.parse()? ); -// } -// "setter" => -// { -// input.parse::< syn::Token![ = ] >()?; -// let value : syn::LitBool = input.parse()?; -// setter = Some( value.value ); -// } -// "hint" => -// { -// input.parse::< syn::Token![ = ] >()?; -// let value : syn::LitBool = input.parse()?; -// hint = value.value; -// } -// "definition" => -// { -// input.parse::< syn::Token![ = ] >()?; -// definition = Some( input.parse()? ); -// } -// _ => -// { -// return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'name', 'setter', or 'definition'. For example: `collection( name = myName, setter = true, definition = MyDefinition )`", ident ) ) ); -// } -// } -// } -// else -// { -// return Err( syn::Error::new( input.span(), "Expected 'name', 'setter', or 'definition' identifier. For example: `subform_collection( name = myName, setter = true, hint = false, definition = MyDefinition )`" ) ); -// } -// -// // Optional comma handling -// if input.peek( syn::Token![ , ] ) -// { -// input.parse::< syn::Token![ , ] >()?; -// } -// } -// -// Ok( Self { name : name.into(), setter : setter.into(), hint : hint.into(), definition : definition.into() } ) -// } -// } - /// Represents a subform attribute to control subform setter generation. /// Used to specify extra options for using one former as subformer of another one. /// For example name of setter could be customized. From 5a1798bfc4b7aeccbfa0ae548d8e0ef586faa662 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 18:05:29 +0300 Subject: [PATCH 40/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 142 +++++++----------- 1 file changed, 51 insertions(+), 91 deletions(-) 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 8e80e957b3..cf64cc2f2e 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -1,6 +1,6 @@ use super::*; -use macro_tools::{ attr, Result, AttributePropertyComponent }; +use macro_tools::{ attr, Result, AttributeComponent, AttributePropertyComponent }; use former_types::{ ComponentAssign }; // xxx : document @@ -147,12 +147,12 @@ pub struct AttributeConfig } -impl AttributeConfig +impl AttributeComponent for AttributeConfig { const KEYWORD : &'static str = "former"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta { @@ -192,7 +192,6 @@ where } } - impl syn::parse::Parse for AttributeConfig { fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > @@ -248,61 +247,6 @@ impl syn::parse::Parse for AttributeConfig } } -// impl syn::parse::Parse for AttributeConfig -// { -// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > -// { -// let mut default : Option< syn::Expr > = None; -// // let mut only_storage : Option< bool > = None; -// -// while !input.is_empty() -// { -// let lookahead = input.lookahead1(); -// if lookahead.peek( syn::Ident ) -// { -// let ident : syn::Ident = input.parse()?; -// match ident.to_string().as_str() -// { -// "default" => -// { -// input.parse::< syn::Token![ = ] >()?; -// default = Some( input.parse()? ); -// } -// _ => -// { -// return Err( syn::Error::new_spanned( &ident, format!( "Unexpected identifier '{}'. Expected 'default'. For example: `former( default = 13 )`", ident ) ) ); -// } -// } -// } -// -// else -// { -// return Err( syn::Error::new( input.span(), "Expected 'default'. For example: `former( default = 13 )`" ) ); -// } -// -// // Optional comma handling -// if input.peek( syn::Token![ , ] ) -// { -// input.parse::< syn::Token![ , ] >()?; -// } -// } -// -// Ok( Self { default : default.into() } ) -// } -// } - -/// -/// Attribute to enable/disable scalar setter generation. -/// -/// ## Example Input -/// -/// A typical input to parse might look like the following: -/// -/// ```ignore -/// name = field_name, setter = true -/// ``` -/// - #[ derive( Debug, Default ) ] pub struct AttributeScalarSetter { @@ -315,13 +259,23 @@ pub struct AttributeScalarSetter pub hint : AttributePropertyHint, } -#[ allow( dead_code ) ] impl AttributeScalarSetter +{ + + /// Should setter be generated or not? + pub fn setter( &self ) -> bool + { + self.setter.is_none() || self.setter.unwrap() + } + +} + +impl AttributeComponent for AttributeScalarSetter { const KEYWORD : &'static str = "scalar"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta { @@ -337,12 +291,6 @@ impl AttributeScalarSetter } } - /// Should setter be generated or not? - pub fn setter( &self ) -> bool - { - self.setter.is_none() || self.setter.unwrap() - } - } impl< IntoT > ComponentAssign< AttributeScalarSetter, IntoT > for FieldAttributes @@ -473,13 +421,23 @@ pub struct AttributeSubformScalarSetter pub hint : AttributePropertyHint, } -#[ allow( dead_code ) ] impl AttributeSubformScalarSetter +{ + + /// Should setter be generated or not? + pub fn setter( &self ) -> bool + { + self.setter.is_none() || self.setter.unwrap() + } + +} + +impl AttributeComponent for AttributeSubformScalarSetter { const KEYWORD : &'static str = "subform_scalar"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta { @@ -495,12 +453,6 @@ impl AttributeSubformScalarSetter } } - /// Should setter be generated or not? - pub fn setter( &self ) -> bool - { - self.setter.is_none() || self.setter.unwrap() - } - } impl< IntoT > ComponentAssign< AttributeSubformScalarSetter, IntoT > for FieldAttributes @@ -688,13 +640,23 @@ pub struct AttributeSubformCollectionSetter pub definition : AttributePropertyDefinition, } -// xxx : use trait impl AttributeSubformCollectionSetter +{ + + /// Should setter be generated or not? + pub fn setter( &self ) -> bool + { + self.setter.is_none() || self.setter.unwrap() + } + +} + +impl AttributeComponent for AttributeSubformCollectionSetter { const KEYWORD : &'static str = "subform_collection"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta { @@ -710,12 +672,6 @@ impl AttributeSubformCollectionSetter } } - /// Should setter be generated or not? - pub fn setter( &self ) -> bool - { - self.setter.is_none() || self.setter.unwrap() - } - } impl< IntoT > ComponentAssign< AttributeSubformCollectionSetter, IntoT > for FieldAttributes @@ -866,13 +822,23 @@ pub struct AttributeSubformEntrySetter pub hint : AttributePropertyHint, } -// xxx : use trait impl AttributeSubformEntrySetter +{ + + /// Should setter be generated or not? + pub fn setter( &self ) -> bool + { + self.setter.as_ref().is_none() || self.setter.as_ref().unwrap() + } + +} + +impl AttributeComponent for AttributeSubformEntrySetter { const KEYWORD : &'static str = "subform_entry"; - pub fn from_meta( attr : &syn::Attribute ) -> Result< Self > + fn from_meta( attr : &syn::Attribute ) -> Result< Self > { match attr.meta { @@ -888,12 +854,6 @@ impl AttributeSubformEntrySetter } } - /// Should setter be generated or not? - pub fn setter( &self ) -> bool - { - self.setter.as_ref().is_none() || self.setter.as_ref().unwrap() - } - } impl< IntoT > ComponentAssign< AttributeSubformEntrySetter, IntoT > for FieldAttributes From 2fc6bda1f4a181d98d743a811a6741721c767113 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 18:06:41 +0300 Subject: [PATCH 41/44] former : refactoring parsing --- module/core/former_meta/src/derive_former/attr_prop.rs | 2 ++ module/core/former_meta/src/derive_former/field_attrs.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/module/core/former_meta/src/derive_former/attr_prop.rs b/module/core/former_meta/src/derive_former/attr_prop.rs index 9af98f61f1..cf8ed4ca29 100644 --- a/module/core/former_meta/src/derive_former/attr_prop.rs +++ b/module/core/former_meta/src/derive_former/attr_prop.rs @@ -182,11 +182,13 @@ where T : syn::parse::Parse + quote::ToTokens, { /// Just unwrap, returning internal data. + #[ allow( dead_code ) ] pub fn internal( self ) -> T { self.0 } /// Returns Option< &T > instead of &Option< T > + #[ allow( dead_code ) ] pub fn ref_internal( &self ) -> &T { &self.0 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 cf64cc2f2e..f28c119c38 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -263,6 +263,7 @@ impl AttributeScalarSetter { /// Should setter be generated or not? + #[ allow( dead_code ) ] pub fn setter( &self ) -> bool { self.setter.is_none() || self.setter.unwrap() From ef33cbd0b1c479441dfc21035ef571d3fff9e229 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 18:22:57 +0300 Subject: [PATCH 42/44] former : refactoring parsing --- .../src/derive_former/attr_prop.rs | 46 ++++++++----------- .../src/derive_former/field_attrs.rs | 8 ++-- .../src/derive_former/struct_attrs.rs | 27 +++++------ 3 files changed, 32 insertions(+), 49 deletions(-) diff --git a/module/core/former_meta/src/derive_former/attr_prop.rs b/module/core/former_meta/src/derive_former/attr_prop.rs index cf8ed4ca29..83e2f80351 100644 --- a/module/core/former_meta/src/derive_former/attr_prop.rs +++ b/module/core/former_meta/src/derive_former/attr_prop.rs @@ -1,4 +1,3 @@ - use super::*; use macro_tools::{ AttributePropertyComponent }; @@ -13,19 +12,20 @@ AttributePropertyOptionalSyn // = AttributePropertyBoolean -/// Generics bolean attirbute property. +/// A generic boolean attribute property. /// Defaults to `false`. #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyBoolean< Marker >( bool, ::core::marker::PhantomData< Marker > ); impl< Marker > AttributePropertyBoolean< Marker > { - /// Just unwrap, returning internal data. + /// Just unwraps and returns the internal data. pub fn internal( self ) -> bool { self.0 } - /// Returns Option< &T > instead of &Option< T > + + /// Returns a reference to the internal boolean value. pub fn ref_internal( &self ) -> &bool { &self.0 @@ -87,19 +87,20 @@ impl< Marker > AsRef< bool > for AttributePropertyBoolean< Marker > // = AttributePropertyOptionalBoolean -/// Generics optional bolean attirbute property: `Option< bool >`. +/// A generic optional boolean attribute property: `Option< bool >`. /// Defaults to `false`. #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyOptionalBoolean< Marker >( Option< bool >, ::core::marker::PhantomData< Marker > ); impl< Marker > AttributePropertyOptionalBoolean< Marker > { - /// Just unwrap, returning internal data. + /// Just unwraps and returns the internal data. pub fn internal( self ) -> Option< bool > { self.0 } - /// Returns Option< &T > instead of &Option< T > + + /// Returns a reference to the internal optional boolean value. pub fn ref_internal( &self ) -> Option< &bool > { self.0.as_ref() @@ -170,24 +171,24 @@ impl< Marker > AsRef< Option< bool > > for AttributePropertyOptionalBoolean< Mar // = AttributePropertySyn -/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. +/// Property of an attribute which simply wraps one of the standard `syn` types. #[ derive( Debug, Clone ) ] pub struct AttributePropertySyn< T, Marker >( T, ::core::marker::PhantomData< Marker > ) where - T : syn::parse::Parse + quote::ToTokens, -; + T : syn::parse::Parse + quote::ToTokens; impl< T, Marker > AttributePropertySyn< T, Marker > where T : syn::parse::Parse + quote::ToTokens, { - /// Just unwrap, returning internal data. + /// Just unwraps and returns the internal data. #[ allow( dead_code ) ] pub fn internal( self ) -> T { self.0 } - /// Returns Option< &T > instead of &Option< T > + + /// Returns a reference to the internal data. #[ allow( dead_code ) ] pub fn ref_internal( &self ) -> &T { @@ -203,17 +204,6 @@ where const KEYWORD : &'static str = Marker::KEYWORD; } -// xxx -// impl< T, Marker > Default for AttributePropertySyn< T, Marker > -// where -// T : syn::parse::Parse + quote::ToTokens, -// { -// fn default() -> Self -// { -// Self( Default::default(), Default::default() ) -// } -// } - impl< T, Marker > syn::parse::Parse for AttributePropertySyn< T, Marker > where T : syn::parse::Parse + quote::ToTokens, @@ -288,23 +278,23 @@ where T : syn::parse::Parse + quote::ToTokens // = AttributePropertyOptionalSyn -/// Property of an attribute which simply wrap one of standard of `syn` type and keep it optional. +/// Property of an attribute which simply wraps one of the standard `syn` types and keeps it optional. #[ derive( Debug, Clone ) ] pub struct AttributePropertyOptionalSyn< T, Marker >( Option< T >, ::core::marker::PhantomData< Marker > ) where - T : syn::parse::Parse + quote::ToTokens, -; + T : syn::parse::Parse + quote::ToTokens; impl< T, Marker > AttributePropertyOptionalSyn< T, Marker > where T : syn::parse::Parse + quote::ToTokens, { - /// Just unwrap, returning internal data. + /// Just unwraps and returns the internal data. pub fn internal( self ) -> Option< T > { self.0 } - /// Returns Option< &T > instead of &Option< T > + + /// Returns an Option reference to the internal data. pub fn ref_internal( &self ) -> Option< &T > { self.0.as_ref() 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 f28c119c38..00e15c6511 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -960,9 +960,9 @@ impl syn::parse::Parse for AttributeSubformEntrySetter } } -// == attribute entries +// == attribute properties -// = AttributePropertyHint +// = /// Marker type for attribute property to specify whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. @@ -980,7 +980,7 @@ impl AttributePropertyComponent for AttributePropertyHintMarker /// Defaults to `false`, which means no hint is provided unless explicitly requested. pub type AttributePropertyHint = AttributePropertyBoolean< AttributePropertyHintMarker >; -// = Marker type for AttributePropertySetter +// = /// Disable generation of setter. /// Attributes still might generate some helper methods to reuse by custom setter. @@ -1040,5 +1040,3 @@ impl AttributePropertyComponent for AttributePropertyDefinitionMarker /// Definition of the collection former to use, e.g., `former::VectorFormer`. pub type AttributePropertyDefinition = AttributePropertyOptionalSyn< syn::Type, AttributePropertyDefinitionMarker >; - -// xxx2 : continue 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 dc6936809b..ab5983c03d 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -394,7 +394,6 @@ impl syn::parse::Parse for AttributeMutator /// `#[ perform( fn after1< 'a >() -> Option< &'a str > ) ]` /// -// xxx : reuse more generic structure #[ derive( Debug ) ] pub struct AttributePerform { @@ -421,17 +420,6 @@ impl AttributeComponent for AttributePerform } -impl< IntoT > ComponentAssign< AttributePerform, IntoT > for StructAttributes -where - IntoT : Into< AttributePerform >, -{ - #[ inline( always ) ] - fn assign( &mut self, component : IntoT ) - { - self.perform = Some( component.into() ); - } -} - impl syn::parse::Parse for AttributePerform { fn parse( input : syn::parse::ParseStream< '_ > ) -> Result< Self > @@ -443,11 +431,18 @@ impl syn::parse::Parse for AttributePerform } } -// == attribute entries - -// xxx2 : qqq : continue and get it implemented for all entries of all attribures +impl< IntoT > ComponentAssign< AttributePerform, IntoT > for StructAttributes +where + IntoT : Into< AttributePerform >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + self.perform = Some( component.into() ); + } +} -// xxx : reuse more generic structure +// == attribute properties /// Marker type for attribute property to specify whether to provide a sketch as a hint. /// Defaults to `false`, which means no hint is provided unless explicitly requested. From 3919db6be17e029f6835cccf2012e33ff025d474 Mon Sep 17 00:00:00 2001 From: wandalen Date: Sat, 25 May 2024 19:25:59 +0300 Subject: [PATCH 43/44] former : refactoring parsing --- module/core/former_meta/src/derive_former.rs | 2 - .../src/derive_former/attr_prop.rs | 402 --------------- .../src/derive_former/field_attrs.rs | 65 +-- .../src/derive_former/struct_attrs.rs | 11 +- module/core/macro_tools/src/attr_prop.rs | 458 ++++++++++++++++++ module/core/macro_tools/src/lib.rs | 4 + 6 files changed, 482 insertions(+), 460 deletions(-) delete mode 100644 module/core/former_meta/src/derive_former/attr_prop.rs create mode 100644 module/core/macro_tools/src/attr_prop.rs diff --git a/module/core/former_meta/src/derive_former.rs b/module/core/former_meta/src/derive_former.rs index 54e40ad182..d3093505cd 100644 --- a/module/core/former_meta/src/derive_former.rs +++ b/module/core/former_meta/src/derive_former.rs @@ -6,8 +6,6 @@ use proc_macro2::TokenStream; // qqq : implement interfaces for other collections -mod attr_prop; -use attr_prop::*; mod field_attrs; use field_attrs::*; mod field; diff --git a/module/core/former_meta/src/derive_former/attr_prop.rs b/module/core/former_meta/src/derive_former/attr_prop.rs deleted file mode 100644 index 83e2f80351..0000000000 --- a/module/core/former_meta/src/derive_former/attr_prop.rs +++ /dev/null @@ -1,402 +0,0 @@ -use super::*; -use macro_tools::{ AttributePropertyComponent }; - -/* - -AttributePropertyBoolean -AttributePropertyOptionalBoolean -AttributePropertySyn -AttributePropertyOptionalSyn - -*/ - -// = AttributePropertyBoolean - -/// A generic boolean attribute property. -/// Defaults to `false`. -#[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertyBoolean< Marker >( bool, ::core::marker::PhantomData< Marker > ); - -impl< Marker > AttributePropertyBoolean< Marker > -{ - /// Just unwraps and returns the internal data. - pub fn internal( self ) -> bool - { - self.0 - } - - /// Returns a reference to the internal boolean value. - pub fn ref_internal( &self ) -> &bool - { - &self.0 - } -} - -impl< Marker > AttributePropertyComponent for AttributePropertyBoolean< Marker > -where - Marker : AttributePropertyComponent, -{ - const KEYWORD : &'static str = Marker::KEYWORD; -} - -impl< Marker > syn::parse::Parse for AttributePropertyBoolean< Marker > -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : syn::LitBool = input.parse()?; - Ok( value.value.into() ) - } -} - -impl< Marker > From< bool > for AttributePropertyBoolean< Marker > -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( src, Default::default() ) - } -} - -impl< Marker > From< AttributePropertyBoolean< Marker > > for bool -{ - #[ inline( always ) ] - fn from( src : AttributePropertyBoolean< Marker > ) -> Self - { - src.0 - } -} - -impl< Marker > core::ops::Deref for AttributePropertyBoolean< Marker > -{ - type Target = bool; - #[ inline( always ) ] - fn deref( &self ) -> &bool - { - &self.0 - } -} - -impl< Marker > AsRef< bool > for AttributePropertyBoolean< Marker > -{ - #[ inline( always ) ] - fn as_ref( &self ) -> &bool - { - &self.0 - } -} - -// = AttributePropertyOptionalBoolean - -/// A generic optional boolean attribute property: `Option< bool >`. -/// Defaults to `false`. -#[ derive( Debug, Default, Clone, Copy ) ] -pub struct AttributePropertyOptionalBoolean< Marker >( Option< bool >, ::core::marker::PhantomData< Marker > ); - -impl< Marker > AttributePropertyOptionalBoolean< Marker > -{ - /// Just unwraps and returns the internal data. - pub fn internal( self ) -> Option< bool > - { - self.0 - } - - /// Returns a reference to the internal optional boolean value. - pub fn ref_internal( &self ) -> Option< &bool > - { - self.0.as_ref() - } -} - -impl< Marker > AttributePropertyComponent for AttributePropertyOptionalBoolean< Marker > -where - Marker : AttributePropertyComponent, -{ - const KEYWORD : &'static str = Marker::KEYWORD; -} - -impl< Marker > syn::parse::Parse for AttributePropertyOptionalBoolean< Marker > -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : syn::LitBool = input.parse()?; - Ok( value.value.into() ) - } -} - -impl< Marker > From< bool > for AttributePropertyOptionalBoolean< Marker > -{ - #[ inline( always ) ] - fn from( src : bool ) -> Self - { - Self( Some( src ), Default::default() ) - } -} - -impl< Marker > From< Option< bool > > for AttributePropertyOptionalBoolean< Marker > -{ - #[ inline( always ) ] - fn from( src : Option< bool > ) -> Self - { - Self( src, Default::default() ) - } -} - -impl< Marker > From< AttributePropertyOptionalBoolean< Marker > > for Option< bool > -{ - #[ inline( always ) ] - fn from( src : AttributePropertyOptionalBoolean< Marker > ) -> Self - { - src.0 - } -} - -impl< Marker > core::ops::Deref for AttributePropertyOptionalBoolean< Marker > -{ - type Target = Option< bool >; - #[ inline( always ) ] - fn deref( &self ) -> &Option< bool > - { - &self.0 - } -} - -impl< Marker > AsRef< Option< bool > > for AttributePropertyOptionalBoolean< Marker > -{ - #[ inline( always ) ] - fn as_ref( &self ) -> &Option< bool > - { - &self.0 - } -} - -// = AttributePropertySyn - -/// Property of an attribute which simply wraps one of the standard `syn` types. -#[ derive( Debug, Clone ) ] -pub struct AttributePropertySyn< T, Marker >( T, ::core::marker::PhantomData< Marker > ) -where - T : syn::parse::Parse + quote::ToTokens; - -impl< T, Marker > AttributePropertySyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, -{ - /// Just unwraps and returns the internal data. - #[ allow( dead_code ) ] - pub fn internal( self ) -> T - { - self.0 - } - - /// Returns a reference to the internal data. - #[ allow( dead_code ) ] - pub fn ref_internal( &self ) -> &T - { - &self.0 - } -} - -impl< T, Marker > AttributePropertyComponent for AttributePropertySyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, - Marker : AttributePropertyComponent, -{ - const KEYWORD : &'static str = Marker::KEYWORD; -} - -impl< T, Marker > syn::parse::Parse for AttributePropertySyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : T = input.parse()?; - Ok( value.into() ) - } -} - -impl< T, Marker > quote::ToTokens for AttributePropertySyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, -{ - fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) - { - self.0.to_tokens( tokens ); - } -} - -impl< T, Marker > core::ops::Deref for AttributePropertySyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens -{ - type Target = T; - #[ inline( always ) ] - fn deref( &self ) -> &T - { - &self.0 - } -} - -impl< T, Marker > AsRef< T > for AttributePropertySyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn as_ref( &self ) -> &T - { - &self.0 - } -} - -impl< T, Marker > From< T > for AttributePropertySyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : T ) -> Self - { - Self( src, Default::default() ) - } -} - -// impl< T, Marker > From< AttributePropertySyn< T, Marker > > for T -// where T : syn::parse::Parse + quote::ToTokens -// { -// #[ inline( always ) ] -// fn from( src : AttributePropertySyn< T, Marker > ) -> Self -// { -// src.0 -// } -// } - -// impl< 'a, T, Marker > From< &'a AttributePropertySyn< T, Marker > > for Option< &'a T > -// where T : syn::parse::Parse + quote::ToTokens -// { -// #[ inline( always ) ] -// fn from( src : &'a AttributePropertySyn< T, Marker > ) -> Self -// { -// &src.0 -// } -// } - -// = AttributePropertyOptionalSyn - -/// Property of an attribute which simply wraps one of the standard `syn` types and keeps it optional. -#[ derive( Debug, Clone ) ] -pub struct AttributePropertyOptionalSyn< T, Marker >( Option< T >, ::core::marker::PhantomData< Marker > ) -where - T : syn::parse::Parse + quote::ToTokens; - -impl< T, Marker > AttributePropertyOptionalSyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, -{ - /// Just unwraps and returns the internal data. - pub fn internal( self ) -> Option< T > - { - self.0 - } - - /// Returns an Option reference to the internal data. - pub fn ref_internal( &self ) -> Option< &T > - { - self.0.as_ref() - } -} - -impl< T, Marker > AttributePropertyComponent for AttributePropertyOptionalSyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, - Marker : AttributePropertyComponent, -{ - const KEYWORD : &'static str = Marker::KEYWORD; -} - -impl< T, Marker > Default for AttributePropertyOptionalSyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, -{ - fn default() -> Self - { - Self( None, Default::default() ) - } -} - -impl< T, Marker > syn::parse::Parse for AttributePropertyOptionalSyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, -{ - fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > - { - let value : T = input.parse()?; - Ok( value.into() ) - } -} - -impl< T, Marker > quote::ToTokens for AttributePropertyOptionalSyn< T, Marker > -where - T : syn::parse::Parse + quote::ToTokens, -{ - fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) - { - self.0.to_tokens( tokens ); - } -} - -impl< T, Marker > core::ops::Deref for AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens -{ - type Target = Option< T >; - #[ inline( always ) ] - fn deref( &self ) -> &Option< T > - { - &self.0 - } -} - -impl< T, Marker > AsRef< Option< T > > for AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn as_ref( &self ) -> &Option< T > - { - &self.0 - } -} - -impl< T, Marker > From< T > for AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : T ) -> Self - { - Self( Some( src ), Default::default() ) - } -} - -impl< T, Marker > From< Option< T > > for AttributePropertyOptionalSyn< T, Marker > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : Option< T > ) -> Self - { - Self( src, Default::default() ) - } -} - -impl< T, Marker > From< AttributePropertyOptionalSyn< T, Marker > > for Option< T > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : AttributePropertyOptionalSyn< T, Marker > ) -> Self - { - src.0 - } -} - -impl< 'a, T, Marker > From< &'a AttributePropertyOptionalSyn< T, Marker > > for Option< &'a T > -where T : syn::parse::Parse + quote::ToTokens -{ - #[ inline( always ) ] - fn from( src : &'a AttributePropertyOptionalSyn< T, Marker > ) -> Self - { - src.0.as_ref() - } -} 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 00e15c6511..ccb5dd6a20 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -1,6 +1,15 @@ use super::*; -use macro_tools::{ attr, Result, AttributeComponent, AttributePropertyComponent }; +use macro_tools:: +{ + attr, + Result, + AttributeComponent, + AttributePropertyComponent, + AttributePropertyBoolean, + AttributePropertyOptionalBoolean, + AttributePropertyOptionalSyn, +}; use former_types::{ ComponentAssign }; // xxx : document @@ -78,60 +87,6 @@ impl FieldAttributes } -// impl FieldAttributes -// { -// pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > -// { -// let mut config = None; -// let mut scalar = None; -// let mut subform_scalar = None; -// let mut subform_collection = None; -// let mut subform_entry = None; -// -// for attr in attrs -// { -// let key_ident = attr.path().get_ident() -// .ok_or_else( || syn_err!( attr, "Expects an attribute of format #[ attribute( key1 = val1, key2 = val2 ) ], but got:\n {}", qt!{ #attr } ) )?; -// let key_str = format!( "{}", key_ident ); -// -// if attr::is_standard( &key_str ) -// { -// continue; -// } -// -// match key_str.as_ref() -// { -// AttributeConfig::KEYWORD => -// { -// config.replace( AttributeConfig::from_meta( &attr )? ); -// } -// AttributeScalarSetter::KEYWORD => -// { -// scalar.replace( AttributeScalarSetter::from_meta( &attr )? ); -// } -// AttributeSubformScalarSetter::KEYWORD => -// { -// subform_scalar.replace( AttributeSubformScalarSetter::from_meta( &attr )? ); -// } -// AttributeSubformCollectionSetter::KEYWORD => -// { -// subform_collection.replace( AttributeSubformCollectionSetter::from_meta( &attr )? ); -// } -// AttributeSubformEntrySetter::KEYWORD => -// { -// subform_entry.replace( AttributeSubformEntrySetter::from_meta( &attr )? ); -// } -// _ => -// { -// return Err( syn_err!( attr, "Unknown field attribute {}", qt!{ #attr } ) ); -// } -// } -// } -// -// Ok( FieldAttributes { config, scalar, subform_scalar, subform_collection, subform_entry } ) -// } -// } - /// /// Attribute to hold configuration information about the field such as default value. /// 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 ab5983c03d..e0b84d4933 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -1,6 +1,15 @@ use super::*; -use macro_tools::{ attr, Result, AttributeComponent, AttributePropertyComponent }; + +use macro_tools:: +{ + attr, + Result, + AttributeComponent, + AttributePropertyComponent, + AttributePropertyBoolean, +}; + use former_types::{ ComponentAssign }; /// Represents the attributes of a struct, including storage fields, mutator, and perform attributes. diff --git a/module/core/macro_tools/src/attr_prop.rs b/module/core/macro_tools/src/attr_prop.rs new file mode 100644 index 0000000000..468d7c1f94 --- /dev/null +++ b/module/core/macro_tools/src/attr_prop.rs @@ -0,0 +1,458 @@ +//! +//! Attributes analyzys and manipulation. +//! + +/// Internal namespace. +pub( crate ) mod private +{ + use crate::*; + + /* + + AttributePropertyBoolean + AttributePropertyOptionalBoolean + AttributePropertySyn + AttributePropertyOptionalSyn + + */ + + // = AttributePropertyBoolean + + /// A generic boolean attribute property. + /// Defaults to `false`. + #[ derive( Debug, Default, Clone, Copy ) ] + pub struct AttributePropertyBoolean< Marker >( bool, ::core::marker::PhantomData< Marker > ); + + impl< Marker > AttributePropertyBoolean< Marker > + { + /// Just unwraps and returns the internal data. + pub fn internal( self ) -> bool + { + self.0 + } + + /// Returns a reference to the internal boolean value. + pub fn ref_internal( &self ) -> &bool + { + &self.0 + } + } + + impl< Marker > AttributePropertyComponent for AttributePropertyBoolean< Marker > + where + Marker : AttributePropertyComponent, + { + const KEYWORD : &'static str = Marker::KEYWORD; + } + + impl< Marker > syn::parse::Parse for AttributePropertyBoolean< Marker > + { + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } + } + + impl< Marker > From< bool > for AttributePropertyBoolean< Marker > + { + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( src, Default::default() ) + } + } + + impl< Marker > From< AttributePropertyBoolean< Marker > > for bool + { + #[ inline( always ) ] + fn from( src : AttributePropertyBoolean< Marker > ) -> Self + { + src.0 + } + } + + impl< Marker > core::ops::Deref for AttributePropertyBoolean< Marker > + { + type Target = bool; + #[ inline( always ) ] + fn deref( &self ) -> &bool + { + &self.0 + } + } + + impl< Marker > AsRef< bool > for AttributePropertyBoolean< Marker > + { + #[ inline( always ) ] + fn as_ref( &self ) -> &bool + { + &self.0 + } + } + + // = AttributePropertyOptionalBoolean + + /// A generic optional boolean attribute property: `Option< bool >`. + /// Defaults to `false`. + #[ derive( Debug, Default, Clone, Copy ) ] + pub struct AttributePropertyOptionalBoolean< Marker >( Option< bool >, ::core::marker::PhantomData< Marker > ); + + impl< Marker > AttributePropertyOptionalBoolean< Marker > + { + /// Just unwraps and returns the internal data. + pub fn internal( self ) -> Option< bool > + { + self.0 + } + + /// Returns a reference to the internal optional boolean value. + pub fn ref_internal( &self ) -> Option< &bool > + { + self.0.as_ref() + } + } + + impl< Marker > AttributePropertyComponent for AttributePropertyOptionalBoolean< Marker > + where + Marker : AttributePropertyComponent, + { + const KEYWORD : &'static str = Marker::KEYWORD; + } + + impl< Marker > syn::parse::Parse for AttributePropertyOptionalBoolean< Marker > + { + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : syn::LitBool = input.parse()?; + Ok( value.value.into() ) + } + } + + impl< Marker > From< bool > for AttributePropertyOptionalBoolean< Marker > + { + #[ inline( always ) ] + fn from( src : bool ) -> Self + { + Self( Some( src ), Default::default() ) + } + } + + impl< Marker > From< Option< bool > > for AttributePropertyOptionalBoolean< Marker > + { + #[ inline( always ) ] + fn from( src : Option< bool > ) -> Self + { + Self( src, Default::default() ) + } + } + + impl< Marker > From< AttributePropertyOptionalBoolean< Marker > > for Option< bool > + { + #[ inline( always ) ] + fn from( src : AttributePropertyOptionalBoolean< Marker > ) -> Self + { + src.0 + } + } + + impl< Marker > core::ops::Deref for AttributePropertyOptionalBoolean< Marker > + { + type Target = Option< bool >; + #[ inline( always ) ] + fn deref( &self ) -> &Option< bool > + { + &self.0 + } + } + + impl< Marker > AsRef< Option< bool > > for AttributePropertyOptionalBoolean< Marker > + { + #[ inline( always ) ] + fn as_ref( &self ) -> &Option< bool > + { + &self.0 + } + } + + // = AttributePropertySyn + + /// Property of an attribute which simply wraps one of the standard `syn` types. + #[ derive( Debug, Clone ) ] + pub struct AttributePropertySyn< T, Marker >( T, ::core::marker::PhantomData< Marker > ) + where + T : syn::parse::Parse + quote::ToTokens; + + impl< T, Marker > AttributePropertySyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + { + /// Just unwraps and returns the internal data. + #[ allow( dead_code ) ] + pub fn internal( self ) -> T + { + self.0 + } + + /// Returns a reference to the internal data. + #[ allow( dead_code ) ] + pub fn ref_internal( &self ) -> &T + { + &self.0 + } + } + + impl< T, Marker > AttributePropertyComponent for AttributePropertySyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + Marker : AttributePropertyComponent, + { + const KEYWORD : &'static str = Marker::KEYWORD; + } + + impl< T, Marker > syn::parse::Parse for AttributePropertySyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + { + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : T = input.parse()?; + Ok( value.into() ) + } + } + + impl< T, Marker > quote::ToTokens for AttributePropertySyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + { + fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) + { + self.0.to_tokens( tokens ); + } + } + + impl< T, Marker > core::ops::Deref for AttributePropertySyn< T, Marker > + where T : syn::parse::Parse + quote::ToTokens + { + type Target = T; + #[ inline( always ) ] + fn deref( &self ) -> &T + { + &self.0 + } + } + + impl< T, Marker > AsRef< T > for AttributePropertySyn< T, Marker > + where T : syn::parse::Parse + quote::ToTokens + { + #[ inline( always ) ] + fn as_ref( &self ) -> &T + { + &self.0 + } + } + + impl< T, Marker > From< T > for AttributePropertySyn< T, Marker > + where T : syn::parse::Parse + quote::ToTokens + { + #[ inline( always ) ] + fn from( src : T ) -> Self + { + Self( src, Default::default() ) + } + } + + // impl< T, Marker > From< AttributePropertySyn< T, Marker > > for T + // where T : syn::parse::Parse + quote::ToTokens + // { + // #[ inline( always ) ] + // fn from( src : AttributePropertySyn< T, Marker > ) -> Self + // { + // src.0 + // } + // } + + // impl< 'a, T, Marker > From< &'a AttributePropertySyn< T, Marker > > for Option< &'a T > + // where T : syn::parse::Parse + quote::ToTokens + // { + // #[ inline( always ) ] + // fn from( src : &'a AttributePropertySyn< T, Marker > ) -> Self + // { + // &src.0 + // } + // } + + // = AttributePropertyOptionalSyn + + /// Property of an attribute which simply wraps one of the standard `syn` types and keeps it optional. + #[ derive( Debug, Clone ) ] + pub struct AttributePropertyOptionalSyn< T, Marker >( Option< T >, ::core::marker::PhantomData< Marker > ) + where + T : syn::parse::Parse + quote::ToTokens; + + impl< T, Marker > AttributePropertyOptionalSyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + { + /// Just unwraps and returns the internal data. + pub fn internal( self ) -> Option< T > + { + self.0 + } + + /// Returns an Option reference to the internal data. + pub fn ref_internal( &self ) -> Option< &T > + { + self.0.as_ref() + } + } + + impl< T, Marker > AttributePropertyComponent for AttributePropertyOptionalSyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + Marker : AttributePropertyComponent, + { + const KEYWORD : &'static str = Marker::KEYWORD; + } + + impl< T, Marker > Default for AttributePropertyOptionalSyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + { + fn default() -> Self + { + Self( None, Default::default() ) + } + } + + impl< T, Marker > syn::parse::Parse for AttributePropertyOptionalSyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + { + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let value : T = input.parse()?; + Ok( value.into() ) + } + } + + impl< T, Marker > quote::ToTokens for AttributePropertyOptionalSyn< T, Marker > + where + T : syn::parse::Parse + quote::ToTokens, + { + fn to_tokens( &self, tokens : &mut proc_macro2::TokenStream ) + { + self.0.to_tokens( tokens ); + } + } + + impl< T, Marker > core::ops::Deref for AttributePropertyOptionalSyn< T, Marker > + where T : syn::parse::Parse + quote::ToTokens + { + type Target = Option< T >; + #[ inline( always ) ] + fn deref( &self ) -> &Option< T > + { + &self.0 + } + } + + impl< T, Marker > AsRef< Option< T > > for AttributePropertyOptionalSyn< T, Marker > + where T : syn::parse::Parse + quote::ToTokens + { + #[ inline( always ) ] + fn as_ref( &self ) -> &Option< T > + { + &self.0 + } + } + + impl< T, Marker > From< T > for AttributePropertyOptionalSyn< T, Marker > + where T : syn::parse::Parse + quote::ToTokens + { + #[ inline( always ) ] + fn from( src : T ) -> Self + { + Self( Some( src ), Default::default() ) + } + } + + impl< T, Marker > From< Option< T > > for AttributePropertyOptionalSyn< T, Marker > + where T : syn::parse::Parse + quote::ToTokens + { + #[ inline( always ) ] + fn from( src : Option< T > ) -> Self + { + Self( src, Default::default() ) + } + } + + impl< T, Marker > From< AttributePropertyOptionalSyn< T, Marker > > for Option< T > + where T : syn::parse::Parse + quote::ToTokens + { + #[ inline( always ) ] + fn from( src : AttributePropertyOptionalSyn< T, Marker > ) -> Self + { + src.0 + } + } + + impl< 'a, T, Marker > From< &'a AttributePropertyOptionalSyn< T, Marker > > for Option< &'a T > + where T : syn::parse::Parse + quote::ToTokens + { + #[ inline( always ) ] + fn from( src : &'a AttributePropertyOptionalSyn< T, Marker > ) -> Self + { + src.0.as_ref() + } + } + +} + +#[ doc( inline ) ] +#[ allow( unused_imports ) ] +pub use protected::*; + +/// Protected namespace of the module. +pub mod protected +{ + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::orphan::*; + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::private:: + { + }; +} + +/// Orphan namespace of the module. +pub mod orphan +{ + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::exposed::*; +} + +/// Exposed namespace of the module. +pub mod exposed +{ + pub use super::protected as attr_prop; + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::prelude::*; + #[ doc( inline ) ] + #[ allow( unused_imports ) ] + pub use super::private:: + { + AttributePropertyBoolean, + AttributePropertyOptionalBoolean, + AttributePropertySyn, + AttributePropertyOptionalSyn, + }; +} + +/// Prelude to use essentials: `use my_module::prelude::*`. +pub mod prelude +{ +} diff --git a/module/core/macro_tools/src/lib.rs b/module/core/macro_tools/src/lib.rs index fe0ee3655f..b1ababf64b 100644 --- a/module/core/macro_tools/src/lib.rs +++ b/module/core/macro_tools/src/lib.rs @@ -27,6 +27,7 @@ mod file { // use super::*; pub mod attr; + pub mod attr_prop; pub mod container_kind; pub mod derive; pub mod diag; @@ -79,6 +80,7 @@ pub mod protected pub use super::file:: { attr::orphan::*, + attr_prop::orphan::*, container_kind::orphan::*, derive::orphan::*, diag::orphan::*, @@ -134,6 +136,7 @@ pub mod exposed pub use super::file:: { attr::exposed::*, + attr_prop::exposed::*, container_kind::exposed::*, derive::orphan::*, diag::exposed::*, @@ -204,6 +207,7 @@ pub mod prelude pub use super::file:: { attr::prelude::*, + attr_prop::prelude::*, container_kind::prelude::*, derive::orphan::*, diag::prelude::*, From fee118d234fedf563378c7649ddf22b13b32cd6b Mon Sep 17 00:00:00 2001 From: wandalen Date: Mon, 27 May 2024 00:03:21 +0300 Subject: [PATCH 44/44] former : refactoring parsing --- .../src/derive_former/field_attrs.rs | 38 ++- .../src/derive_former/struct_attrs.rs | 1 + module/core/macro_tools/src/attr_prop.rs | 225 +++++++++++++++--- .../macro_tools/tests/inc/attr_prop_test.rs | 102 ++++++++ module/core/macro_tools/tests/inc/mod.rs | 1 + 5 files changed, 330 insertions(+), 37 deletions(-) create mode 100644 module/core/macro_tools/tests/inc/attr_prop_test.rs 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 ccb5dd6a20..a4f7a1357f 100644 --- a/module/core/former_meta/src/derive_former/field_attrs.rs +++ b/module/core/former_meta/src/derive_former/field_attrs.rs @@ -1,3 +1,4 @@ +//! Attributes of a field. use super::*; use macro_tools:: @@ -12,8 +13,6 @@ use macro_tools:: }; use former_types::{ ComponentAssign }; -// xxx : document - /// /// Attributes of a field. /// @@ -21,23 +20,46 @@ use former_types::{ ComponentAssign }; #[ derive( Debug, Default ) ] pub struct FieldAttributes { + /// Configuration attribute for a field. pub config : Option< AttributeConfig >, + + /// Scalar setter attribute for a field. pub scalar : Option< AttributeScalarSetter >, + + /// Subform scalar setter attribute for a field. pub subform_scalar : Option< AttributeSubformScalarSetter >, + + /// Subform collection setter attribute for a field. pub subform_collection : Option< AttributeSubformCollectionSetter >, + + /// Subform entry setter attribute for a field. pub subform_entry : Option< AttributeSubformEntrySetter >, } impl FieldAttributes { + /// Creates an instance of `FieldAttributes` from a list of attributes. + /// + /// # Parameters + /// + /// * `attrs`: An iterator over references to `syn::Attribute`. + /// + /// # Returns + /// + /// * `Result< Self >`: A result containing an instance of `FieldAttributes` on success, + /// or a `syn::Error` on failure. + /// + /// This function processes each attribute in the provided iterator and assigns the + /// appropriate attribute type to the respective field in the `FieldAttributes` struct. + /// pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { let mut result = Self::default(); - // let known_attributes = "Known structure attirbutes are : `storage_fields`, `mutator`, `perform`, `debug`."; + // Known attributes for error reporting let known_attributes = const_format::concatcp! ( - "Known attirbutes are : ", + "Known attributes are : ", "debug", ", ", AttributeConfig::KEYWORD, ", ", AttributeScalarSetter::KEYWORD, @@ -47,6 +69,7 @@ impl FieldAttributes ".", ); + // Helper closure to create a syn::Error for unknown attributes let error = | attr : &syn::Attribute | -> syn::Error { syn_err! @@ -57,19 +80,20 @@ impl FieldAttributes ) }; + // Iterate over the provided attributes for attr in attrs { - - // return Err( error( attr ) ); - + // Get the attribute key as a string let key_ident = attr.path().get_ident().ok_or_else( || error( attr ) )?; let key_str = format!( "{}", key_ident ); + // Skip standard attributes if attr::is_standard( &key_str ) { continue; } + // Match the attribute key and assign to the appropriate field match key_str.as_ref() { AttributeConfig::KEYWORD => result.assign( AttributeConfig::from_meta( attr )? ), 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 e0b84d4933..73e11f9cb0 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -1,3 +1,4 @@ +//! Attributes of the whole item. use super::*; diff --git a/module/core/macro_tools/src/attr_prop.rs b/module/core/macro_tools/src/attr_prop.rs index 468d7c1f94..0193a8653a 100644 --- a/module/core/macro_tools/src/attr_prop.rs +++ b/module/core/macro_tools/src/attr_prop.rs @@ -1,25 +1,209 @@ //! -//! Attributes analyzys and manipulation. +//! Attribute's properties. Reuse them to define how to parse properties of an attribute. //! +//! +//! # Example +//! +//! ```rust +//! use macro_tools::AttributePropertyBoolean; +//! +//! #[ derive( Debug, Default, Clone, Copy ) ] +//! pub struct DebugMarker; +//! +//! #[ derive( Debug, Default, Clone, Copy ) ] +//! pub struct EnabledMarker; +//! +//! pub trait AttributePropertyComponent +//! { +//! const KEYWORD : &'static str; +//! } +//! +//! impl AttributePropertyComponent for DebugMarker +//! { +//! const KEYWORD : &'static str = "debug"; +//! } +//! +//! impl AttributePropertyComponent for EnabledMarker +//! { +//! const KEYWORD : &'static str = "enabled"; +//! } +//! +//! #[ derive( Debug, Default ) ] +//! struct MyAttributes +//! { +//! pub debug : AttributePropertyBoolean< DebugMarker >, +//! pub enabled : AttributePropertyBoolean< EnabledMarker >, +//! } +//! +//! impl syn::parse::Parse for MyAttributes +//! { +//! fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > +//! { +//! let mut debug = AttributePropertyBoolean::< DebugMarker >::default(); +//! let mut enabled = AttributePropertyBoolean::< EnabledMarker >::default(); +//! +//! while !input.is_empty() +//! { +//! let lookahead = input.lookahead1(); +//! if lookahead.peek( syn::Ident ) +//! { +//! let ident : syn::Ident = input.parse()?; +//! input.parse::< syn::Token![=] >()?; +//! match ident.to_string().as_str() +//! { +//! DebugMarker::KEYWORD => debug = input.parse()?, +//! EnabledMarker::KEYWORD => enabled = input.parse()?, +//! _ => return Err( lookahead.error() ), +//! } +//! } +//! else +//! { +//! return Err( lookahead.error() ); +//! } +//! +//! // Optional comma handling +//! if input.peek( syn::Token![,] ) +//! { +//! input.parse::< syn::Token![,] >()?; +//! } +//! } +//! +//! Ok( MyAttributes { debug, enabled } ) +//! } +//! } +//! +//! let input : syn::Attribute = syn::parse_quote!( #[ attribute( enabled = true, debug = false ) ] ); +//! let meta = match input.meta +//! { +//! syn::Meta::List( meta_list ) => meta_list, +//! _ => panic!( "Expected a Meta::List" ), +//! }; +//! +//! let nested_meta_stream : proc_macro2::TokenStream = meta.tokens; +//! let attrs : MyAttributes = syn::parse2( nested_meta_stream ).unwrap(); +//! println!( "{:?}", attrs ); +//! ``` +//! +//! In this example, the `AttributePropertyBoolean` struct is used to define attributes with boolean properties. +//! The `DebugMarker` and `EnabledMarker` structs act as markers to distinguish between different boolean attributes. +//! The `MyAttributes` struct aggregates these boolean attributes. +//! +//! The `Parse` implementation for `MyAttributes` iterates through the attribute's key-value pairs, +//! identifying each by its marker's keyword and parsing the boolean value. +//! It uses the `ParseStream` to parse identifiers and their associated values, +//! matching them to the appropriate marker's keyword. +//! If an unrecognized identifier is encountered, it returns an error. +//! +//! The `parse_quote!` macro is used to create a `syn::Attribute` instance with the attribute syntax, +//! which is then parsed into the `MyAttributes` struct. The resulting `MyAttributes` instance is printed to the console. + +// xxx : qqq : improve documentation, add examples /// Internal namespace. pub( crate ) mod private { use crate::*; - /* - - AttributePropertyBoolean - AttributePropertyOptionalBoolean - AttributePropertySyn - AttributePropertyOptionalSyn - - */ - // = AttributePropertyBoolean /// A generic boolean attribute property. /// Defaults to `false`. + /// + /// # Example + /// + /// ```rust + /// use macro_tools::AttributePropertyBoolean; + /// + /// #[ derive( Debug, Default, Clone, Copy ) ] + /// pub struct DebugMarker; + /// + /// #[ derive( Debug, Default, Clone, Copy ) ] + /// pub struct EnabledMarker; + /// + /// pub trait AttributePropertyComponent + /// { + /// const KEYWORD : &'static str; + /// } + /// + /// impl AttributePropertyComponent for DebugMarker + /// { + /// const KEYWORD : &'static str = "debug"; + /// } + /// + /// impl AttributePropertyComponent for EnabledMarker + /// { + /// const KEYWORD : &'static str = "enabled"; + /// } + /// + /// #[ derive( Debug, Default ) ] + /// struct MyAttributes + /// { + /// pub debug : AttributePropertyBoolean< DebugMarker >, + /// pub enabled : AttributePropertyBoolean< EnabledMarker >, + /// } + /// + /// impl syn::parse::Parse for MyAttributes + /// { + /// fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + /// { + /// let mut debug = AttributePropertyBoolean::< DebugMarker >::default(); + /// let mut enabled = AttributePropertyBoolean::< EnabledMarker >::default(); + /// + /// while !input.is_empty() + /// { + /// let lookahead = input.lookahead1(); + /// if lookahead.peek( syn::Ident ) + /// { + /// let ident : syn::Ident = input.parse()?; + /// input.parse::< syn::Token![=] >()?; + /// match ident.to_string().as_str() + /// { + /// DebugMarker::KEYWORD => debug = input.parse()?, + /// EnabledMarker::KEYWORD => enabled = input.parse()?, + /// _ => return Err( lookahead.error() ), + /// } + /// } + /// else + /// { + /// return Err( lookahead.error() ); + /// } + /// + /// // Optional comma handling + /// if input.peek( syn::Token![,] ) + /// { + /// input.parse::< syn::Token![,] >()?; + /// } + /// } + /// + /// Ok( MyAttributes { debug, enabled } ) + /// } + /// } + /// + /// let input : syn::Attribute = syn::parse_quote!( #[ attribute( enabled = true, debug = false ) ] ); + /// let meta = match input.meta + /// { + /// syn::Meta::List( meta_list ) => meta_list, + /// _ => panic!( "Expected a Meta::List" ), + /// }; + /// + /// let nested_meta_stream : proc_macro2::TokenStream = meta.tokens; + /// let attrs : MyAttributes = syn::parse2( nested_meta_stream ).unwrap(); + /// println!( "{:?}", attrs ); + /// ``` + /// + /// In this example, the `AttributePropertyBoolean` struct is used to define attributes with boolean properties. + /// The `DebugMarker` and `EnabledMarker` structs act as markers to distinguish between different boolean attributes. + /// The `MyAttributes` struct aggregates these boolean attributes. + /// + /// The `Parse` implementation for `MyAttributes` iterates through the attribute's key-value pairs, + /// identifying each by its marker's keyword and parsing the boolean value. + /// It uses the `ParseStream` to parse identifiers and their associated values, + /// matching them to the appropriate marker's keyword. + /// If an unrecognized identifier is encountered, it returns an error. + /// + /// The `parse_quote!` macro is used to create a `syn::Attribute` instance with the attribute syntax, + /// which is then parsed into the `MyAttributes` struct. The resulting `MyAttributes` instance is printed to the console. + #[ derive( Debug, Default, Clone, Copy ) ] pub struct AttributePropertyBoolean< Marker >( bool, ::core::marker::PhantomData< Marker > ); @@ -75,6 +259,7 @@ pub( crate ) mod private impl< Marker > core::ops::Deref for AttributePropertyBoolean< Marker > { type Target = bool; + #[ inline( always ) ] fn deref( &self ) -> &bool { @@ -262,26 +447,6 @@ pub( crate ) mod private } } - // impl< T, Marker > From< AttributePropertySyn< T, Marker > > for T - // where T : syn::parse::Parse + quote::ToTokens - // { - // #[ inline( always ) ] - // fn from( src : AttributePropertySyn< T, Marker > ) -> Self - // { - // src.0 - // } - // } - - // impl< 'a, T, Marker > From< &'a AttributePropertySyn< T, Marker > > for Option< &'a T > - // where T : syn::parse::Parse + quote::ToTokens - // { - // #[ inline( always ) ] - // fn from( src : &'a AttributePropertySyn< T, Marker > ) -> Self - // { - // &src.0 - // } - // } - // = AttributePropertyOptionalSyn /// Property of an attribute which simply wraps one of the standard `syn` types and keeps it optional. diff --git a/module/core/macro_tools/tests/inc/attr_prop_test.rs b/module/core/macro_tools/tests/inc/attr_prop_test.rs new file mode 100644 index 0000000000..8d2ff6c559 --- /dev/null +++ b/module/core/macro_tools/tests/inc/attr_prop_test.rs @@ -0,0 +1,102 @@ +use super::*; +use quote::ToTokens; + +#[ test ] +fn test_attribute_property_boolean() +{ + + #[ derive( Debug, Default, Clone, Copy ) ] + pub struct DebugMarker; + + #[ derive( Debug, Default, Clone, Copy ) ] + pub struct EnabledMarker; + + pub trait AttributePropertyComponent + { + const KEYWORD : &'static str; + } + + impl AttributePropertyComponent for DebugMarker + { + const KEYWORD : &'static str = "debug"; + } + + impl AttributePropertyComponent for EnabledMarker + { + const KEYWORD : &'static str = "enabled"; + } + + #[ derive( Debug, Default ) ] + struct MyAttributes + { + pub debug : AttributePropertyBoolean< DebugMarker >, + pub enabled : AttributePropertyBoolean< EnabledMarker >, + } + + impl syn::parse::Parse for MyAttributes + { + fn parse( input : syn::parse::ParseStream< '_ > ) -> syn::Result< Self > + { + let mut debug = AttributePropertyBoolean::< DebugMarker >::default(); + let mut enabled = AttributePropertyBoolean::< EnabledMarker >::default(); + + while !input.is_empty() + { + let lookahead = input.lookahead1(); + if lookahead.peek( syn::Ident ) + { + let ident : syn::Ident = input.parse()?; + input.parse::< syn::Token![=] >()?; + match ident.to_string().as_str() + { + DebugMarker::KEYWORD => debug = input.parse()?, + EnabledMarker::KEYWORD => enabled = input.parse()?, + _ => return Err( lookahead.error() ), + } + } + else + { + return Err( lookahead.error() ); + } + + // Optional comma handling + if input.peek( syn::Token![,] ) + { + input.parse::< syn::Token![,] >()?; + } + } + + Ok( MyAttributes { debug, enabled } ) + } + } + + let input : syn::Attribute = syn::parse_quote!( #[ attribute( enabled = true, debug = false ) ] ); + let meta = match input.meta + { + syn::Meta::List( meta_list ) => meta_list, + _ => panic!( "Expected a Meta::List" ), + }; + + let nested_meta_stream : proc_macro2::TokenStream = meta.tokens; + let attrs : MyAttributes = syn::parse2( nested_meta_stream ).unwrap(); + println!( "{:?}", attrs ); + + let attr : AttributePropertyBoolean< DebugMarker > = AttributePropertyBoolean::default(); + assert_eq!( attr.internal(), false ); + let attr : AttributePropertyBoolean< DebugMarker > = true.into(); + assert_eq!( attr.internal(), true ); + let attr : AttributePropertyBoolean< DebugMarker > = false.into(); + assert_eq!( attr.internal(), false ); + + let input : syn::Attribute = syn::parse_quote!( #[ attribute( enabled = true, debug = false ) ] ); + let meta = match input.meta + { + syn::Meta::List( meta_list ) => meta_list, + _ => panic!( "Expected a Meta::List" ), + }; + + let nested_meta_stream : proc_macro2::TokenStream = meta.tokens; + let parsed : MyAttributes = syn::parse2( nested_meta_stream ).unwrap(); + assert_eq!( parsed.enabled.internal(), true ); + assert_eq!( parsed.debug.internal(), false ); +} diff --git a/module/core/macro_tools/tests/inc/mod.rs b/module/core/macro_tools/tests/inc/mod.rs index f1c2bd1c01..9ed0a80bee 100644 --- a/module/core/macro_tools/tests/inc/mod.rs +++ b/module/core/macro_tools/tests/inc/mod.rs @@ -15,6 +15,7 @@ mod if_enabled use super::*; mod attr_test; + mod attr_prop_test; mod basic_test; mod container_kind_test; mod derive_test;