Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions module/core/component_model/Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- {{# generate.module_header{} #}} -->

# Module :: component_model
# Module :: `component_model`

[![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_component_model_push.yml/badge.svg)](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_push.yml)
Expand Down Expand Up @@ -47,19 +47,19 @@ where
}
}

fn main() {
//fn main() {
let mut person = Person::default();
person.assign(42);
person.assign("Alice");
assert_eq!(person, Person { age: 42, name: "Alice".to_string() });
}
//}
```

## API Overview

- **Assign**: Generic trait for assigning values to struct fields by type.
- **AssignWithType**: Trait for assigning values with explicit type annotation.
- **ComponentsAssign**: Trait for assigning multiple components at once.
- **`Assign`**: Generic trait for assigning values to struct fields by type.
- **`AssignWithType`**: Trait for assigning values with explicit type annotation.
- **`ComponentsAssign`**: Trait for assigning multiple components at once.

See [component_model_types documentation](https://docs.rs/component_model_types) for details.

Expand Down
3 changes: 0 additions & 3 deletions module/core/component_model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ pub mod dependency
#[ cfg( feature = "enabled" ) ]
pub use own::*;

#[ allow( unused_imports ) ]
#[ cfg( feature = "enabled" ) ]
// Former macro is intentionally not re-exported; all coupling with "former" is removed.

/// Own namespace of the module.
#[ cfg( feature = "enabled" ) ]
#[ allow( unused_imports ) ]
Expand Down
2 changes: 1 addition & 1 deletion module/core/component_model_meta/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![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_component_model_meta_push.yml/badge.svg)](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_meta_push.yml) [![docs.rs](https://img.shields.io/docsrs/component_model_meta?color=e3e8f0&logo=docs.rs)](https://docs.rs/component_model_meta) [![discord](https://img.shields.io/discord/872391416519737405?color=eee&logo=discord&logoColor=eee&label=ask)](https://discord.gg/m3YfbXpUUY)
<!--{ generate.module_header.end }-->

A flexible implementation of the Builder pattern supporting nested builders and collection-specific subcomponent_models. Implementation of its derive macro. Should not be used independently, instead use `module::component_model` which relies on the module.
A flexible implementation of the Builder pattern supporting nested builders and collection-specific `subcomponent_models`. Implementation of its derive macro. Should not be used independently, instead use `module::component_model` which relies on the module.

Not intended to be used without runtime. This module and runtime is aggregate in `module::component_model` is [here](https://github.com/Wandalen/wTools/tree/master/module/core/component_model).

Expand Down
30 changes: 14 additions & 16 deletions module/core/former_meta/src/derive_former/former_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ pub(super) struct EnumVariantHandlerContext< 'a >
pub has_debug : bool,
}


#[allow(clippy::too_many_lines)]
pub(super) fn former_for_enum
(
ast : &syn::DeriveInput,
Expand Down Expand Up @@ -211,7 +211,7 @@ pub(super) fn former_for_enum
{
ast,
variant,
struct_attrs : &struct_attrs,
struct_attrs,
enum_name,
vis,
generics,
Expand Down Expand Up @@ -266,11 +266,11 @@ pub(super) fn former_for_enum
{
return Err( syn::Error::new_spanned( ctx.variant, "#[subform_scalar] is not allowed on zero-field struct variants." ) );
}
if !ctx.variant_attrs.scalar.is_some()
if ctx.variant_attrs.scalar.is_none()
{
return Err( syn::Error::new_spanned( ctx.variant, "Zero-field struct variants require `#[scalar]` attribute for direct construction." ) );
}
let generated = struct_zero_fields_handler::handle(&mut ctx)?;
let generated = struct_zero_fields_handler::handle(&mut ctx);
ctx.methods.push(generated); // Collect generated tokens
}
_len =>
Expand All @@ -284,23 +284,21 @@ pub(super) fn former_for_enum
}
else
{
let generated = struct_multi_fields_scalar::handle(&mut ctx)?;
let generated = struct_multi_fields_scalar::handle(&mut ctx);
ctx.methods.push(generated); // Collect generated tokens
}
}
else if fields.named.len() == 1
{
let generated = struct_single_field_subform::handle(&mut ctx)?;
ctx.methods.push(generated); // Collect generated tokens
}
else
{
if fields.named.len() == 1
{
let generated = struct_single_field_subform::handle(&mut ctx)?;
ctx.methods.push(generated); // Collect generated tokens
}
else
{
let generated = struct_multi_fields_subform::handle(&mut ctx)?;
ctx.methods.push(generated); // Collect generated tokens
}
let generated = struct_multi_fields_subform::handle(&mut ctx);
ctx.methods.push(generated); // Collect generated tokens
}

}
}
} // End of match
Expand Down Expand Up @@ -329,7 +327,7 @@ pub(super) fn former_for_enum

if has_debug
{
let about = format!( "derive : Former\nenum : {}", enum_name );
let about = format!( "derive : Former\nenum : {enum_name}" );
diag::report_print( about, original_input, &result );
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// qqq : Implement shared emitter functions

use super::*;
use macro_tools::{ Result, quote::{ quote } };
use macro_tools::{ quote::{ quote } };
use proc_macro2::TokenStream; // Corrected import for TokenStream
// use super::EnumVariantHandlerContext;

#[allow(dead_code)] // Suppress warning about unused function
pub( crate ) fn generate_direct_constructor_for_variant( _ctx : &EnumVariantHandlerContext< '_ > ) -> Result< TokenStream >
pub( crate ) fn generate_direct_constructor_for_variant( _ctx : &EnumVariantHandlerContext< '_ > ) -> TokenStream
{
// qqq : Implement
Ok( quote!{} )
quote!{}
}
// qqq : Add other placeholder functions as needed
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// qqq : Implement logic for Struct { f1:T1, ... } with #[scalar]

use super::*;
use macro_tools::{ Result, quote, syn };
use macro_tools::{ quote, syn };
use super::EnumVariantHandlerContext;
use proc_macro2::TokenStream; // Import TokenStream
use convert_case::{ Case, Casing }; // Import Case and Casing from convert_case

#[allow(dead_code)] // Suppress warning about unused function
pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< TokenStream >
pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> TokenStream
{
// This handler is specifically for Struct { f1: T1, ... } variants with #[scalar].
// The main dispatch should ensure this is only called for such variants.
Expand Down Expand Up @@ -73,5 +73,5 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<
generated_tokens.extend(generated_standalone);
}

Ok( generated_tokens )
generated_tokens
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// qqq : Implement logic for Struct { f1:T1, ... } with #[subform_scalar] or default

use super::*;
use macro_tools::{ Result, quote, syn };
use macro_tools::{ quote, syn };
use super::EnumVariantHandlerContext;
use proc_macro2::TokenStream; // Import TokenStream
use convert_case::{ Case, Casing }; // Import Case and Casing from convert_case

#[allow(dead_code)] // Suppress warning about unused function
pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< TokenStream >
pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> TokenStream
{
// This handler is specifically for Struct { f1: T1, ... } variants with #[subform_scalar] or default behavior.
// The main dispatch should ensure this is only called for such variants.
Expand Down Expand Up @@ -55,5 +55,5 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<
// This will likely involve using common_emitters or dedicated logic here.
// For now, just returning the method/constructor tokens.

Ok( generated_tokens )
generated_tokens
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<
let vis = &ctx.vis; // Get visibility

// Get the single field's type and identifier
let field = ctx.variant_field_info.get(0).ok_or_else(|| {
let field = ctx.variant_field_info.first().ok_or_else(|| {
syn::Error::new_spanned(ctx.variant, "Struct variant with #[scalar] must have exactly one field.")
})?;
let field_ident = &field.ident;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,46 +18,59 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<

// Decompose generics for use in signatures (impl_generics and ty_generics are needed from local decomposition)
let ( _def_generics, impl_generics, ty_generics, _local_where_clause_option_unused ) = // Renamed to avoid confusion
macro_tools::generic_params::decompose(&ctx.generics);
macro_tools::generic_params::decompose( ctx.generics );

// Use merged_where_clause from the context for any top-level item's where clause (like standalone fns or VariantFormer struct)
let top_level_where_clause = match ctx.merged_where_clause { // Use ctx.merged_where_clause
Some(clause) => quote! { where #clause }, // Add `where` keyword if clause exists
None => quote! {},
let top_level_where_clause = match ctx.merged_where_clause
{ // Use ctx.merged_where_clause
Some( clause ) => quote! { where #clause }, // Add `where` keyword if clause exists
None => quote! {},
};

// Get the single field's info
let field_info = ctx.variant_field_info.get(0).ok_or_else(|| {
syn::Error::new_spanned(ctx.variant, "Struct variant with subform behavior must have exactly one field for this handler.")
let field_info = ctx.variant_field_info.first().ok_or_else(
||
{
syn::Error::new_spanned( ctx.variant, "Struct variant with subform behavior must have exactly one field for this handler." )
})?;
let field_name_original = &field_info.ident; // This is the original field name from the enum variant
let field_ty = &field_info.ty;

// Generate the name for the implicit variant former, make it generic if enum is generic
let variant_former_name_str = format!("{}{}Former", enum_ident, variant_ident);
let variant_former_ident = format_ident!("{}", variant_former_name_str);
let variant_former_name_generic = if ctx.generics.params.is_empty() {
quote! { #variant_former_ident }
} else {
quote! { #variant_former_ident< #ty_generics > }
let variant_former_name_str = format!( "{enum_ident}{variant_ident}Former" );
let variant_former_ident = format_ident!( "{}", variant_former_name_str );
let variant_former_name_generic = if ctx.generics.params.is_empty()
{
quote! { #variant_former_ident }
}
else
{
quote! { #variant_former_ident< #ty_generics > }
};

// Correctly create method_ident for the accessor method, handling raw identifiers
let method_ident = {
let name_str = variant_ident.to_string();
// Raw identifier check (consistent with other handlers)
if let Some(core_name) = name_str.strip_prefix("r#") {
let snake_core_name = core_name.to_case(Case::Snake);
syn::Ident::new_raw(&snake_core_name, variant_ident.span())
} else {
let snake_name = name_str.to_case(Case::Snake);
let is_keyword = matches!(snake_name.as_str(), "as" | "async" | "await" | "break" | "const" | "continue" | "crate" | "dyn" | "else" | "enum" | "extern" | "false" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "Self" | "self" | "static" | "struct" | "super" | "trait" | "true" | "type" | "unsafe" | "use" | "where" | "while" | "union" );
if is_keyword {
syn::Ident::new_raw(&snake_name, variant_ident.span())
} else {
syn::Ident::new(&snake_name, variant_ident.span())
}
let method_ident =
{
let name_str = variant_ident.to_string();
// Raw identifier check (consistent with other handlers)
if let Some( core_name ) = name_str.strip_prefix( "r#" )
{
let snake_core_name = core_name.to_case( Case::Snake );
syn::Ident::new_raw( &snake_core_name, variant_ident.span() )
}
else
{
let snake_name = name_str.to_case( Case::Snake );
let is_keyword = matches!( snake_name.as_str(), "as" | "async" | "await" | "break" | "const" | "continue" | "crate" | "dyn" | "else" | "enum" | "extern" | "false" | "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" | "match" | "mod" | "move" | "mut" | "pub" | "ref" | "return" | "Self" | "self" | "static" | "struct" | "super" | "trait" | "true" | "type" | "unsafe" | "use" | "where" | "while" | "union" );
if is_keyword
{
syn::Ident::new_raw( &snake_name, variant_ident.span() )
}
else
{
syn::Ident::new( &snake_name, variant_ident.span() )
}
}
};

// Generate the static method: Enum::variant_name() -> VariantFormer<...>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use super::*;
use macro_tools::{ Result, quote };
use macro_tools::quote;
use proc_macro2::TokenStream; // Corrected import for TokenStream
// use former_types::FormerDefinition; // Not needed here

/// Handles zero-field struct variants with the `#[scalar]` attribute.
/// Returns generated tokens for the static method and optionally the standalone constructor.
pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< TokenStream >
pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> TokenStream
{
// This handler is specifically for variants with #[scalar]
// The main dispatch should ensure this is only called for scalar zero-field struct variants.
Expand Down Expand Up @@ -52,5 +52,5 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<
// and place them in the correct scope (outside the enum impl block).
}

Ok( generated_tokens )
generated_tokens
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<

// Decompose generics for use in signatures (impl_generics and ty_generics are needed)
let ( _def_generics, impl_generics, ty_generics, _local_where_clause_option ) =
macro_tools::generic_params::decompose(&ctx.generics);
macro_tools::generic_params::decompose(ctx.generics);

// Use merged_where_clause from the context for the standalone constructor's where clause
let where_clause = match ctx.merged_where_clause {
Expand All @@ -28,7 +28,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<
};

// Get the single field's type and identifier
let field = ctx.variant_field_info.get(0).ok_or_else(|| {
let field = ctx.variant_field_info.first().ok_or_else(|| {
syn::Error::new_spanned(ctx.variant, "Tuple variant with #[scalar] must have exactly one field.")
})?;
let field_ty = &field.ty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<
// The main dispatch should ensure this is only called for such variants.

let variant_ident = &ctx.variant.ident;
let _enum_ident = &ctx.enum_name;
let vis = &ctx.vis; // Get visibility

// Get the single field's type
let field = ctx.variant_field_info.get(0).ok_or_else(|| {
let field = ctx.variant_field_info.first().ok_or_else(|| {
syn::Error::new_spanned(ctx.variant, "Tuple variant with subform behavior must have exactly one field.")
})?;
let field_ty = &field.ty;

let type_path_str = quote!{ #field_ty }.to_string().replace(" ", "");
let type_path_str = quote!{ #field_ty }.to_string().replace(' ', "");
let is_phantom_data_field = type_path_str.starts_with("core::marker::PhantomData") || type_path_str.starts_with("std::marker::PhantomData");

let method_ident_string = variant_ident.to_string().to_case( Case::Snake );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<

// Decompose generics (we need impl_generics and ty_generics from this)
let ( _def_generics, impl_generics, ty_generics, _local_where_clause_option_unused ) = // Renamed to avoid confusion
macro_tools::generic_params::decompose(&ctx.generics);
macro_tools::generic_params::decompose(ctx.generics);

// Use merged_where_clause from the context for the standalone constructor's where clause
let top_level_where_clause = match ctx.merged_where_clause { // Use ctx.merged_where_clause
Expand Down Expand Up @@ -65,15 +65,19 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result<
let fn_signature_generics = if ctx.generics.params.is_empty() { quote!{} } else { quote!{ < #impl_generics > } };
let return_type_generics = if ctx.generics.params.is_empty() { quote!{} } else { quote!{ < #ty_generics > } };

let enum_path_for_construction = if ctx.generics.params.is_empty() {
quote!{ #enum_ident }
} else {
if ty_generics.is_empty() { quote!{ #enum_ident } } else { quote!{ #enum_ident::< #ty_generics > } }
// FIX: Combine the two conditions with identical blocks using ||
let enum_path_for_construction = if ctx.generics.params.is_empty() || ty_generics.is_empty()
{
quote!{ #enum_ident }
}
else
{
quote!{ #enum_ident::< #ty_generics > }
};

// Create unique name for standalone constructor: [enum_name]_[variant_snake_case]
let standalone_method_name_str = format!("{}_{}", enum_ident.to_string().to_case(Case::Snake), method_ident.to_string());
let standalone_method_ident = syn::Ident::new(&standalone_method_name_str, variant_ident.span());
let standalone_method_name_str = format!( "{}_{}", enum_ident.to_string().to_case( Case::Snake ), method_ident );
let standalone_method_ident = syn::Ident::new( &standalone_method_name_str, variant_ident.span() );

let generated_standalone = quote!
{
Expand Down
Loading