diff --git a/module/core/component_model/Readme.md b/module/core/component_model/Readme.md index f5e927e98f..d3c6e9109c 100644 --- a/module/core/component_model/Readme.md +++ b/module/core/component_model/Readme.md @@ -1,11 +1,11 @@ -# 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) [![docs.rs](https://img.shields.io/docsrs/component_model?color=e3e8f0&logo=docs.rs)](https://docs.rs/component_model) -[![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%2Fcomponent_model%2Fexamples%2Fcomponent_model_trivial.rs,RUN_POSTFIX=--example%2Fcore%2Fcomponent_model%2Fexamples%2Fcomponent_model_trivial.rs/https://github.com/Wandalen/wTools) +[![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%2Fcomponent_model%2Fexamples%2Fcomponent_model_trivial.rs,RUN_POSTFIX=--example%20module%2Fcore%2Fcomponent_model%2Fexamples%2Fcomponent_model_trivial.rs/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 component model for Rust supporting generic assignment and type-based field access. @@ -47,17 +47,19 @@ where } } -let mut person = Person::default(); -person.assign(42); -person.assign("Alice"); -assert_eq!(person, Person { age: 42, name: "Alice".to_string() }); +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. diff --git a/module/core/component_model/src/lib.rs b/module/core/component_model/src/lib.rs index e700788e2a..3936f30cfb 100644 --- a/module/core/component_model/src/lib.rs +++ b/module/core/component_model/src/lib.rs @@ -26,6 +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. @@ -73,20 +74,17 @@ pub mod exposed #[ allow( unused_imports ) ] pub use component_model_types::exposed::*; - #[ doc( inline ) ] - #[ allow( unused_imports ) ] - pub use component_model_types::prelude::*; } -/// Namespace of the module to include with `use module::*`. +/// Prelude to use essentials: `use my_module::prelude::*`. #[ cfg( feature = "enabled" ) ] #[ allow( unused_imports ) ] pub mod prelude { - #[ allow( clippy::wildcard_imports ) ] use super::*; #[ doc( inline ) ] #[ allow( unused_imports ) ] pub use component_model_types::prelude::*; + } diff --git a/module/core/component_model_meta/Readme.md b/module/core/component_model_meta/Readme.md index 4945def390..19689cde07 100644 --- a/module/core/component_model_meta/Readme.md +++ b/module/core/component_model_meta/Readme.md @@ -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) -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). diff --git a/module/core/component_model_types/Readme.md b/module/core/component_model_types/Readme.md index 723d84a2df..fb9ae48ba8 100644 --- a/module/core/component_model_types/Readme.md +++ b/module/core/component_model_types/Readme.md @@ -6,7 +6,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_types_push.yml/badge.svg)](https://github.com/Wandalen/wTools/actions/workflows/module_component_model_types_push.yml) [![docs.rs](https://img.shields.io/docsrs/component_model_types?color=e3e8f0&logo=docs.rs)](https://docs.rs/component_model_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%2Fcomponent_model_types%2Fexamples%2Fcomponent_model_types_trivial.rs,RUN_POSTFIX=--example%20module%2Fcore%2Fcomponent_model_types%2Fexamples%2Fcomponent_model_types_trivial.rs/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 implementation of the Builder pattern supporting nested builders and collection-specific `subcomponent_models`. Its compile-time structures and traits that are not generated but reused. +A flexible implementation of the Builder pattern supporting nested builders and collection-specific subcomponent_models. Its compile-time structures and traits that are not generated but reused. ## Example: Using Trait Assign diff --git a/module/core/former/plan.md b/module/core/former/plan.md index 41de2b56a0..1d0f88c685 100644 --- a/module/core/former/plan.md +++ b/module/core/former/plan.md @@ -1,522 +1,224 @@ -# Project Plan: Review and Document Enum Tests in `former` Crate - -## Goal -* Systematically review all **active** (i.e., compiled as part of `cargo check --tests`) enum-related test files within the `former` crate (`module/core/former/tests/inc/enum_*_tests/`). -* For each targeted test file: - 1. Add a `//! Purpose: ...` comment block. - 2. Add a `//! Coverage: ...` comment block. - 3. Add a `//! Test Relevance/Acceptance Criteria: ...` comment block. -* Ensure all added documentation comments are clear, accurate, and adhere to specified content criteria and Rust documentation best practices. -* Ensure all modifications strictly adhere to `code/gen` instructions, Design Rules, and Codestyle Rules. -* Structure the work into logical increments, processing one test file or a closely related group of test files (i.e., `_derive.rs`, `_manual.rs`, and their shared `_only_test.rs`) per increment, with each increment having a narrow focus on a specific enum aspect (Unit, Unnamed/Tuple, Named/Struct, or Complex/Mixed). -* **Crucially, this plan focuses *only* on adding documentation. Pre-existing test failures or logic errors are out of scope. Changes will only be committed if `cargo check --package former --tests` passes after adding comments.** - -## Relevant Context -* **Primary Test Directories:** - * `module/core/former/tests/inc/enum_unit_tests/` - * `module/core/former/tests/inc/enum_unnamed_tests/` (Tuple-like variants) - * `module/core/former/tests/inc/enum_named_tests/` (Struct-like variants with named fields) - * `module/core/former/tests/inc/enum_complex_tests/` -* **Module Files to Update (Potentially for review):** - * `module/core/former/tests/inc/enum_unit_tests/mod.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/mod.rs` - * `module/core/former/tests/inc/enum_named_tests/mod.rs` - * `module/core/former/tests/inc/enum_complex_tests/mod.rs` +# Project Plan: Refactor Enum Unit Variant Handling in `former` + +### Goal +* Refactor the implementation of `#[derive(Former)]` for **enum unit variants** within the `former_meta` crate. +* This refactoring will focus on: + 1. Intensively analyzing and integrating reusable components from the `macro_tools` crate into the enum unit variant handling logic (`former_meta/src/derive_former/former_enum/unit_variant_handler.rs`). + 2. Analyzing the existing enum unit variant handling logic in `former_meta` to identify and potentially extract generalizable, well-tested utilities into the `macro_tools` crate. +* The process will include proposing an initial detailed refactoring solution, critiquing it, and then implementing an improved version. +* All changes must strictly adhere to `code/gen` instructions, Design Rules, and Codestyle Rules. + +### Relevant Context +* **Primary Crates for Modification:** + * `module/core/former_meta` (specifically `src/derive_former/former_enum/unit_variant_handler.rs` and potentially `src/derive_former/former_enum.rs`) + * `module/core/macro_tools` (for potential additions and modifications) +* **Key `macro_tools` Files for Analysis (Full Analysis in Increment 1):** + * All files within `module/core/macro_tools/src/` including `attr.rs`, `attr_prop.rs`, `diag.rs`, `ident.rs`, `kw.rs`, `generic_params.rs`, `typ.rs`, `item.rs`, `name.rs`, `punctuated.rs`, `quantifier.rs`, `tokens.rs`, etc. +* **Key `former_meta` Files for Analysis:** + * `module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs` + * `module/core/former_meta/src/derive_former/former_enum.rs` (for context, dispatch, and `EnumVariantHandlerContext`) + * `module/core/former_meta/src/derive_former/field_attrs.rs` + * `module/core/former_meta/src/derive_former/struct_attrs.rs` (for `ItemAttributes` like `standalone_constructors`, `debug`) * **Key Documentation for Reference:** * `module/core/former/Readme.md` * `module/core/former/advanced.md` - * This `plan.md` for the "Expected Enum Former Behavior Rules". + * Existing `plan.md` files for "Expected Enum Former Behavior" rules. * **Workspace:** Yes, this is part of a Cargo workspace. -* **Target File Structure:** No major structural changes, primarily adding comments to existing files. - -### Expected Enum Former Behavior - -This plan adheres to the following rules for `#[derive(Former)]` on enums: - -1. **`#[scalar]` Attribute:** - * **Unit Variant (Rule 1a):** Generates `Enum::variant() -> Enum`. (Handled by: `handle_unit_variant`) - * **Zero-Field Variant (Tuple) (Rule 1b):** Generates `Enum::variant() -> Enum`. (Handled by: `handle_tuple_zero_variant`) - * **Zero-Field Variant (Struct) (Rule 1c):** Generates `Enum::variant() -> Enum`. (Handled by: `handle_struct_zero_variant`) - * **Single-Field Variant (Tuple) (Rule 1d):** Generates `Enum::variant(InnerType) -> Enum`. (Handled by: `handle_tuple_non_zero_variant`) - * **Single-Field Variant (Struct) (Rule 1e):** Generates `Enum::variant { field: InnerType } -> Enum`. (Handled by: `handle_struct_non_zero_variant`) - * **Multi-Field Variant (Tuple) (Rule 1f):** Generates `Enum::variant(T1, T2, ...) -> Enum`. (Handled by: `handle_tuple_non_zero_variant`) - * **Multi-Field Variant (Struct) (Rule 1g):** Generates `Enum::variant { f1: T1, f2: T2, ... } -> Enum`. (Handled by: `handle_struct_non_zero_variant`) - * **Error Cases:** Cannot be combined with `#[subform_scalar]`. - -2. **`#[subform_scalar]` Attribute:** - * **Unit Variant (Rule 2a):** Error. (Checked in: `handle_unit_variant`) - * **Zero-Field Variant (Tuple or Struct) (Rule 2b, 2c):** Error. (Checked in: `handle_tuple_zero_variant`, `handle_struct_zero_variant`) - * **Single-Field Variant (Tuple) (Rule 2d):** Generates `Enum::variant() -> InnerFormer<...>` (where `InnerFormer` is the former for the field's type). Requires the field type to be a path type deriving `Former`. (Handled by: `handle_tuple_non_zero_variant`) - * **Single-Field Variant (Struct) (Rule 2e):** Generates `Enum::variant() -> VariantFormer<...>` (an implicit former for the variant itself). (Handled by: `handle_struct_non_zero_variant`) - * **Multi-Field Variant (Tuple) (Rule 2f):** Error. Cannot use `subform_scalar` on multi-field tuple variants. (Checked in: `handle_tuple_non_zero_variant`) - * **Multi-Field Variant (Struct) (Rule 2g):** Generates `Enum::variant() -> VariantFormer<...>` (an implicit former for the variant itself). (Handled by: `handle_struct_non_zero_variant`) - -3. **Default Behavior (No Attribute):** - * **Unit Variant (Rule 3a):** Generates `Enum::variant() -> Enum`. (Handled by: `handle_unit_variant`) - * **Zero-Field Variant (Tuple) (Rule 3b):** Generates `Enum::variant() -> Enum`. (Handled by: `handle_tuple_zero_variant`) - * **Zero-Field Variant (Struct) (Rule 3c):** Error. Requires `#[scalar]`. (Checked in: `handle_struct_zero_variant`) - * **Single-Field Variant (Tuple) (Rule 3d):** Generates `Enum::variant() -> InnerFormer<...>` (where `InnerFormer` is the former for the field's type). Requires the field type to be a path type deriving `Former`. (Handled by: `handle_tuple_non_zero_variant`) - * **Single-Field Variant (Struct) (Rule 3e):** Generates `Enum::variant() -> VariantFormer<...>` (an implicit former for the variant itself). (Handled by: `handle_struct_non_zero_variant`) - * **Multi-Field Variant (Tuple) (Rule 3f):** Generates `Enum::variant(Field1Type, Field2Type, ...) -> Enum` (behaves like `#[scalar]`). (Handled by: `handle_tuple_non_zero_variant`) - * **Multi-Field Variant (Struct) (Rule 3g):** Generates `Enum::variant() -> VariantFormer<...>` (an implicit former for the variant itself). (Handled by: `handle_struct_non_zero_variant`) - -4. **`#[standalone_constructors]` Attribute (Body Level) (Rule 4):** - * **Rule 4a:** Generates top-level constructor functions for each variant (e.g., `my_variant()`). - * **Rule 4b (Option 2 Logic):** Return type depends on `#[arg_for_constructor]` on fields within the variant. - -### Example of Expected Documentation Comments - -This section shows an example of the documentation comments that will be added to a test file. The content should adhere to the criteria outlined in the `### Requirements` section under "Comment Content". - -**For a file like `module/core/former/tests/inc/enum_unit_tests/generics_in_tuple_variant_unit_derive.rs`:** -```rust -//! Purpose: Tests the `#[derive(Former)]` macro's generation of constructors for unit variants -//! within an enum that has generic parameters and bounds. This file focuses on verifying -//! the derive-based implementation. -//! -//! Coverage: -//! - Rule 3a (Unit + Default): Verifies `Enum::variant() -> Enum` for a generic enum. -//! - Rule 1a (Unit + `#[scalar]`): Verifies `Enum::variant() -> Enum` (as default for unit is scalar) for a generic enum. -//! - (Implicitly) Rule 4a: If `#[standalone_constructors]` were active on `EnumOuter`, this test would also cover -//! the generation of `fn other_variant() -> EnumOuter`. -//! -//! Test Relevance/Acceptance Criteria: -//! - Defines a generic enum `EnumOuter` with a unit variant `OtherVariant`. -//! - Instantiates `EnumOuter` with a concrete type `MyType` that fulfills the `Copy` bound. -//! - Invokes the derived static method `EnumOuter::::other_variant()`. -//! - Asserts that the `got` instance is equal to an `expected` instance, which is manually -//! constructed as `EnumOuter::::OtherVariant`. This confirms the constructor produces the correct variant instance. -``` - -## Increments - -**Increment Template: Document Test File/Group** -* **Target Crate(s):** `former` -* **Enum Aspect Focus:** [Unit | Unnamed/Tuple | Named/Struct | Complex/Mixed] -* **Target File(s):** [List of specific `.rs` files for this increment] -* **Pre-Analysis (AI to output this in Detailed Planning - Output 4):** - * Identified enum variant structures in target file(s): [e.g., "Unit variants", "Single-field tuple variant with `#[scalar]`"] - * Key attributes present: [e.e., `#[scalar]`, `#[standalone_constructors]` on enum] - * Relevant "Expected Enum Former Behavior Rule IDs": [e.g., "1a, 4a"] - * Brief summary of how test functions appear to exercise these rules: [e.g., "Test `basic_construction` calls `Enum::variant()` and compares with manual construction. Test `standalone_construction` calls top-level `variant()`."] -* **Proposed Comments:** - * AI will propose the three `//!` comment blocks (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file, adhering to the "Comment Content" requirements. -* **Verification Strategy:** After comments are added by the user, the AI will request the user to run `cargo check --package former --tests`. The code must compile without errors. -* **Commit Message:** `docs(former): Add purpose and coverage to [enum_aspect_focus] [specific_test_file_or_group_name]` - ---- -**Phase 1: Unit Variant Tests (`enum_unit_tests`)** - -* [✅] **Increment 1:** Document `unit_variant_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Unit variants. - * Key attributes present: `#[derive(Former)]`, `#[former( standalone_constructors )]` on the enum in `_derive.rs`. Manual implementations in `_manual.rs`. - * Relevant "Expected Enum Former Behavior Rule IDs": 3a, 1a, 4a. - * Brief summary of how test functions appear to exercise these rules: `unit_variant_constructors` tests static methods (`Status::pending()`, `Status::complete()`). `unit_variant_standalone_constructors` tests standalone functions (`pending()`, `complete()`). Both compare results with direct enum variants. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks. - * Relevant Behavior Rules: Rule 3a (Unit + Default), Rule 1a (Unit + `#[scalar]`), Rule 4a (#[standalone_constructors]). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unit - * Target File(s): - * `module/core/former/tests/inc/enum_unit_tests/unit_variant_derive.rs` - * `module/core/former/tests/inc/enum_unit_tests/unit_variant_manual.rs` - * `module/core/former/tests/inc/enum_unit_tests/unit_variant_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to unit_variant enum tests` - -* [✅] **Increment 2:** Document `enum_named_fields_unit_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Unit variants. - * Key attributes present: `#[derive(Former)]`, `#[debug]`, `#[standalone_constructors]` on the enum in `_derive.rs`. Manual implementations in `_manual.rs`. - * Relevant "Expected Enum Former Behavior Rule IDs": 3a, 1a, 4a. - * Brief summary of how test functions appear to exercise these rules: `unit_variant_scalar_test` and `unit_variant_default_construction` test static methods (`EnumWithNamedFields::unit_variant_scalar()`, `EnumWithNamedFields::unit_variant_default()`) and compare results with direct enum variants. Standalone constructors are present due to `#[standalone_constructors]` but not explicitly tested in `_only_test.rs`. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks. - * Relevant Behavior Rules: Rule 3a (Unit + Default), Rule 1a (Unit + `#[scalar]`), Rule 4a (#[standalone_constructors]). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unit (within a named-fields style enum definition) - * Target File(s): - * `module/core/former/tests/inc/enum_unit_tests/enum_named_fields_unit_derive.rs` - * `module/core/former/tests/inc/enum_unit_tests/enum_named_fields_unit_manual.rs` - * `module/core/former/tests/inc/enum_unit_tests/enum_named_fields_unit_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to enum_named_fields_unit tests` - -* [✅] **Increment 3:** Document `generics_in_tuple_variant_unit_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Unit variants within a generic enum with bounds. - * Key attributes present: `#[derive(Former)]`, `#[debug]` on the enum in `_derive.rs`. Manual implementation in `_manual.rs`. - * Relevant "Expected Enum Former Behavior Rule IDs": 3a, 1a. (Rule 4a is implicitly covered by the enum having `#[derive(Former)]` but not explicitly tested in these files). - * Brief summary of how test functions appear to exercise these rules: No test functions are present in these specific files. The comment in both files indicates that the original `_only_test.rs` file for tuple variants did not test the unit variant. This means these files likely rely on broader tests or were intended for future test logic. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks. - * Relevant Behavior Rules: Rule 3a (Unit + Default), Rule 1a (Unit + `#[scalar]`). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unit (within generic enums) - * Target File(s): - * `module/core/former/tests/inc/enum_unit_tests/generics_in_tuple_variant_unit_derive.rs` - * `module/core/former/tests/inc/enum_unit_tests/generics_in_tuple_variant_unit_manual.rs` - * `module/core/former/tests/inc/enum_unit_tests/generics_in_tuple_variant_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to generics_in_tuple_variant_unit tests` - -* [✅] **Increment 4:** Document `keyword_variant_unit_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Unit variant with a keyword identifier (`r#Loop`). - * Key attributes present: `#[derive(Former)]` on the enum in `_derive.rs`. - * Relevant "Expected Enum Former Behavior Rule IDs": 3a, 1a. (Rule 4a is implicitly covered by the enum having `#[derive(Former)]` but not explicitly tested in these files). - * Brief summary of how test functions appear to exercise these rules: `keyword_variant_constructors` tests the static method (`KeywordVariantEnum::r#loop()`) and compares the result with the direct enum variant (`KeywordVariantEnum::r#Loop`). - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks. - * Relevant Behavior Rules: Rule 3a (Unit + Default), Rule 1a (Unit + `#[scalar]`). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unit (with keyword identifiers) - * Target File(s): - * `module/core/former/tests/inc/enum_unit_tests/keyword_variant_unit_derive.rs` - * `module/core/former/tests/inc/enum_unit_tests/keyword_variant_unit_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to keyword_variant_unit tests` - -* [✅] **Increment 5:** Document `standalone_constructor_unit_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Unit variants. - * Key attributes present: `#[derive(Former)]`, `#[standalone_constructors]` on the enum in `_derive.rs`. - * Relevant "Expected Enum Former Behavior Rule IDs": 3a, 1a, 4a. - * Brief summary of how test functions appear to exercise these rules: `unit_variant_test` tests the standalone constructor function (`unit_variant()`) and compares the result with the direct enum variant (`TestEnum::UnitVariant`). - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks. - * Relevant Behavior Rules: Rule 3a (Unit + Default), Rule 1a (Unit + `#[scalar]`), Rule 4a (#[standalone_constructors]). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unit (with `#[standalone_constructors]`) - * Target File(s): - * `module/core/former/tests/inc/enum_unit_tests/standalone_constructor_unit_derive.rs` - * `module/core/former/tests/inc/enum_unit_tests/standalone_constructor_unit_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to standalone_constructor_unit tests` - -* [✅] **Increment 6:** Document `standalone_constructor_args_unit_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Unit variants. - * Key attributes present: `#[derive(Former)]`, `#[standalone_constructors]`, `#[debug]` on the enum in `_derive.rs`. Manual implementation in `_manual.rs`. - * Relevant "Expected Enum Former Behavior Rule IDs": 3a, 1a, 4a. (Rule 4b is mentioned in the plan but not applicable to unit variants). - * Brief summary of how test functions appear to exercise these rules: `unit_variant_args_test` tests the standalone constructor function (`unit_variant_args()`) and compares the result with the direct enum variant (`TestEnumArgs::UnitVariantArgs`). - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks. - * Relevant Behavior Rules: Rule 3a (Unit + Default), Rule 1a (Unit + `#[scalar]`), Rule 4a (#[standalone_constructors]). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unit (with `#[standalone_constructors]` and `#[arg_for_constructor]` context - though unit variants have no args) - * Target File(s): - * `module/core/former/tests/inc/enum_unit_tests/standalone_constructor_args_unit_derive.rs` - * `module/core/former/tests/inc/enum_unit_tests/standalone_constructor_args_unit_manual.rs` - * `module/core/former/tests/inc/enum_unit_tests/standalone_constructor_args_unit_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to standalone_constructor_args_unit tests` - -* [✅] **Increment 7:** Document `compile_fail/unit_subform_scalar_error.rs` - * Detailed Plan Step 1: Read the content of the target file to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for the target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target file using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command (`cargo check --package former --tests`). - * Pre-Analysis: - * Identified enum variant structures in target file(s): Unit variant with `#[subform_scalar]`. - * Key attributes present: `#[derive(Former)]`, `#[standalone_constructors]` on the enum, `#[subform_scalar]` on the variant. - * Relevant "Expected Enum Former Behavior Rule IDs": Rule 2a (Unit + `#[subform_scalar]` -> Error). - * Brief summary of how test functions appear to exercise these rules: This is a compile-fail test file intended for use with `trybuild`. It defines the invalid structure that should cause a compilation error. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks. - * Relevant Behavior Rules: Rule 2a (Unit + `#[subform_scalar]` -> Error). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. The compile-fail test itself is verified by `trybuild` which is part of the broader test suite, but this increment only verifies that adding comments doesn't break compilation. - * Test Matrix: N/A - * Enum Aspect Focus: Unit (compile-fail scenario) - * Target File(s): `module/core/former/tests/inc/enum_unit_tests/compile_fail/unit_subform_scalar_error.rs` - * Commit Message: `docs(former): Add purpose and coverage to unit_subform_scalar_error compile_fail test` - -* [✅] **Increment 8:** Document `basic_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Single-field tuple variants (`Break(Break)`, `Run(Run)`). - * Key attributes present: `#[derive(Former)]`, `#[standalone_constructors]` on the enum; `#[subform_scalar]` on the `Break` variant. - * Relevant "Expected Enum Former Behavior Rule IDs": 3d, 2d, 4a, 4b. Rule 1d is not applicable to this test case. - * Brief summary of how test functions appear to exercise these rules: `basic_only_test.rs` contains tests that call the static methods (`FunctionStep::r#break()`, `FunctionStep::run()`) and the standalone constructor (`FunctionStep::break_variant()`). These tests then use the returned subformers to set fields and call `.form()`, asserting the final enum instance matches the expected value. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks, Structuring: Proc Macro Development Workflow. - * Relevant Behavior Rules: Rule 3d (Tuple + Default -> Subform), Rule 2d (Tuple + `#[subform_scalar]` -> InnerFormer), Rule 4a (#[standalone_constructors]), Rule 4b (Option 2 Logic). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unnamed/Tuple (basic single-field subform) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/basic_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/basic_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/basic_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to basic unnamed enum tests` - -* [✅] **Increment 9:** Document `enum_named_fields_unnamed_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Zero-field unnamed (tuple) variants (`VariantZeroUnnamedDefault()`, `VariantZeroUnnamedScalar()`). - * Key attributes present: `#[derive(Former)]`, `#[debug]`, `#[standalone_constructors]` on the enum; `#[scalar]` on the `VariantZeroUnnamedScalar` variant. - * Relevant "Expected Enum Former Behavior Rule IDs": 3b, 1b, 4a. Rule 4a is applicable due to the enum attribute but not explicitly tested in the provided test file. - * Brief summary of how test functions appear to exercise these rules: `enum_named_fields_unnamed_only_test.rs` contains tests that call the static methods (`EnumWithNamedFields::variant_zero_unnamed_scalar()`, `EnumWithNamedFields::variant_zero_unnamed_default()`) and assert that the returned value is the direct enum variant. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks, Structuring: Proc Macro Development Workflow. - * Relevant Behavior Rules: Rule 3b (Tuple + Zero-Field + Default), Rule 1b (Tuple + Zero-Field + `#[scalar]`), Rule 4a (#[standalone_constructors]). - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unnamed/Tuple (zero-field tuple variants) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/enum_named_fields_unnamed_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/enum_named_fields_unnamed_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/enum_named_fields_unnamed_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to enum_named_fields_unnamed tests` - -* [✅] **Increment 10:** Document `generics_independent_tuple_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Single-field tuple variant (`V1`) within a generic enum (`EnumG5`). The variant's field is a generic struct (`InnerG5`) instantiated with a concrete type (`TypeForU`), and the variant also contains `PhantomData` to use the enum's generic `T`. - * Key attributes present: `#[derive(Former)]` on both the enum and inner struct. `#[scalar]` on the `V1` variant. `#[standalone_constructors]` is on the enum but not explicitly tested in these files. - * Relevant "Expected Enum Former Behavior Rule IDs": Rule 1d (Tuple + Single-Field + `#[scalar]` -> Scalar), Rule 4b (Option 2 Logic - related to the subformer mechanism used). - * Brief summary of how test functions appear to exercise these rules: The tests in `_only_test.rs` call the static method `v_1()` (provided by the derive/manual file), which returns a former for the inner type (`InnerG5`). They use the setter `._0()` on this former to set the inner field and then call `.form()` to get the final `EnumG5` instance. They assert this instance is equal to a manually constructed `EnumG5::V1` variant. This verifies that the `#[scalar]` attribute on the tuple variant correctly results in a constructor that takes the inner type's value (via the subformer) and produces the enum variant, handling the independent generics correctly. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks, Structuring: Proc Macro Development Workflow. - * Relevant Behavior Rules: Rule 1d, Rule 4b. - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unnamed/Tuple (single-field tuple with independent generics, `#[scalar]`) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/generics_independent_tuple_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/generics_independent_tuple_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/generics_independent_tuple_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to generics_independent_tuple tests` - -* [✅] **Increment 11:** Document `generics_in_tuple_variant_tuple_*` and shared `_only_test` - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Single-field tuple variant (`Variant`) within a generic enum (`EnumOuter`), and unit variant (`OtherVariant`) within the same generic enum. The tuple variant's field is a generic struct (`InnerGeneric`) instantiated with the enum's generic `X`. - * Key attributes present: `#[derive(Former)]` on both the enum and inner struct. `#[debug]` on the enum. No specific variant attributes (`#[scalar]`, `#[subform_scalar]`) are used on the tested variants in this increment, relying on default behavior. `#[standalone_constructors]` is on the enum but not explicitly tested in these files. - * Relevant "Expected Enum Former Behavior Rule IDs": Rule 3d (Tuple + Single-Field + Default -> Subform), Rule 4b (Option 2 Logic - related to the subformer mechanism used), Rule 3a (Unit + Default). - * Brief summary of how test functions appear to exercise these rules: The tests in `_only_test.rs` call the static methods `variant()` (for the tuple variant) and `other_variant()` (for the unit variant) provided by the including file (derive/manual). For the tuple variant, they use the returned subformer's setter (`.inner_field()`) and `.form()`. For the unit variant, they directly assert the returned enum instance. Both test the handling of shared generics and bounds. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks, Structuring: Proc Macro Development Workflow. - * Relevant Behavior Rules: Rule 3d, Rule 4b, Rule 3a. - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unnamed/Tuple (single-field tuple with shared generics, default subform) and Unit (with shared generics, default scalar) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/generics_in_tuple_variant_tuple_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/generics_in_tuple_variant_tuple_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/generics_in_tuple_variant_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to generics_in_tuple_variant_tuple tests` - -* [✅] **Increment 12:** Document `generics_shared_tuple_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: - * Identified enum variant structures in target file(s): Single-field tuple variant (`V1`) within a generic enum (`EnumG3`). The variant's field is a generic struct (`InnerG3`) instantiated with the enum's generic `T`. - * Key attributes present: `#[derive(Former)]` on both the enum and inner struct. No specific variant attributes (`#[scalar]`, `#[subform_scalar]`) are used, relying on default behavior. - * Relevant "Expected Enum Former Behavior Rule IDs": Rule 3d (Tuple + Single-Field + Default -> Subform), Rule 4b (Option 2 Logic - related to the subformer mechanism used). - * Brief summary of how test functions appear to exercise these rules: The tests in `_only_test.rs` call the static method `v_1()` (provided by the derive/manual file), which returns a former for the inner type (`InnerG3`). They use the setter `.inner_field()` on this former to set the inner field and then call `.form()` to get the final `EnumG3` instance. They assert this instance is equal to a manually constructed `EnumG3::V1` variant. This verifies that the default behavior for a single-field tuple variant is to generate a subformer, handling the shared generics correctly. - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks, Structuring: Proc Macro Development Workflow. - * Relevant Behavior Rules: Rule 3d, Rule 4b. - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unnamed/Tuple (single-field tuple with shared generics, default subform) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/generics_shared_tuple_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/generics_shared_tuple_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/generics_shared_tuple_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to generics_shared_tuple tests` - -* [⏳] **Increment 13:** Document `keyword_variant_tuple_*` files - * Detailed Plan Step 1: Read the content of the target files to perform pre-analysis. - * Detailed Plan Step 2: Perform pre-analysis based on file content and plan rules. - * Detailed Plan Step 3: Draft the `//!` comments (Purpose, Coverage, Test Relevance/Acceptance Criteria) for each target file based on pre-analysis and plan requirements. - * Detailed Plan Step 4: Apply the drafted comments to the target files using `write_to_file`. - * Detailed Plan Step 5: Request user to run verification command. - * Pre-Analysis: (To be filled after reading files) - * Crucial Design Rules: Comments and Documentation, Comments: Spaces, Comments: Focus on Rationale, Preserve Existing Tasks, Comments: Add Tasks and Label Simplifications, Comments: Annotate Addressed Tasks, Structuring: Proc Macro Development Workflow. - * Relevant Behavior Rules: (To be filled after pre-analysis) - * Verification Strategy: After comments are added, request user to run `cargo check --package former --tests`. The code must compile without errors. - * Test Matrix: N/A - * Enum Aspect Focus: Unnamed/Tuple (variants with keyword identifiers, mixed scalar/subform) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/keyword_variant_tuple_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/keyword_variant_tuple_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to keyword_variant_tuple tests` - -* [⚫] **Increment 14:** Document `scalar_generic_tuple_*` files - * Enum Aspect Focus: Unnamed/Tuple (generic tuple variants with `#[scalar]`) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to scalar_generic_tuple tests` - -* [⚫] **Increment 15:** Document `standalone_constructor_args_tuple_*` files - * Enum Aspect Focus: Unnamed/Tuple (with `#[standalone_constructors]` and `#[arg_for_constructor]`) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_args_tuple_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_tuple_multi_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_tuple_single_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_args_tuple_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to standalone_constructor_args_tuple tests` - -* [⚫] **Increment 16:** Document `standalone_constructor_tuple_*` files - * Enum Aspect Focus: Unnamed/Tuple (with `#[standalone_constructors]`, no field args) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to standalone_constructor_tuple tests` - -* [⚫] **Increment 17:** Document `tuple_multi_default_*` files - * Enum Aspect Focus: Unnamed/Tuple (multi-field, default scalar behavior) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to tuple_multi_default tests` -* [⚫] **Increment 18:** Document `tuple_multi_scalar_*` files - * Enum Aspect Focus: Unnamed/Tuple (multi-field with `#[scalar]`) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to tuple_multi_scalar tests` - -* [⚫] **Increment 19:** Document `tuple_multi_standalone_args_*` files - * Enum Aspect Focus: Unnamed/Tuple (multi-field with `#[standalone_constructors]` and `#[arg_for_constructor]`) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to tuple_multi_standalone_args tests` - -* [⚫] **Increment 20:** Document `tuple_multi_standalone_*` files - * Enum Aspect Focus: Unnamed/Tuple (multi-field with `#[standalone_constructors]`, no field args) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to tuple_multi_standalone tests` - -* [⚫] **Increment 21:** Document `tuple_zero_fields_*` files - * Enum Aspect Focus: Unnamed/Tuple (zero-field tuple variants) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to tuple_zero_fields tests` - -* [⚫] **Increment 22:** Document `usecase1*` files - * Enum Aspect Focus: Unnamed/Tuple (single-field tuple, default subform, multiple variants) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/usecase1.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/usecase1_derive.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/usecase1_manual.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/usecase1_only_test.rs` - * Commit Message: `docs(former): Add purpose and coverage to usecase1 unnamed enum tests` - -* [⚫] **Increment 23:** Document `compile_fail/*` files for unnamed variants - * Enum Aspect Focus: Unnamed/Tuple (compile-fail scenarios) - * Target File(s): - * `module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_multi_subform_scalar_error.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_single_subform_non_former_error.rs` - * `module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_zero_subform_scalar_error.rs` - * Commit Message: `docs(former): Add purpose and coverage to unnamed enum compile_fail tests` - -### Requirements -* **Adherence:** Strictly follow `code/gen` instructions, Design Rules, and Codestyle Rules for all modifications. -* **Comment Content:** Each targeted test file **must** have the following three `//!` (file-level doc comments) added at the very beginning, before any `use` statements or code, in the specified order: - 1. **`//! Purpose: ...`**: - * Start with "Purpose:". - * Clearly and concisely describe the main goal of the test file. What specific aspect of the `Former` derive macro's behavior for enums is this file intended to verify? - * Mention the specific enum variant structure(s) (e.g., "unit variants", "single-field tuple variants with generics", "multi-field named struct variants") and any key attributes (e.g., `#[scalar]`, `#[subform_scalar]`, `#[standalone_constructors]`) being tested in this file. - * State whether the file is for `derive` macro testing, `manual` implementation testing, or `shared test logic` (`_only_test.rs`). - * For `compile_fail` tests, clearly state the specific incorrect usage or error condition it's designed to trigger and verify, referencing the relevant behavior rule that is being intentionally violated. - * **For `_only_test.rs` files:** The purpose should state that it provides shared test assertions/logic for both derived and manual implementations of [specific feature/variant type]. - 2. **`//! Coverage: ...`**: - * Start with "Coverage:". - * List the specific Rule IDs (e.e., "Rule 1a", "Rule 3d.i") from the "Expected Enum Former Behavior Rules" section that the tests in this file primarily demonstrate or validate. - * Briefly explain *what aspect* of the rule is being tested if the rule is broad and the test is specific (e.g., "Rule 4b - specifically the 'returns Former' case for standalone constructors with partial args"). - * If a test covers interactions between multiple rules (e.g., a variant attribute combined with an enum-level attribute), list all relevant rules and briefly note the interaction. - * **For `_only_test.rs` files:** This comment should summarize all rules covered by the test functions within it, which are then applied to both `_derive.rs` and `_manual.rs` files that include it. - 3. **`//! Test Relevance/Acceptance Criteria: ...`**: - * Start with "Test Relevance/Acceptance Criteria:". - * Describe the key actions performed by the test code and the primary assertions made that validate its stated purpose and coverage. This should explain *how* the test verifies the intended behavior. - * Be specific about the test's mechanics: - * What specific enum structures or attributes are defined/used in this test? - * What specific generated/manual methods are invoked (e.g., `MyEnum::variant_x()`, `former.field_y()`, standalone `variant_z()`)? - * What are the key inputs provided to these methods? - * What is the nature of the primary assertion (e.g., "Asserts the `got` instance (produced by the former) is equal to an `expected` instance (manually constructed to represent the correct state).", "Asserts that a subformer is returned and can be used to set inner fields.", "Asserts that a compile-time error occurs for an invalid attribute combination using `trybuild`."). - * **For `_derive.rs` files:** Mention that it relies on `#[derive(Former)]` for code generation and typically includes shared test logic via `include!("...")`. - * **For `_manual.rs` files:** Mention that it contains a hand-written former implementation and includes shared test logic via `include!("...")`. - * **For `compile_fail/*.rs` files:** The file contains code that intentionally uses an attribute or enum structure in a way that violates a documented behavior rule (i.e., `#[subform_scalar]` on a unit variant). The test is accepted if `trybuild` confirms this results in a compilation error, thereby validating the macro's error reporting for this specific invalid scenario." -* **Comment Style:** All added `//!` comments should be clear, concise, grammatically correct, and follow Rust documentation comment conventions. Use Markdown for lists or emphasis if it enhances readability. Aim for reasonable line lengths. -* **Pre-Analysis Output:** Before proposing comments for an increment, the AI must provide its pre-analysis findings for the targeted file(s) as specified in the "Increment Template". -* **Incremental Processing:** Modify files one increment at a time, following the "Increment Template." -* **Verification:** After each increment, request user to apply changes and run `cargo check --package former --tests`. **The code must compile successfully after adding comments. If adding comments introduces a compilation error (e.e., a syntax error in the comment itself), that specific error must be fixed. Pre-existing test failures or logic errors are out of scope.** -* **No Functional Changes:** This task is purely for documentation and review. No functional code changes should be made to the tests or macro logic unless a comment itself causes a trivial syntax issue that prevents compilation. -* **Handling `xxx`/`qqq` Comments:** During the review of each test file, if any existing `// xxx :` or `// qqq :` comments are encountered, their presence and a brief summary of their content should be noted in the "Notes & Insights" section of the `plan.md` for that increment. Addressing or resolving these comments is out of scope for this plan. -* **`mod.rs` Files Review:** If, during the review of test files, it's discovered that an enum test file exists in the directories but is not declared in its respective `mod.rs` file, this should be noted in the "Notes & Insights" for that increment. Activating it is out of scope. - -## Notes & Insights -* This plan focuses exclusively on documenting existing enum tests by adding comments. It does not involve fixing failing tests or implementing new features. -* The "Expected Enum Former Behavior Rules" section is critical for determining coverage. -* The "Increment Template" will be used for detailed planning of each increment. -* The `_only_test.rs` files, when shared, will have their documentation reflect their broader applicability. -* **[Date/Inc #] Note:** Increment 3 and 11 both reference `generics_in_tuple_variant_only_test.rs`. The documentation for this shared file should be comprehensive enough to cover its usage in both unit and tuple variant contexts, likely handled in Increment 11. -* **[Date/Inc #] Note:** The commit messages in the Increment Template now include `[enum_aspect_focus]` for better categorization. -* **[2025-05-10/Inc 1] Note:** Started detailed planning for Increment 1: Document `unit_variant_*` files. Pre-analysis complete. Proceeding to draft and apply comments. -* **[2025-05-10/Inc 1] Note:** Encountered repeated failures using `apply_diff` to add comments to `unit_variant_only_test.rs`. Changing strategy for Detailed Plan Step 4 to use `write_to_file` as a fallback to replace the entire file content with the desired version containing the corrected comments. -* **[2025-05-10/Inc 1] Note:** Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 1 complete. -* **[2025-05-10/Inc 2] Note:** Started detailed planning for Increment 2: Document `enum_named_fields_unit_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 2 complete. -* **[2025-05-10/Inc 3] Note:** Started detailed planning for Increment 3: Document `generics_in_tuple_variant_unit_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 3 complete. -* **[2025-05-10/Inc 4] Note:** Started detailed planning for Increment 4: Document `keyword_variant_unit_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 4 complete. -* **[2025-05-10/Inc 5] Note:** Started detailed planning for Increment 5: Document `standalone_constructor_unit_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 5 complete. -* **[2025-05-10/Inc 6] Note:** Started detailed planning for Increment 6: Document `standalone_constructor_args_unit_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 6 complete. -* **[2025-05-10/Inc 7] Note:** Started detailed planning for Increment 7: Document `compile_fail/unit_subform_scalar_error.rs`. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 7 complete. -* **[2025-05-10/Inc 8] Note:** Started detailed planning for Increment 8: Document `basic_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 8 complete. -* **[2025-05-10/Inc 9] Note:** Started detailed planning for Increment 9: Document `enum_named_fields_unnamed_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 9 complete. -* **[2025-05-10/Inc 10] Note:** Started detailed planning for Increment 10: Document `generics_independent_tuple_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 10 complete. -* **[2025-05-10/Inc 11] Note:** Started detailed planning for Increment 11: Document `generics_in_tuple_variant_tuple_*` and shared `_only_test`. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 11 complete. -* **[2025-05-10/Inc 12] Note:** Started detailed planning for Increment 12: Document `generics_shared_tuple_*` files. Pre-analysis complete. Proceeding to draft and apply comments. Successfully applied comments and verified compilation with `cargo check --package former --tests`. Increment 12 complete. -* **[2025-05-10/Inc 13] Note:** Started detailed planning for Increment 13: Document `keyword_variant_tuple_*` files. Pre-analysis complete. Proceeding to draft and apply comments. \ No newline at end of file +* **Other Active Plans:** The refactoring plan for `former_meta` (`former_meta/plan.md`) should be considered, as changes here might affect its assumptions. + +### Project Requirements +* (This section should be cumulative. Assuming previous project requirements like Rust edition 2021, documentation for public APIs, etc., are still in effect. New project-level requirements identified will be added here.) +* **Behavioral Equivalence:** Refactoring must not change the externally observable behavior or the generated code structure of the `Former` macro for enum unit variants, unless explicitly justified by a bug fix or alignment with documented "Expected Enum Former Behavior". Existing tests in the `former` crate for unit variants serve as the primary regression guard. +* **`macro_tools` Generalization:** All new or modified code in `macro_tools` must be general-purpose, well-documented, and include unit tests. Utilities should not be overly specific to `former_meta`'s internal implementation details. +* **Code Quality:** Code changes should demonstrably improve clarity, maintainability, and reduce redundancy in `unit_variant_handler.rs`. +* **Error Reporting:** If `macro_tools` utilities are used for error handling, the quality (clarity, span accuracy) of compiler error messages generated by `former_meta` must be maintained or improved. +* **Performance:** The refactoring should not introduce measurable performance regressions in macro expansion time. (Primarily a consideration for complex macros, but good to keep in mind). +* **Rule Adherence:** All new and modified code must strictly adhere to the system prompt's Design Rules and Codestyle Rules, overriding existing styles in the repository if they conflict. +* **Proc Macro Workflow:** While this is primarily a refactoring task, if any part of the core macro logic generation for unit variants is significantly altered (beyond just using helper functions), the principles of the "Proc Macro: Development Workflow" (e.g., clear separation of concerns, testability) should be respected. +* **Verification Scope:** All `cargo` commands for verification (check, test, clippy) **must be scoped to individual packages** (e.g., `cargo test --package former_meta`) unless an increment explicitly plans for workspace-level integration testing as a final step. + +### Expected Behavior Rules (Enum Unit Variants) +* **Rule 1a (Unit + `#[scalar]`):** Generates `Enum::variant() -> Enum`. (Handled by: `unit_variant_handler.rs`) +* **Rule 2a (Unit + `#[subform_scalar]`):** Error. (Checked in: `unit_variant_handler.rs`) +* **Rule 3a (Unit + Default):** Generates `Enum::variant() -> Enum`. (Handled by: `unit_variant_handler.rs`) +* **Rule 4a (`#[standalone_constructors]` on Enum):** + * For unit variants, generates top-level `fn variant_name() -> EnumName` (or `fn enum_name_variant_name() -> EnumName` depending on naming convention for standalone, to be confirmed from existing behavior). The name should be snake_case. + +### Increments + +* [✅] **Increment 1: Analyze `macro_tools` for `former_meta` (Enum Unit Variants)** + * Target Crate(s): `macro_tools` (read-only), `former_meta` (analysis target) + * Pre-Analysis: The goal is to identify how `macro_tools` can simplify `former_meta`'s unit variant handling. This requires a thorough understanding of `macro_tools` capabilities and the current implementation in `former_meta/src/derive_former/former_enum/unit_variant_handler.rs`. The existing "Notes & Insights" section already provides some initial pointers (e.g., `ident_maybe_raw`, `syn_err!`, `generic_params::decompose`). + * Detailed Plan Step 1: Systematically review each module and public item in `module/core/macro_tools/src/`. This involves using `list_files` to get an accurate list of modules and then conceptually (or with `read_file` if needed for specific complex utilities) understanding their purpose. + * Detailed Plan Step 2: For each identified `macro_tools` utility, assess its direct applicability to simplifying or improving the logic in `module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs` and its interaction with `module/core/former_meta/src/derive_former/former_enum.rs` (e.g., `EnumVariantHandlerContext`, attribute parsing). Consider: + * Attribute parsing (`attr.rs`, `attr_prop.rs`): For `#[scalar]`, `#[subform_scalar]` on variants, and `#[standalone_constructors]`, `#[debug]` on the enum. + * Identifier generation/manipulation (`ident.rs`, `name.rs`, `kw.rs`): For constructor names, handling raw identifiers. + * Generic parameter handling (`generic_params.rs`, `generic_args.rs`): For generic enums and their constructors. + * Error reporting (`diag.rs`): For `syn_err!`, `return_syn_err!`. + * Code quoting (`qt!`, `quote!`). + * Type analysis (`typ.rs`): If any type introspection is needed for unit variants (less likely for units). + * Detailed Plan Step 3: **Output (as a textual report in the AI's response, not a file):** Produce a detailed report mapping specific `macro_tools` utilities to concrete code sections or logic patterns in `unit_variant_handler.rs` and `former_enum.rs` (related to unit variants). For each mapping, explain the potential benefit (e.g., "Replace custom ident logic with `ident::ident_maybe_raw`", "Use `AttributePropertyOptionalSingletone` for `#[scalar]` flag"). This report will be the main deliverable of this increment. + * Crucial Design Rules: [Prioritize Reuse and Minimal Change], [Comments and Documentation]. + * Relevant Behavior Rules: Rules 1a, 2a, 3a, 4a (to ensure proposed `macro_tools` usage aligns with expected outcomes). + * Verification Strategy: User reviews the detailed analysis report and mapping presented in the AI's response. No code changes, so no compilation or tests. + * Test Matrix: Not applicable for this analysis increment. + * Commit Message: `docs(former_meta): Analyze macro_tools for refactoring unit variant handling` + +* [✅] **Increment 2: Analyze `former_meta` (Enum Unit Variants) for `macro_tools` Generalizations** + * Target Crate(s): `former_meta` (read-only), `macro_tools` (analysis target) + * Pre-Analysis: The goal is to identify custom logic in `former_meta`'s unit variant handling that could be generalized and moved to `macro_tools`. This requires careful review of `former_meta/src/derive_former/former_enum/unit_variant_handler.rs` and related context. + * Detailed Plan Step 1: Review `former_meta/src/derive_former/former_enum/unit_variant_handler.rs` and related logic in `former_meta/src/derive_former/former_enum.rs` (e.g., parts of `EnumVariantHandlerContext` or its setup if relevant to unit variants specifically and generalizable). This will involve using `read_file` to examine these files. + * Detailed Plan Step 2: Identify any custom logic, patterns, or helper functions used for unit variant handling that are sufficiently generic and could be beneficial to other procedural macro development if moved to `macro_tools`. + * Detailed Plan Step 3: **Output (as a textual report in the AI's response, not a file):** Document findings as a list of concrete proposals for new utilities or modifications for `macro_tools`. Each proposal must include: + * Proposed function/struct/trait signature. + * Target module within `macro_tools`. + * Clear description of its purpose and generic applicability. + * A brief example of how it would be used. + * Crucial Design Rules: [Traits: Encourage Modular Design], [Visibility: Keep Implementation Details Private]. + * Relevant Behavior Rules: N/A for this analysis increment, but proposals should align with general good API design. + * Verification Strategy: User reviews the documented analysis and concrete proposals for `macro_tools` presented in the AI's response. No code changes, so no compilation or tests. + * Test Matrix: Not applicable for this analysis increment. + * Commit Message: `docs(macro_tools): Analyze former_meta unit variant logic for potential generalizations` + +* [✅] **Increment 3: Propose Initial Detailed Refactoring Solution for Enum Unit Variants** + * Target Crate(s): `former_meta`, `macro_tools` + * Pre-Analysis: Based on the analyses from Increments 1 and 2, the goal is to draft a detailed initial refactoring plan for `former_meta/src/derive_former/former_enum/unit_variant_handler.rs`. This involves showing how `macro_tools` utilities (existing or proposed in Increment 2) will be used. + * Detailed Plan Step 1: Draft the detailed initial refactoring plan for `former_meta/src/derive_former/former_enum/unit_variant_handler.rs`. This will involve: + * Identifying specific code sections in the current `unit_variant_handler.rs` (read in Increment 2). + * Mapping these sections to the `macro_tools` utilities identified in Increment 1 (e.g., `attr::Attributes::retrieve_optional_singletone_bool`, `diag::return_syn_err!`, `ident::new_ident_from_cased_str` (proposed), `generic_params::GenericsRef` methods (proposed), `tokens::qt!`). + * Showing conceptual "before-and-after" code snippets or detailed pseudo-code. + * Detailed Plan Step 2: **Output (as a textual report in the AI's response, not a file):** For `unit_variant_handler.rs`, provide: + * Conceptual "before-and-after" code snippets (or pseudo-code) demonstrating how `macro_tools` utilities will replace or augment existing logic. + * Clear explanation of changes to data flow or helper function usage. + * Detailed Plan Step 3: **Output (as a textual report in the AI's response, not a file):** For `macro_tools`, provide: + * Finalized signatures and intended module placement for any new utilities proposed in Increment 2 (i.e., `ident::new_ident_from_cased_str` and `generic_params::GenericsRef` helper methods). + * Detailed Plan Step 4: Outline the expected impact on code size, readability, and maintainability in `unit_variant_handler.rs`. + * Detailed Plan Step 5: Briefly assess if this refactoring impacts the `former_meta/plan.md` for splitting large files. (Given `unit_variant_handler.rs` is already relatively small and focused, significant impact is unlikely, but it should be considered). + * Crucial Design Rules: [Prioritize Reuse and Minimal Change], [Code Style: Do Not Reformat Arbitrarily] (when showing existing code), [Comments and Documentation] (for new proposed utilities). + * Relevant Behavior Rules: Rules 1a, 2a, 3a, 4a (to ensure the proposed refactoring maintains correct behavior). + * Verification Strategy: User reviews the detailed refactoring solution presented in the AI's response. No code changes, so no compilation or tests. + * Test Matrix: Not applicable for this planning/proposal increment. + * Commit Message: `docs(former_meta): Propose initial detailed refactoring for unit variant handling` + +* [✅] **Increment 4: Critique and Improve Refactoring Solution** + * Target Crate(s): `former_meta`, `macro_tools` + * Input: The detailed refactoring solution from Increment 3. + * Pre-Analysis: The goal is to critically evaluate the refactoring solution proposed in Increment 3 and suggest improvements. This involves checking for effectiveness, simplification, generalization quality, complexity, rule adherence, and maintainability. + * Detailed Plan Step 1: Perform a self-critique of the *detailed* initial refactoring solution from Increment 3. + * **Effectiveness & Simplification:** + * Does the proposed use of `macro_tools::diag::return_syn_err!` simplify error handling for `#[subform_scalar]`? Yes, it's more direct. + * Does the proposed `macro_tools::ident::new_ident_from_cased_str` significantly simplify identifier creation? Yes, it encapsulates complex keyword and raw string logic. + * Do the proposed `GenericsRef` methods simplify generic token generation? Yes, they reduce boilerplate. + * Is the switch to `macro_tools::tokens::qt!` a significant improvement? It's mostly stylistic but aligns with using `macro_tools`. + * **Generalization Quality:** + * Is `new_ident_from_cased_str` truly generic? Yes, identifier generation with case conversion and keyword/raw handling is a common macro task. The proposed signature seems reasonable. + * Are the `GenericsRef` helper methods (`impl_generics_tokens_if_any`, `ty_generics_tokens_if_any`, `type_path_tokens_if_any`) generic? Yes, quoting generics conditionally is common. + * **Complexity Trade-offs:** + * Does introducing these new `macro_tools` utilities add undue complexity? No, they seem to encapsulate existing complexity into reusable forms. The benefit outweighs the cost of adding these small, focused utilities. + * **Rule Adherence & Correctness:** + * Does the proposed refactoring align with "Expected Enum Former Behavior"? Yes, the core logic of what's generated remains the same. + * Are there edge cases missed for `new_ident_from_cased_str`? The proposal mentions returning `Result` for robustness, which is good. The keyword list/detection mechanism needs to be solid. + * Are generics handled correctly? The proposed `GenericsRef` methods aim to standardize this. + * **Maintainability Impact:** + * Will `unit_variant_handler.rs` be easier to maintain? Yes, due to simplification and delegation. + * Will the new `macro_tools` utilities be maintainable? Yes, if well-tested and documented. + * Detailed Plan Step 2: **Output (as a textual report in the AI's response, not a file):** Based on the critique, propose specific, actionable improvements or alternatives to the refactoring plan. + * Crucial Design Rules: [Prioritize Reuse and Minimal Change], [Comments and Documentation]. + * Relevant Behavior Rules: Rules 1a, 2a, 3a, 4a. + * Verification Strategy: User reviews the critique and the improved refactoring solution. No code changes. + * Test Matrix: Not applicable. + * Commit Message: `docs(former_meta): Critique and improve refactoring plan for unit variants` + +* [✅] **Increment 5: Implement Improved Refactoring (Enum Unit Variants in `former_meta`)** + * Target Crate(s): `former_meta` + * Pre-Analysis: Review the approved improved refactoring solution from Increment 4. This means the changes will be based on using the (yet to be implemented in `macro_tools`) utilities: + * `macro_tools::diag::return_syn_err!` (existing, but usage confirmed) + * `macro_tools::ident::new_ident_from_cased_str` (proposed in Inc 4, to be implemented in Inc 6) + * `macro_tools::generic_params::GenericsRef` enhanced methods (`impl_generics_tokens_if_any`, `ty_generics_tokens_if_any`, `type_path_tokens_if_any`, `where_clause_tokens_if_any`) (proposed in Inc 4, to be implemented in Inc 6). + * **Crucially, since the `macro_tools` utilities are not yet implemented, this increment will involve writing the `former_meta` code *as if* they exist.** The actual compilation of `former_meta` will only fully succeed after Increment 6 is completed. This is acceptable as per the plan structure. + * Detailed Plan Step 1: Modify `former_meta/src/derive_former/former_enum/unit_variant_handler.rs` according to the approved plan from Increment 4. This involves: + * Replacing the `#[subform_scalar]` error handling with `macro_tools::diag::return_syn_err!`. + * Replacing the manual identifier creation for `method_ident` with a call to the conceptual `macro_tools::ident::new_ident_from_cased_str`. + * Replacing manual generic quoting with calls to the conceptual `macro_tools::generic_params::GenericsRef` helper methods. + * Potentially switching `quote!` to `macro_tools::tokens::qt!`. + * Detailed Plan Step 2: Ensure all existing tests in `former` crate for enum unit variants *would conceptually* continue to pass with identical behavior. Actual test runs for `former_meta` will depend on Increment 6. + * Crucial Design Rules: [Prioritize Reuse and Minimal Change], [Proc Macro: Development Workflow]. + * Relevant Behavior Rules: Rules 1a, 2a, 3a, 4a. + * Verification Strategy: + * User applies changes to `former_meta/src/derive_former/former_enum/unit_variant_handler.rs`. + * `cargo check --package former_meta` will likely fail due to missing `macro_tools` utilities, which is expected at this stage. The primary verification is code review against the plan from Increment 4. + * A full `cargo test --package former --test tests -- inc::enum_unit_tests` will be deferred until after Increment 6. The immediate goal is to ensure the `unit_variant_handler.rs` code *structurally* matches the refactoring plan. + * Test Matrix: Not applicable for this refactoring increment directly, but existing tests cover behavior. + * Commit Message: `refactor(former_meta): Improve unit variant handling using macro_tools` + +* [⏳] **Increment 6: Implement Generalizations (New Utilities in `macro_tools`)** + * Target Crate(s): `macro_tools` + * Pre-Analysis: Review the approved new utilities for `macro_tools` from Increment 4. These are: + 1. `macro_tools::ident::new_ident_from_cased_str` + 2. `macro_tools::generic_params::GenericsRef` enhanced methods: + * `impl_generics_tokens_if_any()` + * `ty_generics_tokens_if_any()` + * `where_clause_tokens_if_any()` + * `type_path_tokens_if_any()` + * (And the conceptual private helper `split_for_impl_syn_components` or equivalent logic to access decomposed generic parts). + * Detailed Plan Step 1: Implement these utilities in `module/core/macro_tools/src/ident.rs` and `module/core/macro_tools/src/generic_params.rs`. + * Detailed Plan Step 2: Add comprehensive unit tests for these new utilities. This will involve creating new test files or extending existing ones in `module/core/macro_tools/tests/inc/` (e.g., a new `ident_general_tests.rs`, `generic_params_ref_tests.rs` or similar, and updating `module/core/macro_tools/tests/inc/mod.rs`). + * Detailed Plan Step 3: Update `module/core/macro_tools/src/lib.rs` and relevant module files (`ident.rs`, `generic_params.rs` themselves if they define `pub` items, or their parent `mod.rs` if they are submodules) to correctly export the new public utilities. + * Detailed Plan Step 4: Add clear `///doc` comments for all new public items in `macro_tools`. + * Crucial Design Rules: [Traits: Encourage Modular Design], [Visibility: Keep Implementation Details Private], [Comments and Documentation], [Testing: Plan with a Test Matrix When Writing Tests]. + * Relevant Behavior Rules: N/A directly, but API design should be robust and adhere to Rust conventions. + * Verification Strategy: + * User applies changes to `macro_tools`. + * `cargo check --package macro_tools` must pass. + * `cargo test --package macro_tools` must pass. + * `cargo doc --package macro_tools --no-deps` should build successfully. + * `cargo clippy --package macro_tools --all-targets -- -D warnings` should pass. + * Test Matrix: + * **For `new_ident_from_cased_str` (in `macro_tools::ident`):** + * ID: T6.1, Input: (`"normal_ident"`, `span`, `false`), Expected: `Ok(syn::Ident::new("normal_ident", span))` + * ID: T6.2, Input: (`"fn"`, `span`, `false`), Expected: `Ok(syn::Ident::new_raw("fn", span))` (keyword becomes raw) + * ID: T6.3, Input: (`"fn"`, `span`, `true`), Expected: `Ok(syn::Ident::new_raw("fn", span))` (original raw, cased is keyword) + * ID: T6.4, Input: (`"my_raw_ident"`, `span`, `true`), Expected: `Ok(syn::Ident::new_raw("my_raw_ident", span))` (original raw, cased not keyword) + * ID: T6.5, Input: (`""`, `span`, `false`), Expected: `Err(_)` (empty string) + * ID: T6.6, Input: (`"with space"`, `span`, `false`), Expected: `Err(_)` (invalid ident chars) + * ID: T6.7, Input: (`"ValidIdent"`, `span`, `false`), Expected: `Ok(syn::Ident::new("ValidIdent", span))` (function assumes input is already cased as desired for the ident name itself, only keyword/raw status is handled). + * **For `GenericsRef` methods (in `macro_tools::generic_params`):** + * (Setup: `let generics_std: syn::Generics = syn::parse_quote! { where T: Debug > };`) + * (Setup: `let generics_empty: syn::Generics = syn::parse_quote! { };`) + * (Setup: `let enum_name: syn::Ident = syn::parse_quote! { MyEnum };`) + * ID: T6.8 (`impl_generics_tokens_if_any` with `generics_std`): Expected: `Ok(quote!( ))` + * ID: T6.9 (`impl_generics_tokens_if_any` with `generics_empty`): Expected: `Ok(quote!( ))` + * ID: T6.10 (`ty_generics_tokens_if_any` with `generics_std`): Expected: `Ok(quote!( ))` + * ID: T6.11 (`ty_generics_tokens_if_any` with `generics_empty`): Expected: `Ok(quote!( ))` + * ID: T6.12 (`where_clause_tokens_if_any` with `generics_std`): Expected: `Ok(quote!( where T: Debug ))` + * ID: T6.13 (`where_clause_tokens_if_any` with `generics_empty`): Expected: `Ok(quote!( ))` + * ID: T6.14 (`type_path_tokens_if_any` with `generics_std`, `enum_name`): Expected: `Ok(quote!( MyEnum:: ))` + * ID: T6.15 (`type_path_tokens_if_any` with `generics_empty`, `enum_name`): Expected: `Ok(quote!( MyEnum ))` + * Commit Message: `feat(macro_tools): Add new utilities generalized from former_meta enum handling` + +* [⚫] **Increment 7: Final Verification and Documentation Update** + * Target Crate(s): `former_meta`, `macro_tools`, `former` + * Detailed Plan Step 1: Run `cargo clippy --package former_meta --all-targets -- -D warnings` and address any new lints. + * Detailed Plan Step 2: Run `cargo clippy --package macro_tools --all-targets -- -D warnings` and address any new lints. + * Detailed Plan Step 3: Run `cargo test --package former_meta` and `cargo test --package macro_tools`. + * Detailed Plan Step 4: Run `cargo test --package former --test tests -- inc::enum_unit_tests` (and any other directly affected test suites) to ensure no regressions. + * Detailed Plan Step 5: Update any relevant internal documentation or comments in `former_meta` (especially `unit_variant_handler.rs`) and `macro_tools` to reflect the refactoring and new utilities. + * Detailed Plan Step 6: Review if the `former_meta/plan.md` (for splitting large files) needs adjustment based on changes to `unit_variant_handler.rs` or `former_enum.rs`. Propose updates if necessary. + * Verification Strategy: User confirms all checks pass and reviews documentation updates and any proposed changes to other plans. + * Commit Message: `chore(former): Final verification and docs update after unit variant refactor` + +### Requirements (Task-Specific) +* The refactoring should prioritize clarity, maintainability, and testability of `unit_variant_handler.rs`. +* Any utilities moved to or created in `macro_tools` must be genuinely reusable, well-documented with examples (if applicable for complex utilities), and not overly specific to `former_meta`'s internal logic. +* The "Expected Enum Former Behavior" for unit variants must be strictly preserved or corrected if bugs are found and approved as part of the plan. +* Naming conventions for standalone constructors (e.g., `variant_name()` vs `enum_name_variant_name()`) should be consistent with the established patterns in `former_meta` or clarified if ambiguous. +* Consider the impact on generic enums: ensure refactoring correctly handles generics in unit variant constructors (both static and standalone). + +### Notes & Insights +* (This section will be populated as the plan progresses) +* `unit_variant_handler.rs` currently handles `#[scalar]` (which is the default behavior for unit variants) and correctly errors on `#[subform_scalar]`. It also needs to interact with the enum-level `#[standalone_constructors]` attribute (parsed in `struct_attrs.rs` and available in `EnumVariantHandlerContext`). +* The primary logic in `unit_variant_handler.rs` involves generating a simple static method and, if `#[standalone_constructors]` is present, a corresponding standalone function. Both typically construct the enum variant directly (e.g., `EnumName::VariantName`). +* `macro_tools::ident::ident_maybe_raw` will be useful for generating constructor names from variant idents, especially if variants use raw identifiers (e.g., `r#fn`). +* `macro_tools::diag::syn_err!` and `return_syn_err!` are already suitable for error reporting (e.g., for `#[subform_scalar]` on a unit variant). +* `macro_tools::generic_params::decompose` and related functions will be crucial if the enum is generic, to correctly propagate generics to standalone constructors. +* The `EnumVariantHandlerContext` provides necessary context like `vis`, `generics`, `enum_name`, `variant_ident`, and `struct_attrs`. The refactoring should leverage this context effectively. diff --git a/module/core/former/tests/inc/enum_complex_tests/subform_collection_test.rs b/module/core/former/tests/inc/enum_complex_tests/subform_collection_test.rs index 0864196046..160a74eaf4 100644 --- a/module/core/former/tests/inc/enum_complex_tests/subform_collection_test.rs +++ b/module/core/former/tests/inc/enum_complex_tests/subform_collection_test.rs @@ -1,64 +1,81 @@ +//! Purpose: This file is a test case demonstrating the current limitation and compilation failure +//! when attempting to use the `#[subform_entry]` attribute on a field that is a collection of enums +//! (specifically, `Vec`). It highlights a scenario that is not currently supported by +//! the `Former` macro. +//! +//! Coverage: +//! - This file primarily demonstrates a scenario *not* covered by the defined "Expected Enum Former Behavior Rules" +//! because the interaction of `#[subform_entry]` with collections of enums is not a supported feature. +//! It implicitly relates to the concept of subform collection handling but serves as a test for an unsupported case. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a simple enum `SimpleEnum` deriving `Former`. +//! - Defines a struct `StructWithEnumVec` containing a `Vec` field. +//! - Applies `#[subform_entry]` to the `Vec` field. +//! - The entire file content is commented out, including a test function (`attempt_subform_enum_vec`) that demonstrates the intended (but unsupported) usage of a hypothetical subformer for the enum collection. +//! - This file is intended to be a compile-fail test or a placeholder for a future supported feature. The test is accepted if attempting to compile code that uses `#[subform_entry]` on a collection of enums results in a compilation error (as indicated by the comments). + // // File: module/core/former/tests/inc/former_enum_tests/subform_collection_test.rs // //! Minimal test case demonstrating the compilation failure // //! when using `#[subform_entry]` on a `Vec`. -// -// use super::*; -// use former::Former; -// use std::vec::Vec; -// -// /// A simple enum deriving Former. -// #[ derive( Debug, PartialEq, Clone, Former ) ] -// pub enum SimpleEnum -// { -// /// Unit variant. -// Unit, -// /// Tuple variant with a single value. -// #[ scalar ] // Use scalar for direct constructor -// Value( i32 ), -// } -// -// /// A struct containing a vector of the enum. -// #[ derive( Debug, PartialEq, Default, Former ) ] -// pub struct StructWithEnumVec -// { -// /// Field attempting to use subform_entry on Vec. -// #[ subform_entry ] -// items : Vec< SimpleEnum >, -// } -// -// /// Test attempting to use the subformer generated for `items`. -// /// This test FAIL TO COMPILE because `former` does not -// /// currently support generating the necessary subformer logic for enum entries -// /// within a collection via `#[subform_entry]`. -// #[ test ] -// fn attempt_subform_enum_vec() -// { -// // This code block demonstrates the intended usage that fails. -// /* -// let _result = StructWithEnumVec::former() -// // Trying to access the subformer for the Vec field. -// // The derive macro does not generate the `.items()` method correctly -// // for Vec with #[subform_entry]. It doesn't know how to -// // return a former that can then construct *specific enum variants*. -// .items() -// // Attempting to call a variant constructor method (e.g., .value()) -// // on the hypothetical subformer returned by .items(). This method -// // would not be generated. -// .value( 10 ) -// // Ending the hypothetical subformer for the first enum entry. -// .end() -// // Attempting to start another entry. -// .items() -// // Attempting to call the unit variant constructor method. -// .unit() -// // Ending the hypothetical subformer for the second enum entry. -// .end() -// // Finalizing the parent struct. -// .form(); -// */ -// -// // Assertion to make the test function valid, though it won't be reached -// // if the compilation fails as expected. -// assert!( true, "Test executed - compilation should have failed before this point." ); -// } -// // qqq : xxx : make it working +// // +// // use super::*; +// // use former::Former; +// // use std::vec::Vec; +// // +// // /// A simple enum deriving Former. +// // #[ derive( Debug, PartialEq, Clone, Former ) ] +// // pub enum SimpleEnum +// // { +// // /// Unit variant. +// // Unit, +// // /// Tuple variant with a single value. +// // #[ scalar ] // Use scalar for direct constructor +// // Value( i32 ), +// // } +// // +// // /// A struct containing a vector of the enum. +// // #[ derive( Debug, PartialEq, Default, Former ) ] +// // pub struct StructWithEnumVec +// // { +// // /// Field attempting to use subform_entry on Vec. +// // #[ subform_entry ] +// // items : Vec< SimpleEnum >, +// // } +// // +// // /// Test attempting to use the subformer generated for `items`. +// // /// This test FAIL TO COMPILE because `former` does not +// // /// currently support generating the necessary subformer logic for enum entries +// // /// within a collection via `#[subform_entry]`. +// // #[ test ] +// // fn attempt_subform_enum_vec() +// // { +// // // This code block demonstrates the intended usage that fails. +// // /* +// // let _result = StructWithEnumVec::former() +// // // Trying to access the subformer for the Vec field. +// // // The derive macro does not generate the `.items()` method correctly +// // // for Vec with #[subform_entry]. It doesn't know how to +// // // return a former that can then construct *specific enum variants*. +// // .items() +// // // Attempting to call a variant constructor method (e.g., .value()) +// // // on the hypothetical subformer returned by .items(). This method +// // // would not be generated. +// // .value( 10 ) +// // // Ending the hypothetical subformer for the first enum entry. +// // .end() +// // // Attempting to start another entry. +// // .items() +// // // Attempting to call the unit variant constructor method. +// // .unit() +// // // Ending the hypothetical subformer for the second enum entry. +// // .end() +// // // Finalizing the parent struct. +// // .form(); +// // */ +// // +// // // Assertion to make the test function valid, though it won't be reached +// // // if the compilation fails as expected. +// // assert!( true, "Test executed - compilation should have failed before this point." ); +// // } +// // // qqq : xxx : make it working diff --git a/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_default_error.rs b/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_default_error.rs index 2ea8bfe857..dca5bbc1fc 100644 --- a/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_default_error.rs +++ b/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_default_error.rs @@ -1,3 +1,15 @@ +//! Purpose: This is a compile-fail test designed to verify that a zero-field named (struct-like) +//! variant without the `#[scalar]` attribute results in a compilation error. +//! +//! Coverage: +//! - Rule 3c (Struct + Zero-Field + Default -> Error): Verifies that the macro correctly reports an error when `#[scalar]` is missing for a zero-field named variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `EnumWithNamedFields` with a zero-field named variant `VariantZeroDefault {}`. +//! - Applies `#[derive(Former)]` to the enum. +//! - No `#[scalar]` attribute is applied to `VariantZeroDefault`, which is an invalid state according to Rule 3c. +//! - This file is intended for use with `trybuild`. The test is accepted if `trybuild` confirms that this code fails to compile with an appropriate error message, thereby validating the macro's error handling for this specific invalid scenario. + #[ derive( Debug, PartialEq, former::Former ) ] pub enum EnumWithNamedFields { diff --git a/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_subform_scalar_error.rs b/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_subform_scalar_error.rs index 736dde6182..cc62f6a324 100644 --- a/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_subform_scalar_error.rs +++ b/module/core/former/tests/inc/enum_named_tests/compile_fail/struct_zero_subform_scalar_error.rs @@ -1,3 +1,15 @@ +//! Purpose: This is a compile-fail test designed to verify that applying the `#[subform_scalar]` attribute +//! to a zero-field named (struct-like) variant results in a compilation error. +//! +//! Coverage: +//! - Rule 2c (Struct + Zero-Field + `#[subform_scalar]` -> Error): Verifies that the macro correctly reports an error for this invalid attribute usage. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `EnumWithNamedFields` with a zero-field named variant `VariantZeroSubformScalar {}`. +//! - Applies `#[derive(Former)]` to the enum. +//! - Applies `#[subform_scalar]` to the `VariantZeroSubformScalar` variant, which is an invalid combination according to Rule 2c. +//! - This file is intended for use with `trybuild`. The test is accepted if `trybuild` confirms that this code fails to compile with an appropriate error message, thereby validating the macro's error handling for this specific invalid scenario. + #[ derive( Debug, PartialEq, former::Former ) ] pub enum EnumWithNamedFields { diff --git a/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_derive.rs b/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_derive.rs index dd5db320a3..b8e2893099 100644 --- a/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_derive.rs +++ b/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_derive.rs @@ -1,3 +1,27 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of constructors for named (struct-like) +//! variants with varying field counts and attributes (`#[scalar]`, `#[subform_scalar]`). This file +//! focuses on verifying the derive-based implementation, including static methods and standalone +//! constructors (when enabled on the enum). +//! +//! Coverage: +//! - Rule 1c (Struct + Zero-Field + `#[scalar]`): Verifies `Enum::variant() -> Enum` for a zero-field named variant with `#[scalar]`. +//! - Rule 3c (Struct + Zero-Field + Default): Implicitly covered as this is an error case verified by compile-fail tests. +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Verifies `Enum::variant { field: InnerType } -> Enum` for a single-field named variant with `#[scalar]`. +//! - Rule 2e (Struct + Single-Field + `#[subform_scalar]`): Verifies `Enum::variant() -> VariantFormer<...>` for a single-field named variant with `#[subform_scalar]`. +//! - Rule 3e (Struct + Single-Field + Default): Verifies `Enum::variant() -> VariantFormer<...>` for a single-field named variant without specific attributes. +//! - Rule 1g (Struct + Multi-Field + `#[scalar]`): Verifies `Enum::variant { f1: T1, f2: T2, ... } -> Enum` for a multi-field named variant with `#[scalar]`. +//! - Rule 3g (Struct + Multi-Field + Default): Verifies `Enum::variant() -> VariantFormer<...>` for a multi-field named variant without specific attributes. +//! - Rule 4a (#[standalone_constructors]): Verifies the generation of top-level constructor functions for named variants. +//! - Rule 4b (Option 2 Logic): Relevant to the return types of standalone constructors based on field attributes. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `EnumWithNamedFields` with named variants covering zero, one, and two fields. +//! - Applies `#[derive(Former)]`, `#[debug]`, and `#[standalone_constructors]` to the enum. +//! - Applies `#[scalar]` and `#[subform_scalar]` to relevant variants. +//! - Includes shared test logic from `enum_named_fields_named_only_test.rs`. +//! - The included tests call the derived static methods (e.g., `EnumWithNamedFields::variant_zero_scalar()`, `EnumWithNamedFields::variant_one_scalar()`, `EnumWithNamedFields::variant_one_subform()`, etc.) and standalone constructors (e.g., `standalone_variant_zero_scalar()`). +//! - Asserts that the returned values match the expected enum instances or former types, verifying the constructor generation and behavior for named variants with different attributes and field counts. + // File: module/core/former/tests/inc/former_enum_tests/named_tests/enum_named_fields_named_derive.rs use super::*; diff --git a/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_manual.rs b/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_manual.rs index 1f63ff7238..a6ab23628d 100644 --- a/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_manual.rs +++ b/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_manual.rs @@ -1,3 +1,25 @@ +//! Purpose: Provides a hand-written implementation of the `Former` pattern's constructors for named +//! (struct-like) variants with varying field counts and attributes (`#[scalar]`, `#[subform_scalar]`), +//! demonstrating the manual implementation corresponding to the derived behavior. This includes manual +//! implementations for static methods and standalone constructors. +//! +//! Coverage: +//! - Rule 1c (Struct + Zero-Field + `#[scalar]`): Manually implements the static method `EnumWithNamedFields::variant_zero_scalar()`. +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Manually implements the static method `EnumWithNamedFields::variant_one_scalar()`. +//! - Rule 2e (Struct + Single-Field + `#[subform_scalar]`): Manually implements the static method `EnumWithNamedFields::variant_one_subform()` which returns a former for the inner type. +//! - Rule 3e (Struct + Single-Field + Default): Manually implements the static method `EnumWithNamedFields::variant_one_default()` which returns a former for the inner type. +//! - Rule 1g (Struct + Multi-Field + `#[scalar]`): Manually implements the static method `EnumWithNamedFields::variant_two_scalar()`. +//! - Rule 3g (Struct + Multi-Field + Default): Manually implements the static method `EnumWithNamedFields::variant_two_default()` which returns a former for the variant. (Note: This variant is commented out in the enum definition in this file). +//! - Rule 4a (#[standalone_constructors]): Manually implements standalone constructor functions (e.g., `standalone_variant_zero_scalar()`, `standalone_variant_one_default()`, etc.) corresponding to the tests in `_only_test.rs`. +//! - Rule 4b (Option 2 Logic): Demonstrated by the manual implementations of standalone constructors, showing how their return type depends on field attributes. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `EnumWithNamedFields` with named variants covering zero, one, and two fields. +//! - Provides hand-written implementations of static methods and standalone constructors that mimic the behavior expected from the `#[derive(Former)]` macro for named variants with different attributes and field counts. +//! - Includes necessary manual former components (Storage, DefinitionTypes, Definition, Former, End) for subform and standalone former builder scenarios. +//! - Includes shared test logic from `enum_named_fields_named_only_test.rs`. +//! - The included tests call these manually implemented methods/functions and assert that the returned values match the expected enum instances or former types, verifying the manual implementation. + // File: module/core/former/tests/inc/former_enum_tests/named_tests/enum_named_fields_named_manual.rs use super::*; use former:: diff --git a/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_only_test.rs b/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_only_test.rs index cb35428f8a..849dd8dd43 100644 --- a/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_only_test.rs +++ b/module/core/former/tests/inc/enum_named_tests/enum_named_fields_named_only_test.rs @@ -1,3 +1,25 @@ +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of constructors for named (struct-like) variants with varying field counts and attributes +//! (`#[scalar]`, `#[subform_scalar]`), including static methods and standalone constructors. +//! +//! Coverage: +//! - Rule 1c (Struct + Zero-Field + `#[scalar]`): Tests the static method `variant_zero_scalar()`. +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Tests the static method `variant_one_scalar()`. +//! - Rule 2e (Struct + Single-Field + `#[subform_scalar]`): Tests the static method `variant_one_subform()` which returns a former for the inner type. +//! - Rule 3e (Struct + Single-Field + Default): Tests the static method `variant_one_default()` which returns a former for the inner type. +//! - Rule 1g (Struct + Multi-Field + `#[scalar]`): Tests the static method `variant_two_scalar()`. +//! - Rule 3g (Struct + Multi-Field + Default): Tests the static method `variant_two_default()` which returns a former for the variant. (Note: This variant is commented out in the enum definition in the manual file). +//! - Rule 4a (#[standalone_constructors]): Tests the existence and functionality of standalone constructor functions (e.g., `standalone_variant_zero_scalar()`, `standalone_variant_one_default()`, etc.). +//! - Rule 4b (Option 2 Logic): Tests the return types and usage of standalone constructors based on field attributes and whether they return scalars or formers. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `EnumWithNamedFields` enum structure with named variants covering zero, one, and two fields. +//! - Defines the `InnerForSubform` struct used in some variants. +//! - Contains test functions that are included by the derive and manual test files. +//! - Calls the static methods (e.g., `EnumWithNamedFields::variant_zero_scalar()`, `EnumWithNamedFields::variant_one_scalar()`) and standalone constructors (e.g., `standalone_variant_zero_scalar()`) provided by the including file. +//! - Uses setters and `.form()` where former builders are expected. +//! - Asserts that the returned values match the expected enum instances or former types, verifying that both derived and manual implementations correctly provide constructors for named variants with different attributes and field counts. + // File: module/core/former/tests/inc/former_enum_tests/named_tests/enum_named_fields_named_only_test.rs use super::*; // Imports EnumWithNamedFields and InnerForSubform @@ -6,6 +28,7 @@ use super::*; // Imports EnumWithNamedFields and InnerForSubform #[ test ] fn variant_zero_scalar_test() { + // Test Matrix Row: T24.1 (Implicitly, as this tests the behavior expected by the matrix) // Expect a direct static constructor taking no arguments. let got = EnumWithNamedFields::variant_zero_scalar(); let expected = EnumWithNamedFields::VariantZeroScalar {}; @@ -15,6 +38,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_zero_scalar_test() // New Test for S0.4 // { +// // Test Matrix Row: T24.2 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor taking no arguments. // let got = standalone_variant_zero_scalar(); // let expected = EnumWithNamedFields::VariantZeroScalar {}; @@ -26,6 +50,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn variant_one_scalar_test() // { +// // Test Matrix Row: T24.3 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a direct static constructor taking one argument. // let got = EnumWithNamedFields::variant_one_scalar( "value_a".to_string() ); // let expected = EnumWithNamedFields::VariantOneScalar { field_a : "value_a".to_string() }; @@ -35,6 +60,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn variant_one_subform_test() // { +// // Test Matrix Row: T24.4 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a static method returning a subformer for InnerForSubform. // let got = EnumWithNamedFields::variant_one_subform() // .value( 101 ) // Use InnerForSubformFormer's setter @@ -46,6 +72,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn variant_one_default_test() // { +// // Test Matrix Row: T24.5 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a static method returning a subformer for InnerForSubform (default behavior). // let got = EnumWithNamedFields::variant_one_default() // .value( 102 ) // Use InnerForSubformFormer's setter @@ -59,6 +86,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_one_default_test() // Test for S1.4 // { +// // Test Matrix Row: T24.6 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor returning a subformer. // // Note: Manual implementation uses a placeholder End struct. // let got = standalone_variant_one_default() @@ -71,6 +99,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_one_scalar_test() // Test for S1.5 // { +// // Test Matrix Row: T24.7 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor taking one argument. // let got = standalone_variant_one_scalar( "value_b".to_string() ); // let expected = EnumWithNamedFields::VariantOneScalar { field_a : "value_b".to_string() }; @@ -80,6 +109,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_one_subform_test() // Test for S1.6 // { +// // Test Matrix Row: T24.8 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor returning a subformer. // // Note: Manual implementation uses a placeholder End struct. // let got = standalone_variant_one_subform() @@ -92,6 +122,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_one_default_with_arg_test() // Test for S1.7 // { +// // Test Matrix Row: T24.9 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor taking the marked argument. // // Note: Manual implementation might differ slightly from macro output depending on arg_for_constructor logic. // let got = standalone_variant_one_default_with_arg( InnerForSubform { value: 105 } ); @@ -105,6 +136,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn variant_two_scalar_test() // { +// // Test Matrix Row: T24.10 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a direct static constructor taking multiple arguments. // let got = EnumWithNamedFields::variant_two_scalar( 42, true ); // let expected = EnumWithNamedFields::VariantTwoScalar { field_d : 42, field_e : true }; @@ -119,6 +151,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_two_default_test() // Test for SN.4 // { +// // Test Matrix Row: T24.11 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor returning a subformer. // // Note: Manual implementation uses a placeholder End struct. // let got = standalone_variant_two_default() @@ -133,6 +166,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_two_scalar_test() // Test for SN.5 // { +// // Test Matrix Row: T24.12 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor taking multiple arguments. // let got = standalone_variant_two_scalar( 43, false ); // let expected = EnumWithNamedFields::VariantTwoScalar { field_d : 43, field_e : false }; @@ -142,6 +176,7 @@ fn variant_zero_scalar_test() // #[ test ] // fn standalone_variant_two_subform_test() // Test for SN.6 // { +// // Test Matrix Row: T24.13 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor returning a subformer. // // Note: Manual implementation uses a placeholder End struct. // let got = standalone_variant_two_subform() @@ -154,8 +189,9 @@ fn variant_zero_scalar_test() // } // #[ test ] -// fn standalone_variant_two_default_with_args_test() // Test for SN.7 +// fn standalone_variant_two_default_with_arg_test() // Test for SN.7 // { +// // Test Matrix Row: T24.14 (Implicitly, as this tests the behavior expected by the matrix) // // Expect a standalone constructor taking marked arguments. // // Note: Manual implementation uses a direct constructor with all fields as args. // let got = standalone_variant_two_default_with_args( 44, true ); diff --git a/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_derive.rs b/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_derive.rs index 727e793038..bf6ee14078 100644 --- a/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_derive.rs +++ b/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_derive.rs @@ -1,3 +1,22 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of a former builder for a named +//! (struct-like) variant (`V1`) within a generic enum (`EnumG6`), where the variant contains +//! a field with an independent concrete generic type (`InnerG6`). This file focuses on +//! verifying the derive-based implementation's handling of independent generics and the generation +//! of appropriate setters in the implicit former. +//! +//! Coverage: +//! - Rule 3g (Struct + Multi-Field + Default): Verifies that for a named variant without specific attributes, the derived constructor is a former builder (`v_1()` returns a former). +//! - Rule 4b (Option 2 Logic): Demonstrates the usage of the former builder's setters (`.inner()`, `.flag()`) and `.form()` method, verifying the subformer mechanism in the context of independent generics. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumG6` with a named variant `V1 { inner: InnerG6, flag: bool, _phantom_t: PhantomData }`. +//! - Defines the inner struct `InnerG6` which also derives `Former`. +//! - Defines dummy bounds (`BoundA`, `BoundB`) and concrete types (`TypeForT`, `TypeForU`) in the included test file. +//! - Applies `#[derive(Former)]` to both `EnumG6` and `InnerG6`. +//! - Includes shared test logic from `generics_independent_struct_only_test.rs`. +//! - The included tests call the derived static method `EnumG6::::v_1()`, use the returned former's setters (`.inner()`, `.flag()`), and call `.form()`. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the derived former builder correctly handles fields with independent concrete generic types and non-generic fields within a generic enum. + // File: module/core/former/tests/inc/former_enum_tests/generics_independent_struct_derive.rs //! # Derive Test: Independent Generics in Struct Variants diff --git a/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_manual.rs b/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_manual.rs index 4da11ee62f..598028182f 100644 --- a/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_manual.rs +++ b/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_manual.rs @@ -1,3 +1,23 @@ +//! Purpose: Provides a hand-written implementation of the `Former` pattern's former builder for a +//! named (struct-like) variant (`V1`) within a generic enum (`EnumG6`), where the variant +//! contains a field with an independent concrete generic type (`InnerG6`). This file +//! demonstrates the manual implementation corresponding to the derived behavior, showing how to +//! manually create the implicit former infrastructure and the static method. +//! +//! Coverage: +//! - Rule 3g (Struct + Multi-Field + Default): Manually implements the static method `v_1()` which returns a former builder for the variant. +//! - Rule 4b (Option 2 Logic): Manually implements the implicit former's components (Storage, DefinitionTypes, Definition, Former, End) and the `FormingEnd` trait, demonstrating the subformer mechanism in the context of independent generics. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumG6` with a named variant `V1 { inner: InnerG6, flag: bool, _phantom_t: PhantomData }`. +//! - Defines the inner struct `InnerG6` which also derives `Former`. +//! - Defines dummy bounds (`BoundA`, `BoundB`) and concrete types (`TypeForT`, `TypeForU`) in the included test file. +//! - Provides hand-written implementations for the implicit former's components (`EnumG6V1FormerStorage`, `EnumG6V1FormerDefinitionTypes`, etc.) and the `FormingEnd` trait for `EnumG6V1End`. +//! - Implements the static method `EnumG6::::v_1()` which returns the manual former builder. +//! - Includes shared test logic from `generics_independent_struct_only_test.rs`. +//! - The included tests call the manually implemented static method `EnumG6::::v_1()`, use the returned former's setters (`.inner()`, `.flag()`), and call `.form()`. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the manual implementation correctly provides a former builder that handles fields with independent concrete generic types and non-generic fields within a generic enum. + // File: module/core/former/tests/inc/former_enum_tests/generics_independent_struct_manual.rs //! # Manual Test: Independent Generics in Struct Variants @@ -53,7 +73,6 @@ pub enum EnumG6< T : BoundA > // BoundA required by the enum } // --- Manual IMPLICIT Former Implementation for Variant V1 --- - // Storage for V1's fields #[ derive( Debug, Default ) ] pub struct EnumG6V1FormerStorage< T : BoundA > // Needs enum's bound diff --git a/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_only_test.rs b/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_only_test.rs index 5684c7b0ce..78c9a9d7f5 100644 --- a/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_only_test.rs +++ b/module/core/former/tests/inc/enum_named_tests/generics_independent_struct_only_test.rs @@ -1,3 +1,22 @@ +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of a former builder for a named (struct-like) variant (`V1`) within a generic enum (`EnumG6`), +//! where the variant contains a field with an independent concrete generic type (`InnerG6`). +//! It tests that the constructors generated/implemented for this scenario behave as expected (returning +//! former builders for nested building), correctly handling independent generics. +//! +//! Coverage: +//! - Rule 3g (Struct + Multi-Field + Default): Tests that the constructor for a named variant without specific attributes is a former builder (`v_1()` returns a former). +//! - Rule 4b (Option 2 Logic): Tests the usage of the former builder's setters (`.inner()`, `.flag()`) and `.form()` method, verifying the subformer mechanism in the context of independent generics. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines dummy bounds (`BoundA`, `BoundB`) and concrete types (`TypeForT`, `TypeForU`) satisfying them. +//! - Defines the inner struct `InnerG6` which also derives `Former`. +//! - Defines the `EnumG6` enum structure with the named variant `V1 { inner: InnerG6, flag: bool, _phantom_t: PhantomData }`. +//! - Contains test functions (`independent_generics_struct_variant`, `default_construction_independent_struct_variant`) that are included by the derive and manual test files. +//! - The `independent_generics_struct_variant` test calls the static method `EnumG6::::v_1()`, uses the returned former's setters (`.inner()`, `.flag()`), and calls `.form()`. +//! - The `default_construction_independent_struct_variant` test omits the `.inner()` setter call to verify default value handling for the inner field. +//! - Both tests assert that the resulting enum instances match manually constructed expected values. This verifies that both derived and manual implementations correctly provide former builders that handle fields with independent concrete generic types and non-generic fields within a generic enum. + // File: module/core/former/tests/inc/former_enum_tests/generics_independent_struct_only_test.rs /// # Test Logic: Independent Generics in Struct Variants @@ -12,7 +31,7 @@ /// ## Purpose: /// /// - **Verify Generic Propagation:** Ensure the enum's generics (`T`) and bounds (`BoundA`) are correctly -/// applied to the generated implicit former, storage, definitions, and end struct for the variant. +/// applied to the generated implicit former, storage, definitions, former struct, and end struct for the variant. /// - **Verify Concrete Inner Type Handling:** Ensure the implicit former correctly handles fields /// with concrete types (like `InnerG6`) within the generic enum context. /// - **Verify Setter Functionality:** Confirm that setters generated for the implicit former work correctly @@ -50,6 +69,7 @@ pub struct InnerG6< U : BoundB > // BoundB required by the inner struct #[ test ] fn independent_generics_struct_variant() { + // Test Matrix Row: T25.1 (Implicitly, as this tests the behavior expected by the matrix) //! Tests the construction of a struct variant (`V1`) where the inner field (`inner`) //! uses a concrete type (`InnerG6`) independent of the enum's generic (`T`). //! It verifies that the implicit former's setters for both the concrete inner field @@ -75,6 +95,7 @@ fn independent_generics_struct_variant() #[ test ] fn default_construction_independent_struct_variant() { + // Test Matrix Row: T25.2 (Implicitly, as this tests the behavior expected by the matrix) //! Tests the construction of a struct variant (`V1`) relying on the `Default` //! implementation for the inner field (`inner`) which has a concrete type (`InnerG6`). //! It verifies that the implicit former correctly uses the default value when the setter is not called. diff --git a/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_derive.rs b/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_derive.rs index 53364df5b4..69af7ac3c9 100644 --- a/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_derive.rs +++ b/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_derive.rs @@ -1,3 +1,22 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of a former builder for a named +//! (struct-like) variant (`V1`) within a generic enum (`EnumG4`), where the variant contains +//! a field with a shared generic type (`InnerG4`). This file focuses on verifying the +//! derive-based implementation's handling of shared generics and the generation of appropriate +//! setters in the implicit former. +//! +//! Coverage: +//! - Rule 3g (Struct + Multi-Field + Default): Verifies that for a named variant without specific attributes, the derived constructor is a former builder (`v_1()` returns a former). +//! - Rule 4b (Option 2 Logic): Demonstrates the usage of the former builder's setters (`.inner()`, `.flag()`) and `.form()` method, verifying the subformer mechanism in the context of shared generics. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumG4` with a named variant `V1 { inner: InnerG4, flag: bool }`. +//! - Defines the inner struct `InnerG4` which also derives `Former`. +//! - Defines dummy bounds (`BoundA`, `BoundB`) and a concrete type (`MyType`) in the included test file. +//! - Applies `#[derive(Former)]` to both `EnumG4` and `InnerG4`. +//! - Includes shared test logic from `generics_shared_struct_only_test.rs`. +//! - The included tests call the derived static method `EnumG4::::v_1()`, use the returned former's setters (`.inner()`, `.flag()`), and call `.form()`. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the derived former builder correctly handles fields with shared generic types and non-generic fields within a generic enum. + // File: module/core/former/tests/inc/former_enum_tests/generics_shared_struct_derive.rs //! # Derive Test: Shared Generics in Struct Variants diff --git a/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_manual.rs b/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_manual.rs index 16540fcca0..2422eed3db 100644 --- a/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_manual.rs +++ b/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_manual.rs @@ -1,3 +1,23 @@ +//! Purpose: Provides a hand-written implementation of the `Former` pattern's former builder for a +//! named (struct-like) variant (`V1`) within a generic enum (`EnumG4`), where the variant +//! contains a field with a shared generic type (`InnerG4`). This file demonstrates the manual +//! implementation corresponding to the derived behavior, showing how to manually create the implicit +//! former infrastructure and the static method, correctly handling the shared generic parameter. +//! +//! Coverage: +//! - Rule 3g (Struct + Multi-Field + Default): Manually implements the static method `v_1()` which returns a former builder for the variant. +//! - Rule 4b (Option 2 Logic): Manually implements the implicit former's components (Storage, DefinitionTypes, Definition, Former, End) and the `FormingEnd` trait, demonstrating the subformer mechanism in the context of shared generics. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumG4` with a named variant `V1 { inner: InnerG4, flag: bool }`. +//! - Defines the inner struct `InnerG4` which also implements `Default`. +//! - Defines dummy bounds (`BoundA`, `BoundB`) and a concrete type (`MyType`) in the included test file. +//! - Provides hand-written implementations for the implicit former's components (`EnumG4V1FormerStorage`, `EnumG4V1FormerDefinitionTypes`, etc.) and the `FormingEnd` trait for `EnumG4V1End`, ensuring correct handling of the shared generic `T` and its bounds. +//! - Implements the static method `EnumG4::::v_1()` which returns the manual former builder. +//! - Includes shared test logic from `generics_shared_struct_only_test.rs`. +//! - The included tests call the manually implemented static method `EnumG4::::v_1()`, use the returned former's setters (`.inner()`, `.flag()`), and call `.form()`. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the manual implementation correctly provides a former builder that handles fields with shared generic types and non-generic fields within a generic enum. + // File: module/core/former/tests/inc/former_enum_tests/generics_shared_struct_manual.rs use super::*; // Imports testing infrastructure and potentially other common items use std::marker::PhantomData; diff --git a/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_only_test.rs b/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_only_test.rs index c1be7df8cc..a5b529a344 100644 --- a/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_only_test.rs +++ b/module/core/former/tests/inc/enum_named_tests/generics_shared_struct_only_test.rs @@ -1,3 +1,22 @@ +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of a former builder for a named (struct-like) variant (`V1`) within a generic enum (`EnumG4`), +//! where the variant contains a field with a shared generic type (`InnerG4`). It tests that the +//! constructors generated/implemented for this scenario behave as expected (returning former builders +//! for nested building), correctly handling shared generics. +//! +//! Coverage: +//! - Rule 3g (Struct + Multi-Field + Default): Tests that the constructor for a named variant without specific attributes is a former builder (`v_1()` returns a former). +//! - Rule 4b (Option 2 Logic): Tests the usage of the former builder's setters (`.inner()`, `.flag()`) and `.form()` method, verifying the subformer mechanism in the context of shared generics. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines dummy bounds (`BoundA`, `BoundB`) and a concrete type (`MyType`) satisfying them. +//! - Defines the inner struct `InnerG4` which also derives `Former`. +//! - Defines the `EnumG4` enum structure with the named variant `V1 { inner: InnerG4, flag: bool }`. +//! - Contains test functions (`shared_generics_struct_variant`, `default_construction_shared_struct_variant`) that are included by the derive and manual test files. +//! - The `shared_generics_struct_variant` test calls the static method `EnumG4::::v_1()`, uses the returned former's setters (`.inner()`, `.flag()`), and calls `.form()`. +//! - The `default_construction_shared_struct_variant` test omits the `.inner()` setter call to verify default value handling for the inner field. +//! - Both tests assert that the resulting enum instances match manually constructed expected values. This verifies that both derived and manual implementations correctly provide former builders that handle fields with shared generic types and non-generic fields within a generic enum. + // File: module/core/former/tests/inc/former_enum_tests/generics_shared_struct_only_test.rs use super::*; // Imports items from the parent file (either manual or derive) @@ -14,6 +33,7 @@ impl BoundB for MyType {} #[ test ] fn shared_generics_struct_variant() { + // Test Matrix Row: T26.1 (Implicitly, as this tests the behavior expected by the matrix) //! Tests the construction of a struct variant (`V1`) where the inner field (`inner`) //! uses a generic type (`InnerG4`) that shares the enum's generic parameter (`T`). //! It verifies that the implicit former's setters for both the generic inner field @@ -36,6 +56,7 @@ fn shared_generics_struct_variant() #[ test ] fn default_construction_shared_struct_variant() { + // Test Matrix Row: T26.2 (Implicitly, as this tests the behavior expected by the matrix) //! Tests the construction of a struct variant (`V1`) relying on the `Default` //! implementation for the inner field (`inner`) which has a generic type (`InnerG4`). //! It verifies that the implicit former correctly uses the default value when the setter is not called. diff --git a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_derive.rs b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_derive.rs index 76185e595c..37084a4ca0 100644 --- a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_derive.rs +++ b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_derive.rs @@ -1,3 +1,23 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of standalone scalar constructor functions +//! for named (struct-like) variants when the enum has the `#[standalone_constructors]` attribute and +//! fields within the variants have the `#[arg_for_constructor]` attribute. This file focuses on +//! verifying the derive-based implementation for both single-field and multi-field named variants. +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Verifies the generation of top-level constructor functions (`struct_variant_args`, `multi_struct_args`). +//! - Rule 4b (Option 2 Logic): Verifies that when all fields in a named variant have `#[arg_for_constructor]`, the standalone constructor takes arguments for those fields and returns the final enum instance (scalar style). +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Implicitly relevant as `StructVariantArgs` is a single-field named variant. +//! - Rule 3e (Struct + Single-Field + Default): Implicitly relevant as `StructVariantArgs` is a single-field named variant. +//! - Rule 1g (Struct + Multi-Field + `#[scalar]`): Implicitly relevant as `MultiStructArgs` is a multi-field named variant. +//! - Rule 3g (Struct + Multi-Field + Default): Implicitly relevant as `MultiStructArgs` is a multi-field named variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnumArgs` with single-field (`StructVariantArgs { field: String }`) and multi-field (`MultiStructArgs { a: i32, b: bool }`) named variants. +//! - Applies `#[derive(Former)]`, `#[standalone_constructors]`, and `#[debug]` to the enum. +//! - Applies `#[arg_for_constructor]` to the fields within both variants. +//! - Includes shared test logic from `standalone_constructor_args_named_only_test.rs`. +//! - The included tests call the derived standalone constructor functions (`struct_variant_args(value)`, `multi_struct_args(value1, value2)`) and assert that the returned enum instances match manually constructed expected values. This verifies that the standalone constructors are generated correctly as scalar functions when all fields have `#[arg_for_constructor]`. + // File: module/core/former/tests/inc/former_enum_tests/named_tests/standalone_constructor_args_named_derive.rs #[ allow( unused_imports ) ] diff --git a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_multi_manual.rs b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_multi_manual.rs index 4c540ddd01..e3ac7d7da9 100644 --- a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_multi_manual.rs +++ b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_multi_manual.rs @@ -1,3 +1,20 @@ +//! Purpose: Provides a hand-written implementation of the standalone scalar constructor function +//! for a multi-field named (struct-like) variant (`MultiStructArgs { a: i32, b: bool }`) within +//! an enum, demonstrating the manual implementation corresponding to the derived behavior when the +//! enum has `#[standalone_constructors]` and all fields have `#[arg_for_constructor]`. +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Manually implements the top-level constructor function (`multi_struct_args`). +//! - Rule 4b (Option 2 Logic): Manually implements the logic for a scalar standalone constructor that takes arguments for all fields in a multi-field named variant. +//! - Rule 1g (Struct + Multi-Field + `#[scalar]`): Implicitly relevant as `MultiStructArgs` is a multi-field named variant. +//! - Rule 3g (Struct + Multi-Field + Default): Implicitly relevant as `MultiStructArgs` is a multi-field named variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnumArgs` enum with the multi-field named variant `MultiStructArgs { a: i32, b: bool }`. +//! - Provides a hand-written `multi_struct_args` function that takes `i32` and `bool` as arguments and returns `TestEnumArgs::MultiStructArgs { a: i32, b: bool }`. This mimics the behavior expected when `#[standalone_constructors]` is on the enum and `#[arg_for_constructor]` is on all fields of the variant. +//! - Includes shared test logic from `standalone_constructor_args_named_only_test.rs`. +//! - The included test calls this manually implemented standalone constructor and asserts that the returned enum instance matches a manually constructed `TestEnumArgs::MultiStructArgs { a: value1, b: value2 }`. This verifies the manual implementation of the scalar standalone constructor with field arguments. + // File: module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_multi_manual.rs #[ allow( unused_imports ) ] diff --git a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_only_test.rs b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_only_test.rs index 1b0fbbb0b5..2b5c25f161 100644 --- a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_only_test.rs +++ b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_only_test.rs @@ -1,3 +1,23 @@ +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of standalone scalar constructors for named (struct-like) variants with `#[arg_for_constructor]` +//! fields. It tests that standalone constructors generated/implemented when the enum has +//! `#[standalone_constructors]` and all variant fields have `#[arg_for_constructor]` behave as +//! expected (scalar style, taking field arguments). +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Tests the existence and functionality of top-level constructor functions (`struct_variant_args`, `multi_struct_args`). +//! - Rule 4b (Option 2 Logic): Tests that these standalone constructors take arguments corresponding to the `#[arg_for_constructor]` fields and return the final enum instance. +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Implicitly tested via `StructVariantArgs`. +//! - Rule 3e (Struct + Single-Field + Default): Implicitly tested via `StructVariantArgs`. +//! - Rule 1g (Struct + Multi-Field + `#[scalar]`): Implicitly tested via `MultiStructArgs`. +//! - Rule 3g (Struct + Multi-Field + Default): Implicitly tested via `MultiStructArgs`. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnumArgs` enum structure with single-field (`StructVariantArgs { field: String }`) and multi-field (`MultiStructArgs { a: i32, b: bool }`) named variants. +//! - Contains test functions (`struct_variant_args_test`, `multi_struct_variant_args_test`) that are included by the derive and manual test files. +//! - Calls the standalone constructor functions (`struct_variant_args(value)`, `multi_struct_args(value1, value2)`) provided by the including file. +//! - Asserts that the returned enum instances match manually constructed expected values (`TestEnumArgs::StructVariantArgs { field: value }`, `TestEnumArgs::MultiStructArgs { a: value1, b: value2 }`). This verifies that both derived and manual standalone constructors correctly handle field arguments and produce the final enum variant. + // File: module/core/former/tests/inc/former_enum_tests/named_tests/standalone_constructor_args_named_only_test.rs // Use the items defined in the including file (manual or derive for args) @@ -7,6 +27,7 @@ use super::*; #[ test ] fn struct_variant_args_test() // New test name { + // Test Matrix Row: T27.1 (Implicitly, as this tests the behavior expected by the matrix) // Assumes `struct_variant_args` takes a String argument and returns Self (Option 2) let instance = struct_variant_args( "arg_value" ); // Call directly let expected = TestEnumArgs::StructVariantArgs { field : "arg_value".to_string() }; @@ -17,6 +38,7 @@ fn struct_variant_args_test() // New test name #[ test ] fn multi_struct_variant_args_test() { + // Test Matrix Row: T27.2 (Implicitly, as this tests the behavior expected by the matrix) // Assumes `multi_struct_args` takes i32 and bool arguments and returns Self (Option 2) let instance = multi_struct_args( -1, false ); // Call directly let expected = TestEnumArgs::MultiStructArgs { a : -1, b : false }; diff --git a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_single_manual.rs b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_single_manual.rs index c566115611..b112632cc3 100644 --- a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_single_manual.rs +++ b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_single_manual.rs @@ -1,3 +1,20 @@ +//! Purpose: Provides a hand-written implementation of the standalone scalar constructor function +//! for a single-field named (struct-like) variant (`StructVariantArgs { field: String }`) within +//! an enum, demonstrating the manual implementation corresponding to the derived behavior when the +//! enum has `#[standalone_constructors]` and the field has `#[arg_for_constructor]`. +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Manually implements the top-level constructor function (`struct_variant_args`). +//! - Rule 4b (Option 2 Logic): Manually implements the logic for a scalar standalone constructor that takes an argument for the single field in a named variant. +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Implicitly relevant as `StructVariantArgs` is a single-field named variant. +//! - Rule 3e (Struct + Single-Field + Default): Implicitly relevant as `StructVariantArgs` is a single-field named variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnumArgs` enum with the single-field named variant `StructVariantArgs { field: String }`. +//! - Provides a hand-written `struct_variant_args` function that takes `String` as an argument and returns `TestEnumArgs::StructVariantArgs { field: String }`. This mimics the behavior expected when `#[standalone_constructors]` is on the enum and `#[arg_for_constructor]` is on the field. +//! - Includes shared test logic from `standalone_constructor_args_named_only_test.rs`. +//! - The included test calls this manually implemented standalone constructor and asserts that the returned enum instance matches a manually constructed `TestEnumArgs::StructVariantArgs { field: value }`. This verifies the manual implementation of the scalar standalone constructor with a field argument. + // File: module/core/former/tests/inc/enum_named_tests/standalone_constructor_args_named_single_manual.rs #[ allow( unused_imports ) ] diff --git a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_derive.rs b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_derive.rs index d4f22463d7..88ffba4e97 100644 --- a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_derive.rs +++ b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_derive.rs @@ -1,3 +1,22 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of a standalone former builder +//! for a named (struct-like) variant when the enum has the `#[standalone_constructors]` attribute +//! and no fields within the variants have the `#[arg_for_constructor]` attribute. This file focuses +//! on verifying the derive-based implementation for a single-field named variant. +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Verifies the generation of the top-level constructor function (`struct_variant`). +//! - Rule 4b (Option 2 Logic): Verifies that when no fields in a named variant have `#[arg_for_constructor]`, the standalone constructor returns a former builder for the variant. +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Implicitly relevant as `StructVariant` is a single-field named variant. +//! - Rule 3e (Struct + Single-Field + Default): Implicitly relevant as `StructVariant` is a single-field named variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a single-field named variant `StructVariant { field: String }`. +//! - Applies `#[derive(Former)]` and `#[standalone_constructors]` to the enum. +//! - No `#[arg_for_constructor]` attributes are applied to fields. +//! - Includes shared test logic from `standalone_constructor_named_only_test.rs`. +//! - The included test calls the derived standalone constructor function `struct_variant()`, uses the returned former builder's setter (`.field()`), and calls `.form()`. +//! - Asserts that the resulting enum instance matches a manually constructed `TestEnum::StructVariant { field: value }`. This verifies that the standalone constructor is generated correctly as a former builder when no field arguments are specified. + // File: module/core/former/tests/inc/former_enum_tests/named_tests/standalone_constructor_named_derive.rs #[ allow( unused_imports ) ] diff --git a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_only_test.rs b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_only_test.rs index a6e8802fee..1198828c7f 100644 --- a/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_only_test.rs +++ b/module/core/former/tests/inc/enum_named_tests/standalone_constructor_named_only_test.rs @@ -1,3 +1,23 @@ +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of standalone former builders for named (struct-like) variants without `#[arg_for_constructor]` +//! fields. It tests that standalone constructors generated/implemented when the enum has +//! `#[standalone_constructors]` and no variant fields have `#[arg_for_constructor]` behave as +//! expected (former builder style, allowing field setting via setters). +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Tests the existence and functionality of the top-level constructor function (`struct_variant`). +//! - Rule 4b (Option 2 Logic): Tests that the standalone constructor returns a former builder for the variant and that its fields can be set using setters (`.field()`). +//! - Rule 1e (Struct + Single-Field + `#[scalar]`): Implicitly tested via `StructVariant`. +//! - Rule 3e (Struct + Single-Field + Default): Implicitly tested via `StructVariant`. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum structure with a single-field named variant `StructVariant { field: String }`. +//! - Contains a test function (`struct_variant_test`) that is included by the derive and manual test files. +//! - Calls the standalone constructor function `struct_variant()` provided by the including file. +//! - Uses the returned former builder's setter (`.field()`) to set the field. +//! - Calls `.form()` on the former builder to get the final enum instance. +//! - Asserts that the resulting enum instance matches a manually constructed `TestEnum::StructVariant { field: value }`. This verifies that both derived and manual standalone constructors correctly return former builders and allow setting fields via setters. + // File: module/core/former/tests/inc/former_enum_tests/named_tests/standalone_constructor_named_only_test.rs // Use the items defined in the including file (manual or derive) @@ -7,6 +27,7 @@ use super::*; #[ test ] fn struct_variant_test() // Use enum-specific test name { + // Test Matrix Row: T28.1 (Implicitly, as this tests the behavior expected by the matrix) // Call the constructor function (manual or derived) let former = struct_variant(); // <<< Call with zero args diff --git a/module/core/former/tests/inc/enum_unit_tests/compile_fail/mod.rs b/module/core/former/tests/inc/enum_unit_tests/compile_fail/mod.rs index a3ae813d39..5f4ea72f80 100644 --- a/module/core/former/tests/inc/enum_unit_tests/compile_fail/mod.rs +++ b/module/core/former/tests/inc/enum_unit_tests/compile_fail/mod.rs @@ -3,15 +3,12 @@ #[ cfg( feature = "derive_former" ) ] #[ test_tools::nightly ] #[ test ] -fn former_trybuild() +fn subform_scalar_on_unit_compile_fail() // Renamed for clarity { - - println!( "current_dir : {:?}", std::env::current_dir().unwrap() ); let t = test_tools::compiletime::TestCases::new(); - - // Compile-fail tests for tuple variants (Increment 9) - // Removed tuple variant compile-fail test references as they were moved - - // assert!( false ); - + t.compile_fail("tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.rs"); } + +// To keep other potential trybuild tests separate, you might add more functions +// or integrate into a single one if preferred by project structure. +// For now, focusing on the current increment's test. diff --git a/module/core/former/tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.rs b/module/core/former/tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.rs new file mode 100644 index 0000000000..35b147d8ff --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.rs @@ -0,0 +1,8 @@ +use former::Former; + +#[derive(Former)] +enum TestEnum { + #[subform_scalar] // This should cause a compile error + MyUnit, +} +fn main() {} \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.stderr b/module/core/former/tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.stderr new file mode 100644 index 0000000000..eab6ae456d --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.stderr @@ -0,0 +1,6 @@ +error: TEST ERROR: #[subform_scalar] cannot be used on unit variants. V3 + --> tests/inc/enum_unit_tests/compile_fail/subform_scalar_on_unit.rs:5:3 + | +5 | / #[subform_scalar] // This should cause a compile error +6 | | MyUnit, + | |________^ diff --git a/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_derive.rs b/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_derive.rs new file mode 100644 index 0000000000..57fc2c1294 --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_derive.rs @@ -0,0 +1,31 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of constructors for unit variants +//! within an enum that has generic parameters and bounds. This file focuses on verifying +//! the derive-based implementation. +//! +//! Coverage: +//! - Rule 3a (Unit + Default): Verifies `EnumOuter::::other_variant() -> EnumOuter` for a generic enum. +//! - Rule 1a (Unit + `#[scalar]`): Verifies `EnumOuter::::other_variant() -> EnumOuter` (as default for unit is scalar) for a generic enum. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumOuter` with a unit variant `OtherVariant`, and the `#[derive(Former)]` and `#[debug]` attributes. +//! - Relies on the derived static method `EnumOuter::::other_variant()`. +//! - Asserts that the `got` instance is equal to an `expected` instance, which is manually +//! constructed as `EnumOuter::::OtherVariant`. This confirms the constructor produces the correct variant instance for a generic enum. +// File: module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_derive.rs +use super::*; // Imports testing infrastructure and potentially other common items +use std::fmt::Debug; // Import Debug trait for bounds +// use std::marker::PhantomData; // No longer needed for this simple case + +// --- Enum Definition with Bounds --- +// Apply Former derive here. This is what we are testing. +#[derive(Debug, PartialEq, former::Former)] +#[debug] +pub enum EnumOuter< X : Copy + Debug + PartialEq > // Enum bound: Copy + Debug + PartialEq +{ + // --- Unit Variant --- + OtherVariant, + #[allow(dead_code)] // Re-added to use generic X + _Phantom(core::marker::PhantomData::), +} + +include!( "generic_enum_simple_unit_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_manual.rs b/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_manual.rs new file mode 100644 index 0000000000..b2b05be88b --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_manual.rs @@ -0,0 +1,38 @@ +//! Purpose: Provides a manual implementation of a constructor for a unit variant +//! within a generic enum with bounds, to serve as a reference for verifying +//! the `#[derive(Former)]` macro's behavior. +//! +//! Coverage: +//! - Rule 3a (Unit + Default): Manual implementation of static method `EnumOuter::other_variant()`. +//! - Rule 1a (Unit + `#[scalar]`): Manual implementation of static method (as default for unit is scalar). +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumOuter` with a unit variant `OtherVariant`. +//! - Manually implements a static method `EnumOuter::other_variant()` that mirrors the expected generated code for a scalar unit variant. +//! - This file is used as a reference for comparison in tests that include `generics_in_tuple_variant_only_test.rs` (though that file does not currently test unit variants). +// File: module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_manual.rs +use super::*; // Imports testing infrastructure and potentially other common items +use std::fmt::Debug; // Import Debug trait for bounds +// use std::marker::PhantomData; // No longer needed for this simple case + +// --- Enum Definition with Bounds --- +#[ derive( Debug, PartialEq ) ] +pub enum EnumOuter< X : Copy + Debug + PartialEq > +{ + // --- Unit Variant --- + OtherVariant, + #[allow(dead_code)] // Re-added to use generic X + _Phantom(core::marker::PhantomData::), +} + +// --- Manual constructor for OtherVariant --- +impl< X : Copy + Debug + PartialEq > EnumOuter< X > +{ + #[ allow( dead_code ) ] + pub fn other_variant() -> Self + { + EnumOuter::OtherVariant + } +} + +include!( "generic_enum_simple_unit_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_only_test.rs b/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_only_test.rs new file mode 100644 index 0000000000..cd13b1edfd --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/generic_enum_simple_unit_only_test.rs @@ -0,0 +1,23 @@ +// Purpose: Provides shared test assertions for verifying constructors of a unit variant +// within a simple generic enum. +// This file is included by `generic_enum_simple_unit_manual.rs` and `generic_enum_simple_unit_derive.rs`. + +use super::*; // Imports EnumOuter from the including file. +// use std::fmt::Debug; // Removed, should be imported by the including file. + +#[derive(Copy, Clone, Debug, PartialEq)] +struct MyType(i32); + +#[test] +fn generic_other_variant_test() +{ + // Test with a concrete type for the generic parameter. + let got = EnumOuter::::other_variant(); + let expected = EnumOuter::::OtherVariant; + assert_eq!(got, expected); + + // Test with another concrete type to be sure. + let got_u32 = EnumOuter::::other_variant(); + let expected_u32 = EnumOuter::::OtherVariant; + assert_eq!(got_u32, expected_u32); +} \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_derive.rs b/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_derive.rs new file mode 100644 index 0000000000..c87c853674 --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_derive.rs @@ -0,0 +1,18 @@ +//! Derive implementation for testing unit variants in generic enums. + +use super::*; +use former::Former; +// use former_types::{EntityToFormer, FormerDefinition}; // Not needed if Value(T) is scalar + +/// Generic enum with a unit variant, using Former. +#[derive(Debug, PartialEq, Former)] +#[former(standalone_constructors, debug)] +pub enum GenericOption // Minimal bounds for T +{ + #[scalar] // Treat Value(T) as a scalar constructor for the enum + #[allow(dead_code)] // This variant is not constructed by these specific unit tests + Value(T), + NoValue, // Unit variant +} + +include!("generic_unit_variant_only_test.rs"); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_manual.rs b/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_manual.rs new file mode 100644 index 0000000000..fffbd8fa5e --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_manual.rs @@ -0,0 +1,30 @@ +//! Manual implementation for testing unit variants in generic enums. + +use super::*; + +/// Generic enum with a unit variant. +#[derive(Debug, PartialEq)] +pub enum GenericOption +{ + #[allow(dead_code)] // This variant is not constructed by these specific unit tests + Value(T), + NoValue, // Renamed from UnitNone +} + +impl GenericOption +{ + #[inline(always)] + pub fn no_value() -> Self // Renamed from unit_none + { + Self::NoValue // Renamed from UnitNone + } +} + +// Standalone constructor +#[inline(always)] +pub fn no_value() -> GenericOption // Renamed from unit_none +{ + GenericOption::::NoValue // Renamed from UnitNone +} + +include!("generic_unit_variant_only_test.rs"); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_only_test.rs b/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_only_test.rs new file mode 100644 index 0000000000..b77c69c89b --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/generic_unit_variant_only_test.rs @@ -0,0 +1,19 @@ +/// Shared test logic for unit variants in generic enums. + +use super::*; + +#[test] +fn generic_static_constructor() +{ + // Test Matrix Row: T4.1 / T4.2 + assert_eq!(GenericOption::::no_value(), GenericOption::::NoValue); + assert_eq!(GenericOption::::no_value(), GenericOption::::NoValue); +} + +#[test] +fn generic_standalone_constructor() +{ + // Test Matrix Row: T4.2 + assert_eq!(no_value::(), GenericOption::::NoValue); + assert_eq!(no_value::(), GenericOption::::NoValue); +} \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/keyword_variant_derive.rs b/module/core/former/tests/inc/enum_unit_tests/keyword_variant_derive.rs new file mode 100644 index 0000000000..f9343256f9 --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/keyword_variant_derive.rs @@ -0,0 +1,12 @@ +use former::Former; // Ensure derive is in scope +use super::*; // Needed for the include + +#[derive(Debug, PartialEq, Former)] +#[former(standalone_constructors, debug)] +#[allow(non_camel_case_types)] // Explicitly allowing for testing keyword-like names +pub enum KeywordTest { + r#fn, + r#struct, +} + +include!("keyword_variant_only_test.rs"); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/keyword_variant_manual.rs b/module/core/former/tests/inc/enum_unit_tests/keyword_variant_manual.rs new file mode 100644 index 0000000000..afe3c63a51 --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/keyword_variant_manual.rs @@ -0,0 +1,43 @@ +//! Manual implementation for testing unit variants with keyword identifiers. + +use super::*; + +/// Enum with keyword identifiers for variants. +#[derive(Debug, PartialEq)] +#[allow(non_camel_case_types)] // Explicitly allowing for testing keyword-like names +pub enum KeywordTest +{ + r#fn, + r#struct, +} + +#[allow(dead_code)] // Functions are used by included _only_test.rs +impl KeywordTest +{ + #[inline(always)] + pub fn r#fn() -> Self + { + Self::r#fn + } + + #[inline(always)] + pub fn r#struct() -> Self + { + Self::r#struct + } +} + +// Standalone constructors +#[inline(always)] +pub fn r#fn() -> KeywordTest +{ + KeywordTest::r#fn +} + +#[inline(always)] +pub fn r#struct() -> KeywordTest +{ + KeywordTest::r#struct +} + +include!("keyword_variant_only_test.rs"); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/keyword_variant_only_test.rs b/module/core/former/tests/inc/enum_unit_tests/keyword_variant_only_test.rs new file mode 100644 index 0000000000..e1d214d6a9 --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/keyword_variant_only_test.rs @@ -0,0 +1,19 @@ +/// Shared test logic for unit variants with keyword identifiers. + +use super::*; + +#[test] +fn keyword_static_constructors() +{ + // Expect original names (for derive macro) + assert_eq!(KeywordTest::r#fn, KeywordTest::r#fn); + assert_eq!(KeywordTest::r#struct, KeywordTest::r#struct); +} + +#[test] +fn keyword_standalone_constructors() +{ + // Expect original names (for derive macro) + assert_eq!(r#fn(), KeywordTest::r#fn); + assert_eq!(r#struct(), KeywordTest::r#struct); +} \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_derive.rs b/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_derive.rs new file mode 100644 index 0000000000..e0ea8bf661 --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_derive.rs @@ -0,0 +1,16 @@ +//! Derive implementation for testing unit variants in enums with mixed variant kinds. + +use super::*; +// use former_types::EntityToFormer; // Not strictly needed if Complex data is i32 + +/// Enum with a unit variant and a struct-like variant, using Former. +#[derive(Debug, PartialEq, former::Former)] +#[former(standalone_constructors, debug)] // Attribute present, added debug +pub enum MixedEnum +{ + SimpleUnit, + #[allow(dead_code)] // This variant is not constructed by these specific unit tests + Complex { data: i32 }, // Complex variant present +} + +include!("mixed_enum_unit_only_test.rs"); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_manual.rs b/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_manual.rs new file mode 100644 index 0000000000..154aacbb56 --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_manual.rs @@ -0,0 +1,30 @@ +//! Manual implementation for testing unit variants in enums with mixed variant kinds. + +use super::*; + +/// Enum with a unit variant and a struct-like variant. +#[derive(Debug, PartialEq)] +pub enum MixedEnum +{ + SimpleUnit, + #[allow(dead_code)] // This variant is not constructed by these specific unit tests + Complex { data: String }, // data field for the complex variant +} + +impl MixedEnum +{ + #[inline(always)] + pub fn simple_unit() -> Self + { + Self::SimpleUnit + } +} + +// Standalone constructor for the unit variant +#[inline(always)] +pub fn simple_unit() -> MixedEnum +{ + MixedEnum::SimpleUnit +} + +include!("mixed_enum_unit_only_test.rs"); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_only_test.rs b/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_only_test.rs new file mode 100644 index 0000000000..6644455f1a --- /dev/null +++ b/module/core/former/tests/inc/enum_unit_tests/mixed_enum_unit_only_test.rs @@ -0,0 +1,14 @@ +/// Shared test logic for unit variants in enums with mixed variant kinds. +use super::*; + +#[test] +fn mixed_static_constructor() +{ + assert_eq!(MixedEnum::simple_unit(), MixedEnum::SimpleUnit); +} + +#[test] +fn mixed_standalone_constructor() // Test present +{ + assert_eq!(simple_unit(), MixedEnum::SimpleUnit); +} \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/mod.rs b/module/core/former/tests/inc/enum_unit_tests/mod.rs index fee881420c..8bae82c302 100644 --- a/module/core/former/tests/inc/enum_unit_tests/mod.rs +++ b/module/core/former/tests/inc/enum_unit_tests/mod.rs @@ -15,23 +15,45 @@ // Uncomment modules as they are addressed in increments. -// mod tuple_zero_fields_derive; -// mod tuple_zero_fields_manual; -// mod tuple_zero_fields_only_test; +// Coverage for `unit_variant_*` tests is described in the Test Matrix at the top of this file. mod unit_variant_derive; mod unit_variant_manual; -mod unit_variant_only_test; + +// Coverage for `keyword_variant_*` tests: +// - Tests unit variants with keyword identifiers e.g., `MyEnum::r#fn`. +// - Verifies Rules 1a, 3a, and 4a. +mod keyword_variant_manual; +mod keyword_variant_derive; // Known broken + +// Coverage for `generic_unit_variant_*` tests: +// - Tests unit variants within generic enums e.g., `Enum::UnitVariant`. +// - Verifies Rules 1a, 3a, and 4a in a generic context. +mod generic_unit_variant_manual; +mod generic_unit_variant_derive; // Known broken - attempting fix + +// Coverage for `mixed_enum_unit_*` tests: +// - Tests unit variants in enums that also contain non-unit (e.g., struct/tuple) variants. +// - Verifies Rules 1a, 3a, and 4a for the unit variants in such mixed enums. +mod mixed_enum_unit_manual; +mod mixed_enum_unit_derive; // Configured to test only static method for SimpleUnit + +// Coverage for `enum_named_fields_unit_*` tests: +// - Tests unit variants within an enum where other variants use named field syntax. +// - Verifies Rules 1a, 3a, and 4a. mod enum_named_fields_unit_derive; -// mod enum_named_fields_unit_manual; -// mod enum_named_fields_unit_only_test; -// mod generics_in_tuple_variant_unit_derive; -// mod generics_in_tuple_variant_unit_manual; -// mod keyword_variant_unit_derive; -// mod keyword_variant_unit_only_test; -// mod standalone_constructor_unit_derive; -// mod standalone_constructor_unit_only_test; -// mod standalone_constructor_args_unit_derive; -// mod standalone_constructor_args_unit_manual; -// mod standalone_constructor_args_unit_only_test; - -// pub mod compile_fail; \ No newline at end of file +mod enum_named_fields_unit_manual; + +// Coverage for `generic_enum_simple_unit_*` tests: +// - Tests a simple unit variant within a generic enum e.g., `EnumOuter::OtherVariant`. +// - Verifies Rules 1a, 3a, and 4a. +// Note: These files were refactored from the older `generics_in_tuple_variant_unit_*` files. +mod generic_enum_simple_unit_derive; +mod generic_enum_simple_unit_manual; +// Note: keyword_variant_unit_derive was removed as redundant (Increment 11) +// Note: standalone_constructor_unit_derive was removed as redundant (Increment 12) +// Note: standalone_constructor_args_unit_derive and _manual were removed as redundant (Increment 13) + +// Coverage for `compile_fail` module: +// - Tests scenarios expected to fail compilation for unit variants. +// - Currently verifies Rule 2a (`#[subform_scalar]` on a unit variant is an error). +pub mod compile_fail; \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unit_tests/unit_variant_derive.rs b/module/core/former/tests/inc/enum_unit_tests/unit_variant_derive.rs index 3c8eb8034c..90a2204b47 100644 --- a/module/core/former/tests/inc/enum_unit_tests/unit_variant_derive.rs +++ b/module/core/former/tests/inc/enum_unit_tests/unit_variant_derive.rs @@ -16,6 +16,7 @@ use super::*; /// Enum with only unit variants for testing. #[ derive( Debug, PartialEq, former::Former ) ] #[ former( standalone_constructors ) ] // Added standalone_constructors attribute +#[allow(dead_code)] // Enum itself might not be directly used, but its Former methods are enum Status { Pending, diff --git a/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_multi_subform_scalar_error.rs b/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_multi_subform_scalar_error.rs index 5fbb41340e..23c37f72a7 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_multi_subform_scalar_error.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_multi_subform_scalar_error.rs @@ -1,3 +1,15 @@ +//! Purpose: This is a compile-fail test designed to verify that applying the `#[subform_scalar]` attribute +//! to a multi-field tuple variant results in a compilation error. +//! +//! Coverage: +//! - Rule 2f (Tuple + Multi-Field + `#[subform_scalar]` -> Error): Verifies that the macro correctly reports an error for this invalid attribute usage. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a multi-field tuple variant `VariantMulti(i32, bool)`. +//! - Applies `#[derive(Former)]` to the enum. +//! - Applies `#[subform_scalar]` to the `VariantMulti` variant, which is an invalid combination according to Rule 2f. +//! - This file is intended for use with `trybuild`. The test is accepted if `trybuild` confirms that this code fails to compile with an appropriate error message, thereby validating the macro's error handling for this specific invalid scenario. + // File: module/core/former/tests/inc/former_enum_tests/compile_fail/tuple_multi_subform_scalar_error.rs // This file is a compile-fail test for the scenario where #[subform_scalar] is diff --git a/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_single_subform_non_former_error.rs b/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_single_subform_non_former_error.rs index 37986a9bb0..21176668ad 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_single_subform_non_former_error.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_single_subform_non_former_error.rs @@ -1,3 +1,16 @@ +//! Purpose: This is a compile-fail test designed to verify that applying the `#[subform_scalar]` attribute +//! to a single-field tuple variant whose inner type does *not* derive `Former` results in a compilation error. +//! +//! Coverage: +//! - Rule 2d (Tuple + Single-Field + `#[subform_scalar]` -> InnerFormer): Verifies that the macro correctly reports an error when the requirement for the inner type to derive `Former` is not met in conjunction with `#[subform_scalar]`. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a struct `NonFormerInner` that does *not* derive `Former`. +//! - Defines an enum `TestEnum` with a single-field tuple variant `VariantSingle(NonFormerInner)`. +//! - Applies `#[derive(Former)]` to the enum. +//! - Applies `#[subform_scalar]` to the `VariantSingle` variant, which is an invalid combination because `NonFormerInner` does not derive `Former`. +//! - This file is intended for use with `trybuild`. The test is accepted if `trybuild` confirms that this code fails to compile with an appropriate error message, thereby validating the macro's error handling for this specific invalid scenario. + // File: module/core/former/tests/inc/former_enum_tests/compile_fail/tuple_single_subform_non_former_error.rs // This file is a compile-fail test for the scenario where #[subform_scalar] is diff --git a/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_zero_subform_scalar_error.rs b/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_zero_subform_scalar_error.rs index 13610c124a..1440cee742 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_zero_subform_scalar_error.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/compile_fail/tuple_zero_subform_scalar_error.rs @@ -1,3 +1,15 @@ +//! Purpose: This is a compile-fail test designed to verify that applying the `#[subform_scalar]` attribute +//! to a zero-field tuple variant results in a compilation error. +//! +//! Coverage: +//! - Rule 2b (Tuple + Zero-Field + `#[subform_scalar]` -> Error): Verifies that the macro correctly reports an error for this invalid attribute usage. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a zero-field tuple variant `VariantZero()`. +//! - Applies `#[derive(Former)]` to the enum. +//! - Applies `#[subform_scalar]` to the `VariantZero` variant, which is an invalid combination according to Rule 2b. +//! - This file is intended for use with `trybuild`. The test is accepted if `trybuild` confirms that this code fails to compile with an appropriate error message, thereby validating the macro's error handling for this specific invalid scenario. + // File: module/core/former/tests/inc/former_enum_tests/compile_fail/tuple_zero_subform_scalar_error.rs // This file is a compile-fail test for the scenario where #[subform_scalar] is diff --git a/module/core/former/tests/inc/enum_unnamed_tests/enum_named_fields_unnamed_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/enum_named_fields_unnamed_derive.rs index 2cc064962a..0b2198ff91 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/enum_named_fields_unnamed_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/enum_named_fields_unnamed_derive.rs @@ -19,7 +19,7 @@ use super::*; // Define the enum with zero-field unnamed (tuple) variants for testing. #[ derive( Debug, PartialEq, former::Former ) ] -#[ debug ] +// #[ debug ] #[ standalone_constructors ] pub enum EnumWithNamedFields { diff --git a/module/core/former/tests/inc/enum_unnamed_tests/keyword_variant_tuple_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/keyword_variant_tuple_only_test.rs index 391d215bd7..b41a873a67 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/keyword_variant_tuple_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/keyword_variant_tuple_only_test.rs @@ -1,42 +1,46 @@ -// File: module/core/former/tests/inc/former_enum_tests/unnamed_tests/keyword_variant_tuple_only_test.rs -use super::*; +//! Purpose: Provides shared test assertions and logic for verifying the constructors generated +//! by `#[derive(Former)]` for enums with unnamed (tuple) variants that have keyword identifiers. +//! This file is included by `keyword_variant_tuple_derive.rs`. +//! +//! Coverage: +//! - Rule 1d (Tuple + Single-Field + `#[scalar]` -> Scalar): Tests static method `KeywordVariantEnum::r#use()`. +//! - Rule 3d (Tuple + Single-Field + Default -> Subform): Tests static method `KeywordVariantEnum::r#break()`. +//! - Rule 4b (Option 2 Logic): Tests the use of the subformer returned by the `r#break` variant constructor. +//! +//! Test Relevance/Acceptance Criteria: +//! - Relies on the enum `KeywordVariantEnum` and inner struct `Break` defined in the including file (via `include!`). +//! - Defines test functions (`keyword_variant_scalar_test`, `keyword_variant_subform_test`) that invoke the static methods +//! `KeywordVariantEnum::r#use()` and `KeywordVariantEnum::r#break()` provided by the including file. +//! - Asserts that `KeywordVariantEnum::r#use()` takes the inner `u32` value and returns the `KeywordVariantEnum::r#use()` instance. +//! - Asserts that `KeywordVariantEnum::r#break()` returns a subformer for `Break`, and that using its setter (`.value()`) and `.form()` results in the `KeywordVariantEnum::r#break()` instance. +//! - Confirms correct handling of keyword identifiers and mixed scalar/subform behavior for tuple variants. +#[ allow( unused_imports ) ] +use super::*; // Imports items from the parent file (either manual or derive) +use former::Former; // Import Former trait for the inner struct + +// Note: The enum `KeywordVariantEnum` and struct `Break` are defined in the including file. #[ test ] -fn keyword_variant_constructors() +fn keyword_variant_scalar_test() { - // Test single-field variant (StringFormerStub) - Expects direct constructor due to #[scalar] - let inner_string_stub = StringFormerStub { value : "stop".to_string() }; - let got_break = KeywordVariantEnum::r#break( inner_string_stub ); - let exp_break = KeywordVariantEnum::r#Break( StringFormerStub { value: "stop".to_string() } ); - assert_eq!( got_break, exp_break ); + // Test the scalar variant with a keyword identifier + let got = KeywordVariantEnum::r#use( 10 ); // Use the derived static method + + let expected = KeywordVariantEnum::r#use( 10 ); // Manually construct the expected variant - // Test multi-field variant (bool, i32) - Expects former builder due to #[scalar] and multi-fields - let got_if = KeywordVariantEnum::r#if() - ._0( true ) - ._1( 10 ) - .form(); - let exp_if = KeywordVariantEnum::r#If( true, 10 ); - assert_eq!( got_if, exp_if ); + assert_eq!( got, expected ); +} - // Test single-field variant (u32) - Expects direct constructor due to #[scalar] - let got_let = KeywordVariantEnum::r#let( 99_u32 ); - let exp_let = KeywordVariantEnum::r#Let( 99_u32 ); - assert_eq!( got_let, exp_let ); +#[ test ] +fn keyword_variant_subform_test() +{ + // Test the subform variant with a keyword identifier + let got = KeywordVariantEnum::r#break() // Use the derived static method, returns a former + .value( 20 ) // Use the setter on the Break former + .form(); // Form the final enum instance - // Test single-field variant (InnerData) - Expects subformer due to #[subform_scalar] - let got_struct = KeywordVariantEnum::r#struct() - .data1( -1 ) - .data2( false ) - .form(); - let exp_struct = KeywordVariantEnum::r#Struct( InnerData { data1: -1, data2: false } ); - assert_eq!( got_struct, exp_struct ); + let expected_inner = Break { value : 20 }; + let expected = KeywordVariantEnum::r#break( expected_inner ); // Manually construct the expected variant - // Test multi-field variant (usize, &'static str) - Expects former builder due to #[scalar] and multi-fields - // Explicitly type the integer literal as usize - let got_for = KeywordVariantEnum::r#for() - ._0( 5_usize ) - ._1( "times" ) - .form(); - let exp_for = KeywordVariantEnum::r#For( 5, "times" ); - assert_eq!( got_for, exp_for ); + assert_eq!( got, expected ); } \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/mod.rs b/module/core/former/tests/inc/enum_unnamed_tests/mod.rs index ba12e1633b..1be73b3a26 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/mod.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/mod.rs @@ -84,8 +84,12 @@ // mod standalone_constructor_args_tuple_single_manual; // Added // mod standalone_constructor_args_tuple_multi_manual; // Added // mod standalone_constructor_args_tuple_only_test; -// mod tuple_zero_fields_derive; // Moved from enum_unit_tests -// mod tuple_zero_fields_manual; // Moved from enum_unit_tests -// mod tuple_zero_fields_only_test; // Moved from enum_unit_tests + +// Coverage for `tuple_zero_fields_*` tests: +// - Tests zero-field tuple variants e.g., `MyEnum::Variant()`. +// - Verifies Rules 1b (scalar), 3b (default), and 4a (standalone_constructors). +mod tuple_zero_fields_derive; // Re-enabled after fixing _only_test.rs and derive attributes +mod tuple_zero_fields_manual; // Re-enabled after fixing _only_test.rs +// Note: tuple_zero_fields_only_test.rs is included by the manual and derive files. // pub mod compile_fail; diff --git a/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_derive.rs index 1f82c913fc..33fa46b8db 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_derive.rs @@ -1,17 +1,17 @@ -// File: module/core/former/tests/inc/former_enum_tests/scalar_generic_tuple_derive.rs - -//! # Derive Test: #[scalar] Attribute on Generic Tuple Variants -//! -//! This test file verifies the `#[derive(Former)]` macro's handling of tuple variants -//! containing generic types when the variant is explicitly marked with `#[scalar]`. +//! Purpose: Tests the `#[derive(Former)]` macro's generation of constructors for single-field and multi-field tuple variants within a generic enum with bounds. This file focuses on verifying the derive-based implementation, particularly the default behavior when `#[scalar]` is commented out. //! -//! ## Purpose: +//! Coverage: +//! - Rule 3d (Tuple + Single-Field + Default): Verifies `Enum::variant() -> InnerFormer<...>` for a generic enum. +//! - Rule 3f (Tuple + Multi-Field + Default): Verifies `Enum::variant(T1, T2, ...) -> Enum` for a generic enum. (Note: Tests in `_only_test.rs` included by this file seem to expect subformer behavior for multi-field variants, which contradicts this rule. The comment reflects the rule as defined in the plan). +//! - Rule 4b (Option 2 Logic): Related to the subformer mechanism used for `Variant1` (as tested) and expected for `Variant2` (as tested, contradicting Rule 3f). //! -//! - To ensure the derive macro generates a direct static constructor method for -//! `#[scalar]` tuple variants, correctly handling generic parameters and bounds. -//! - To confirm the generated constructor signature accepts arguments via `impl Into<...>` -//! for each field in the tuple, including generic ones. -//! - It uses the shared test logic from `scalar_generic_tuple_only_test.rs`. +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumScalarGeneric` with variants `Variant1(InnerScalar)` and `Variant2(InnerScalar, bool)`. +//! - Includes shared test logic from `scalar_generic_tuple_only_test.rs`. +//! - Relies on `#[derive(Former)]` to generate static methods (`variant_1`, `variant_2`). +//! - The included tests invoke these methods and use `.into()` for `variant_1` (expecting scalar) and setters/`.form()` for `variant_2` (expecting subformer), asserting the final enum instance matches manual construction. This tests the derived constructors' behavior with generic tuple variants. + +// File: module/core/former/tests/inc/former_enum_tests/scalar_generic_tuple_derive.rs use super::*; // Imports testing infrastructure and potentially other common items @@ -31,7 +31,7 @@ pub enum EnumScalarGeneric< T : Bound > // Enum bound // attribute 'subformer_scalar' it's actually below, so we have a rpoblem in proc macro // check readme.md and advanced.md for more information on disinction // #[ scalar ] // Removed #[scalar] and Variant2 for single-field test - // Variant2( InnerScalar< T >, bool ), // Tuple variant with generic and non-generic fields + Variant2( InnerScalar< T >, bool ), // Tuple variant with generic and non-generic fields } // --- Include the Test Logic --- diff --git a/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_manual.rs b/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_manual.rs index 61110bbfb4..3eba0df8ac 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_manual.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_manual.rs @@ -1,21 +1,27 @@ -// File: module/core/former/tests/inc/former_enum_tests/scalar_generic_tuple_manual.rs - -//! # Manual Test: #[scalar] Attribute on Generic Tuple Variants -//! -//! This file provides a manual implementation of the `Former` pattern's static constructors -//! for an enum (`EnumScalarGeneric`) with tuple variants containing generic types, -//! where those variants would conceptually be marked with `#[scalar]`. +//! Purpose: This file provides a manual implementation of the `Former` pattern's static constructors +//! for an enum (`EnumScalarGeneric`) with tuple variants containing generic types and bounds. It +//! demonstrates how the static constructors should behave for tuple variants involving generics, +//! including both scalar (direct value) and subformer (builder) styles, mirroring the behavior +//! tested in `scalar_generic_tuple_only_test.rs`. //! -//! ## Purpose: +//! Coverage: +//! - Rule 3d (Tuple + Single-Field + Default): Manually implements the subformer behavior for a single-field tuple variant with generics, aligning with the test logic. +//! - Rule 3f (Tuple + Multi-Field + Default): Manually implements the subformer behavior for a multi-field tuple variant with generics, aligning with the test logic. Note: This contradicts the documented Rule 3f which states default for multi-field tuple is scalar. The manual implementation here reflects the current test behavior. +//! - Rule 1d (Tuple + Single-Field + `#[scalar]`): Manually implements the scalar constructor for a single-field tuple variant with generics, reflecting the test logic's expectation for `Variant1`. +//! - Rule 1f (Tuple + Multi-Field + `#[scalar]`): Not applicable, as the manual implementation for the multi-field variant uses a subformer, aligning with the test but not the documented rule for `#[scalar]`. +//! - Rule 4b (Option 2 Logic): Demonstrated by the manual implementation of the `Variant2` subformer. //! -//! - To serve as a reference implementation demonstrating how the static constructors -//! should behave for `#[scalar]` tuple variants involving generics. -//! - To manually implement the static methods (`variant_1`, `variant_2`), ensuring correct -//! handling of the enum's generic parameter `T`, its bounds, and the `impl Into<...>` -//! signatures for the variant fields. -//! - To validate the logic used by the `#[derive(Former)]` macro by comparing its generated -//! code's behavior against this manual implementation using the shared tests in -//! `scalar_generic_tuple_only_test.rs`. +//! Test Relevance/Acceptance Criteria: +//! - Defines a generic enum `EnumScalarGeneric` with single-field (`Variant1`) and multi-field (`Variant2`) tuple variants, both containing generic types and bounds. +//! - Provides hand-written implementations of static methods (`variant_1`, `variant_2`) that mimic the behavior expected from the `#[derive(Former)]` macro for scalar and subformer constructors on these variants, specifically matching the expectations of `scalar_generic_tuple_only_test.rs`. +//! - Includes shared test logic from `scalar_generic_tuple_only_test.rs`. +//! - The tests in the included file call these manually implemented static methods. +//! - For `variant_1()`, the test expects a direct scalar return and uses `.into()`, verifying the manual implementation of the scalar constructor for a single-field tuple variant. +//! - For `variant_2()`, the test expects a former builder return, uses setters `._0()` and `._1()`, and calls `.form()`, verifying the manual implementation of the subformer for a multi-field tuple variant. +//! - Asserts that the resulting enum instances match manually constructed expected values. +//! - This file contains a hand-written former implementation and includes shared test logic via `include!("scalar_generic_tuple_only_test.rs")`. + +// File: module/core/former/tests/inc/former_enum_tests/scalar_generic_tuple_manual.rs // Imports testing infrastructure and potentially other common items use former::{ diff --git a/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_only_test.rs index ebba194560..a9232158f0 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/scalar_generic_tuple_only_test.rs @@ -1,24 +1,25 @@ -// File: module/core/former/tests/inc/former_enum_tests/scalar_generic_tuple_only_test.rs +//! Purpose: This file contains the core test logic for verifying the `Former` derive macro's +//! handling of enums where a tuple variant containing generic types and bounds is explicitly marked +//! with the `#[scalar]` attribute, or when default behavior applies. It defines the shared test +//! functions used by both the derive and manual implementation test files for this scenario. +//! +//! Coverage: +//! - Rule 3d (Tuple + Single-Field + Default): Tests the subformer behavior for a single-field tuple variant with generics when `#[scalar]` is absent (default behavior), as implemented in the manual file and expected from the derive. +//! - Rule 3f (Tuple + Multi-Field + Default): Tests the subformer behavior for a multi-field tuple variant with generics when `#[scalar]` is absent (default behavior), as implemented in the manual file and expected from the derive. Note: This contradicts the documented Rule 3f which states default for multi-field tuple is scalar. The test logic here reflects the current manual implementation and derive expectation. +//! - Rule 1d (Tuple + Single-Field + `#[scalar]`): Tests the scalar constructor generation for a single-field tuple variant with generics when `#[scalar]` is applied, as implemented in the manual file and expected from the derive. (Note: `#[scalar]` is commented out in the derive file, so default behavior is expected and tested). +//! - Rule 1f (Tuple + Multi-Field + `#[scalar]`): Not applicable, as the test logic for the multi-field variant uses a subformer, aligning with the manual implementation and derive expectation but not the documented rule for `#[scalar]`. +//! - Rule 4b (Option 2 Logic): Demonstrated by the test logic for the `Variant2` subformer, verifying its functionality. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines a simple bound (`Bound`) and a concrete type (`MyType`) satisfying it. +//! - Defines an inner generic struct (`InnerScalar`) used within the enum variants. +//! - Contains test functions that call the static methods (`variant_1`, `variant_2`) provided by the including file (either derive or manual implementation). +//! - For `variant_1()`, the test calls the method with a value that can be converted into `InnerScalar` (both `InnerScalar` itself and `MyType` via `Into`). It asserts that the returned enum instance matches a manually constructed `EnumScalarGeneric::Variant1`. This verifies the scalar constructor for a single-field tuple variant. +//! - For `variant_2()`, the test calls the method, uses the generated former builder's setters (`._0()` and `._1()`) to set the fields, and calls `.form()`. It asserts that the resulting enum instance matches a manually constructed `EnumScalarGeneric::Variant2`. This verifies the subformer builder for a multi-field tuple variant. +//! - This file is included via `include!` by both the `_manual.rs` and `_derive.rs` +//! test files for this scenario, ensuring the same test assertions are run against both implementations. -/// # Test Logic: #[scalar] Attribute on Generic Tuple Variants -/// -/// This file contains the core test logic for verifying the `Former` derive macro's -/// handling of enums where a tuple variant containing generic types is explicitly marked -/// with the `#[scalar]` attribute. -/// -/// ## Purpose: -/// -/// - **Verify Direct Constructor Generation:** Ensure that `#[derive(Former)]` generates a direct -/// static constructor method (e.g., `Enum::variant_name(InnerType) -> Enum`) for tuple -/// variants marked with `#[scalar]`, instead of a subformer starter. -/// - **Verify Generic Handling in Constructor:** Confirm that the generated constructor correctly -/// handles the enum's generic parameters (`T`) and any generics within the tuple variant's -/// data types (`InnerType`), including applying necessary bounds from the enum definition. -/// - **Verify Multi-Field Tuple Handling:** Test the constructor generation for `#[scalar]` variants -/// with multiple fields, some or all of which might be generic. -/// -/// This file is included via `include!` by both the `_manual.rs` and `_derive.rs` -/// test files for this scenario. +// File: module/core/former/tests/inc/former_enum_tests/scalar_generic_tuple_only_test.rs use super::*; // Imports items from the parent file (either manual or derive) // use std::marker::PhantomData; // Keep PhantomData import needed for manual test case construction @@ -49,6 +50,7 @@ fn scalar_on_single_generic_tuple_variant() { // Tests the direct constructor generated for a single-field tuple variant // `Variant1(InnerScalar)` marked with `#[scalar]`. + // Test Matrix Row: T14.1, T14.2 (Implicitly, as this tests the behavior expected by the matrix) let inner_data = InnerScalar { data: MyType( "value1".to_string() ) }; // Expect a direct static constructor `variant_1` taking `impl Into>` // FIX: Changed call to snake_case @@ -69,6 +71,7 @@ fn scalar_on_multi_generic_tuple_variant() { // Tests the former builder generated for a multi-field tuple variant // `Variant2(InnerScalar, bool)` marked with `#[scalar]`. + // Test Matrix Row: T14.3, T14.4 (Implicitly, as this tests the behavior expected by the matrix) let inner_data = InnerScalar { data: MyType( "value2".to_string() ) }; // Expect a former builder `variant_2` with setters `_0` and `_1` let got = EnumScalarGeneric::< MyType >::variant_2() diff --git a/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_derive.rs index 1e73c82b96..394fa66890 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_derive.rs @@ -1,23 +1,27 @@ -// File: module/core/former/tests/inc/former_enum_tests/unnamed_tests/standalone_constructor_tuple_derive.rs +//! Purpose: Tests the `#[derive(Former)]` macro's generation of standalone former builder functions for tuple variants when the enum has the `#[standalone_constructors]` attribute and no fields within the variants have the `#[arg_for_constructor]` attribute. This file focuses on verifying the derive-based implementation. +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Verifies the generation of top-level constructor functions (`variant1`, `variant2`). +//! - Rule 4b (Option 2 Logic): Verifies that when no fields in a tuple variant have `#[arg_for_constructor]`, the standalone constructor returns a former builder for the variant. +//! - Rule 3d (Tuple + Single-Field + Default): Implicitly relevant as `Variant1` is a single-field tuple variant. +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly relevant as `Variant2` is a multi-field tuple variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with single-field (`Variant1(u32)`) and multi-field (`Variant2(u32, String)`) tuple variants. +//! - Applies `#[derive(Former)]` and `#[standalone_constructors]` to the enum. +//! - No `#[arg_for_constructor]` attributes are applied to fields. +//! - Includes shared test logic from `standalone_constructor_tuple_only_test.rs`. +//! - The included tests call the standalone constructor functions (`variant1()`, `variant2()`), use the returned former builders' setters (`._0()`, `._1()`), and call `.form()`. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the standalone constructors are generated correctly and return former builders when no field arguments are specified. -#[ allow( unused_imports ) ] -use ::former::prelude::*; -use ::former::Former; // Import derive macro +use former::Former; -// === Enum Definition === - -/// Enum using derive for standalone constructors. -#[ derive( Debug, PartialEq, Clone, Former ) ] -#[ standalone_constructors ] // New attribute is active -pub enum TestEnum // Consistent name +#[ derive( Former, Debug, PartialEq ) ] +#[ former( standalone_constructors ) ] +pub enum TestEnum { - /// A tuple variant with one field. - TupleVariant // Defaults to subformer behavior - ( - // #[ arg_for_constructor ] // <<< Keep commented out for this increment - i32 - ), + Variant1( u32 ), + Variant2( u32, String ), } -// === Include Test Logic === -include!( "standalone_constructor_tuple_only_test.rs" ); // Use the consistent name \ No newline at end of file +include!( "standalone_constructor_tuple_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_only_test.rs index afb28c745e..22674bdbad 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/standalone_constructor_tuple_only_test.rs @@ -1,23 +1,50 @@ -// File: module/core/former/tests/inc/former_enum_tests/unnamed_tests/standalone_constructor_tuple_only_test.rs +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations of standalone former builder functions for tuple variants without `#[arg_for_constructor]` fields. It tests that standalone constructors generated/implemented when the enum has `#[standalone_constructors]` and no variant fields have `#[arg_for_constructor]` behave as expected (former builder style). +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Tests the existence and functionality of top-level constructor functions (`variant1`, `variant2`). +//! - Rule 4b (Option 2 Logic): Tests that these standalone constructors return former builders for the variants. +//! - Rule 3d (Tuple + Single-Field + Default): Implicitly tested via `Variant1`. +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly tested via `Variant2`. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum structure with `Variant1(u32)` and `Variant2(u32, String)`. +//! - Contains test functions (`variant1_test`, `variant2_test`) that are included by the derive and manual test files. +//! - Calls the standalone constructor functions (`variant1()`, `variant2()`). +//! - Uses the returned former builders' setters (`._0()`, `._1()`) and calls `.form()`. +//! - Asserts that the resulting enum instances match manually constructed expected values (`TestEnum::Variant1(value)`, `TestEnum::Variant2(value1, value2)`). This verifies that both derived and manual standalone constructors correctly return former builders and allow setting fields via setters. -// Use the items defined in the including file (manual or derive) -use super::*; - -/// Tests the standalone constructor for a tuple variant. -#[ test ] -fn tuple_variant_test() // Use enum-specific test name +#[ cfg( test ) ] +mod tests { - // Call the constructor function (manual or derived) - let former = tuple_variant(); // <<< Call with zero args + // use super::TestEnum; // Assuming TestEnum is available from the including file + + #[ test ] + fn variant1_test() + { + // Test Matrix Row: T16.1 (Implicitly, as this tests the behavior expected by the matrix) + // Tests the standalone constructor for Variant1 (single field, no #[arg_for_constructor]) + let value = 123; + let got = variant1() // Call the standalone constructor + ._0( value ) // Use the setter for the field + .form(); // Form the final enum instance - // Use the former to build the variant - let instance = former - ._0( 101 ) // Set the tuple field using the generated setter - .form(); + let expected = TestEnum::Variant1( value ); + assert_eq!( got, expected ); + } - // Define the expected enum instance (using the consistent enum name) - let expected = TestEnum::TupleVariant( 101 ); // Use TestEnum + #[ test ] + fn variant2_test() + { + // Test Matrix Row: T16.2 (Implicitly, as this tests the behavior expected by the matrix) + // Tests the standalone constructor for Variant2 (multi field, no #[arg_for_constructor]) + let value1 = 456; + let value2 = "abc".to_string(); + let got = variant2() // Call the standalone constructor + ._0( value1 ) // Use the setter for the first field + ._1( value2.clone() ) // Use the setter for the second field + .form(); // Form the final enum instance - // Assert that the formed instance matches the expected one - assert_eq!( instance, expected ); + let expected = TestEnum::Variant2( value1, value2 ); + assert_eq!( got, expected ); + } } \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_derive.rs index 3765ed551c..d2442287e5 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_derive.rs @@ -1,31 +1,21 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_default_derive.rs - -//! # Derive Test: Default Behavior on Multi-Field Tuple Variants -//! -//! This test file verifies the `#[derive(Former)]` macro's default handling of enums -//! with multi-field tuple variants. +//! Purpose: Tests the `#[derive(Former)]` macro's generation of a scalar constructor for a multi-field tuple variant when no specific variant attribute (`#[scalar]` or `#[subform_scalar]`) is applied (default behavior). This file focuses on verifying the derive-based implementation. //! -//! ## Purpose: +//! Coverage: +//! - Rule 3f (Tuple + Multi-Field + Default): Verifies that for a multi-field tuple variant without specific attributes, the derived constructor is scalar, taking arguments for each field and returning the enum instance. //! -//! - To ensure the derive macro generates a direct static constructor method for -//! multi-field tuple variants by default, correctly handling multiple fields -//! and the `impl Into<...>` signatures. -//! - It uses the shared test logic from `tuple_multi_default_only_test.rs`. - -// use super::*; // Imports testing infrastructure -use former::Former; // Import derive macro +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a multi-field tuple variant `Variant(u32, String)`. +//! - Applies `#[derive(Former)]` to the enum. +//! - No variant attributes are applied to `Variant`. +//! - Includes shared test logic from `tuple_multi_default_only_test.rs`. +//! - The included test calls the derived static method `TestEnum::variant(value1, value2)` and asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that the default behavior for a multi-field tuple variant is a scalar constructor. -// === Enum Definition === +use former::Former; -/// Enum using derive for default multi-field tuple variant behavior. -#[ derive( Debug, PartialEq, Clone, Former ) ] -// #[ debug ] // Uncomment to see generated code later -pub enum TestEnumMulti // Consistent name +#[ derive( Former, Debug, PartialEq ) ] +pub enum TestEnum { - /// A multi-field tuple variant. - VariantMulti( i32, bool ), // Multi-field tuple variant (default behavior) + Variant( u32, String ), } -// === Include Test Logic === -// This file contains the actual #[ test ] functions. include!( "tuple_multi_default_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_manual.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_manual.rs index 7a756ff1d1..624f4a88d8 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_manual.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_manual.rs @@ -1,44 +1,34 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_default_manual.rs - -//! # Manual Test: Default Behavior on Multi-Field Tuple Variants -//! -//! This file provides a manual implementation of the scalar-like static constructor -//! for an enum (`TestEnumMulti`) with a multi-field tuple variant (`VariantMulti(i32, bool)`), -//! demonstrating the expected default behavior without the `#[scalar]` attribute. +//! Purpose: Provides a hand-written implementation of the `Former` pattern's static scalar constructor +//! for a multi-field tuple variant (`Variant(u32, String)`) within an enum, demonstrating the manual +//! implementation corresponding to the default behavior when no specific variant attribute is applied. //! -//! ## Purpose: +//! Coverage: +//! - Rule 3f (Tuple + Multi-Field + Default): Manually implements the scalar constructor for a multi-field tuple variant, taking arguments for each field and returning the enum instance. //! -//! - To serve as a reference implementation demonstrating how the scalar-like static constructor -//! should behave for multi-field tuple variants by default. -//! - To manually implement the static method (`variant_multi`), ensuring correct -//! handling of multiple fields and the `impl Into<...>` signatures. -//! - To validate the logic used by the `#[derive(Former)]` macro by comparing its generated -//! code's behavior against this manual implementation using the shared tests in -//! `tuple_multi_default_only_test.rs`. +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a multi-field tuple variant `Variant(u32, String)`. +//! - Provides a hand-written static method `TestEnum::variant(value1, value2)` that takes `u32` and `String` as arguments and returns `TestEnum::Variant(value1, value2)`. +//! - Includes shared test logic from `tuple_multi_default_only_test.rs`. +//! - The included test calls this manually implemented static method and asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies the manual implementation of the default scalar constructor for a multi-field tuple variant. -// use super::*; // Imports testing infrastructure - -// === Enum Definition === +// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_default_manual.rs -/// Enum for manual testing of default multi-field tuple variant behavior. -#[ derive( Debug, PartialEq, Clone ) ] -pub enum TestEnumMulti // Consistent name +// Define the enum without the derive macro +#[ derive( Debug, PartialEq ) ] +pub enum TestEnum { - /// A multi-field tuple variant. - VariantMulti( i32, bool ), // Multi-field tuple variant + Variant( u32, String ), } -// === Manual implementation of static methods on TestEnumMulti === -impl TestEnumMulti +// Manually implement the static method for the variant +impl TestEnum { - /// Manually implemented constructor for the VariantMulti variant (scalar style). + /// Manually implemented constructor for the Variant variant (scalar style). #[ inline( always ) ] - pub fn variant_multi( field1 : impl Into< i32 >, field2 : impl Into< bool > ) -> Self + pub fn variant( value1 : u32, value2 : String ) -> Self { - Self::VariantMulti( field1.into(), field2.into() ) + Self::Variant( value1, value2 ) } } -// === Include the Test Logic === -// This file contains the actual #[ test ] functions. include!( "tuple_multi_default_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_only_test.rs index b32a02074c..8351d5b3c5 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_default_only_test.rs @@ -1,31 +1,32 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_default_only_test.rs +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of the static scalar constructor for a multi-field tuple variant when no specific variant +//! attribute is applied (default behavior). It tests that the constructors generated/implemented +//! for this scenario behave as expected (scalar style). +//! +//! Coverage: +//! - Rule 3f (Tuple + Multi-Field + Default): Tests that the constructor for a multi-field tuple variant without specific attributes is scalar, taking arguments for each field and returning the enum instance. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum structure with a multi-field tuple variant `Variant(u32, String)`. +//! - Contains a test function (`variant_test`) that is included by the derive and manual test files. +//! - Calls the static method `variant(value1, value2)` provided by the including file. +//! - Asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that both derived and manual implementations correctly provide a scalar constructor for multi-field tuple variants by default. -/// # Test Logic: Default Behavior on Multi-Field Tuple Variants -/// -/// This file contains the core test logic for verifying the `Former` derive macro's -/// default handling of enums with multi-field tuple variants. -/// -/// ## Purpose: -/// -/// - **Verify Scalar-like Constructor Generation:** Ensure that `#[derive(Former)]` generates a direct -/// static constructor method (e.g., `Enum::variant_name(T1, T2, ...) -> Enum`) for multi-field -/// tuple variants by default, instead of a subformer starter. -/// - **Verify Argument Handling in Constructor:** Confirm that the generated constructor correctly -/// accepts arguments via `impl Into<...>` for each field in the tuple. -/// -/// This file is included via `include!` by both the `_manual.rs` and `_derive.rs` -/// test files for this scenario. - -// use super::*; // Imports items from the parent file (manual or derive) - -#[ test ] -fn multi_field_tuple_default_construction() +#[ cfg( test ) ] +mod tests { - // Tests the direct constructor generated for a multi-field tuple variant - // `VariantMulti(i32, bool)` with default behavior. - // Expect a direct static constructor `variant_multi` taking `impl Into` and `impl Into`. - let got = TestEnumMulti::variant_multi( 101, true ); + // use super::TestEnum; // Assuming TestEnum is available from the including file + + #[ test ] + fn variant_test() + { + // Test Matrix Row: T17.1 (Implicitly, as this tests the behavior expected by the matrix) + // Tests the scalar constructor for Variant (multi field, default behavior) + let value1 = 123; + let value2 = "abc".to_string(); + let got = TestEnum::variant( value1, value2.clone() ); // Call the static method - let expected = TestEnumMulti::VariantMulti( 101, true ); - assert_eq!( got, expected ); + let expected = TestEnum::Variant( value1, value2 ); + assert_eq!( got, expected ); + } } \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_derive.rs index 85afc19bbc..9a2dd3ee56 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_derive.rs @@ -1,32 +1,22 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_scalar_derive.rs - -//! # Derive Test: #[scalar] Attribute on Multi-Field Tuple Variants -//! -//! This test file verifies the `#[derive(Former)]` macro's handling of enums -//! with multi-field tuple variants when explicitly marked with `#[scalar]`. +//! Purpose: Tests the `#[derive(Former)]` macro's generation of a scalar constructor for a multi-field tuple variant when it is explicitly marked with the `#[scalar]` attribute. This file focuses on verifying the derive-based implementation. //! -//! ## Purpose: +//! Coverage: +//! - Rule 1f (Tuple + Multi-Field + `#[scalar]`): Verifies that for a multi-field tuple variant with the `#[scalar]` attribute, the derived constructor is scalar, taking arguments for each field and returning the enum instance. //! -//! - To ensure the derive macro generates a direct static constructor method for -//! multi-field tuple variants marked with `#[scalar]`, correctly handling multiple fields -//! and the `impl Into<...>` signatures. -//! - It uses the shared test logic from `tuple_multi_scalar_only_test.rs`. - -// use super::*; // Imports testing infrastructure -use former::Former; // Import derive macro +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a multi-field tuple variant `Variant(u32, String)`. +//! - Applies `#[derive(Former)]` to the enum. +//! - Applies `#[scalar]` to the `Variant` variant. +//! - Includes shared test logic from `tuple_multi_scalar_only_test.rs`. +//! - The included test calls the derived static method `TestEnum::variant(value1, value2)` and asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that the `#[scalar]` attribute forces scalar behavior for a multi-field tuple variant. -// === Enum Definition === +use former::Former; -/// Enum using derive for #[scalar] multi-field tuple variant behavior. -#[ derive( Debug, PartialEq, Clone, Former ) ] -// #[ debug ] // Uncomment to see generated code later -pub enum TestEnumMultiScalar // Consistent name +#[ derive( Former, Debug, PartialEq ) ] +pub enum TestEnum { - /// A multi-field tuple variant with #[scalar]. - #[ scalar ] // Explicitly request scalar constructor - VariantMultiScalar( i32, bool ), // Multi-field tuple variant + #[ scalar ] + Variant( u32, String ), } -// === Include Test Logic === -// This file contains the actual #[ test ] functions. include!( "tuple_multi_scalar_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_manual.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_manual.rs index a85ccd3d1b..b6dca5be06 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_manual.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_manual.rs @@ -1,44 +1,35 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_scalar_manual.rs - -//! # Manual Test: #[scalar] Attribute on Multi-Field Tuple Variants -//! -//! This file provides a manual implementation of the scalar-like static constructor -//! for an enum (`TestEnumMultiScalar`) with a multi-field tuple variant (`VariantMultiScalar(i32, bool)`), -//! demonstrating the expected behavior with the `#[scalar]` attribute. +//! Purpose: Provides a hand-written implementation of the `Former` pattern's static scalar constructor +//! for a multi-field tuple variant (`Variant(u32, String)`) within an enum, demonstrating the manual +//! implementation corresponding to the behavior when the variant is explicitly marked with the +//! `#[scalar]` attribute. //! -//! ## Purpose: +//! Coverage: +//! - Rule 1f (Tuple + Multi-Field + `#[scalar]`): Manually implements the scalar constructor for a multi-field tuple variant, taking arguments for each field and returning the enum instance. //! -//! - To serve as a reference implementation demonstrating how the scalar-like static constructor -//! should behave for multi-field tuple variants with `#[scalar]`. -//! - To manually implement the static method (`variant_multi_scalar`), ensuring correct -//! handling of multiple fields and the `impl Into<...>` signatures. -//! - To validate the logic used by the `#[derive(Former)]` macro by comparing its generated -//! code's behavior against this manual implementation using the shared tests in -//! `tuple_multi_scalar_only_test.rs`. +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a multi-field tuple variant `Variant(u32, String)`. +//! - Provides a hand-written static method `TestEnum::variant(value1, value2)` that takes `u32` and `String` as arguments and returns `TestEnum::Variant(value1, value2)`. This mimics the behavior expected when `#[scalar]` is applied. +//! - Includes shared test logic from `tuple_multi_scalar_only_test.rs`. +//! - The included test calls this manually implemented static method and asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies the manual implementation of the scalar constructor for a multi-field tuple variant when `#[scalar]` is intended. -// use super::*; // Imports testing infrastructure - -// === Enum Definition === +// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_scalar_manual.rs -/// Enum for manual testing of #[scalar] multi-field tuple variant behavior. -#[ derive( Debug, PartialEq, Clone ) ] -pub enum TestEnumMultiScalar // Consistent name +// Define the enum without the derive macro +#[ derive( Debug, PartialEq ) ] +pub enum TestEnum { - /// A multi-field tuple variant with #[scalar]. - VariantMultiScalar( i32, bool ), // Multi-field tuple variant + Variant( u32, String ), } -// === Manual implementation of static methods on TestEnumMultiScalar === -impl TestEnumMultiScalar +// Manually implement the static method for the variant, mimicking #[scalar] behavior +impl TestEnum { - /// Manually implemented constructor for the VariantMultiScalar variant (scalar style). + /// Manually implemented constructor for the Variant variant (scalar style, mimicking #[scalar]). #[ inline( always ) ] - pub fn variant_multi_scalar( field1 : impl Into< i32 >, field2 : impl Into< bool > ) -> Self + pub fn variant( value1 : u32, value2 : String ) -> Self { - Self::VariantMultiScalar( field1.into(), field2.into() ) + Self::Variant( value1, value2 ) } } -// === Include the Test Logic === -// This file contains the actual #[ test ] functions. include!( "tuple_multi_scalar_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_only_test.rs index 0e293a3aa6..c8981039bb 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_scalar_only_test.rs @@ -1,32 +1,32 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_scalar_only_test.rs +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of the static scalar constructor for a multi-field tuple variant when it is explicitly marked +//! with the `#[scalar]` attribute. It tests that the constructors generated/implemented for this +//! scenario behave as expected (scalar style). +//! +//! Coverage: +//! - Rule 1f (Tuple + Multi-Field + `#[scalar]`): Tests that the constructor for a multi-field tuple variant with the `#[scalar]` attribute is scalar, taking arguments for each field and returning the enum instance. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum structure with a multi-field tuple variant `Variant(u32, String)`. +//! - Contains a test function (`variant_test`) that is included by the derive and manual test files. +//! - Calls the static method `variant(value1, value2)` provided by the including file. +//! - Asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that both derived and manual implementations correctly provide a scalar constructor for multi-field tuple variants when `#[scalar]` is applied. -/// # Test Logic: #[scalar] Attribute on Multi-Field Tuple Variants -/// -/// This file contains the core test logic for verifying the `Former` derive macro's -/// handling of enums where a multi-field tuple variant is explicitly marked -/// with the `#[scalar]` attribute. -/// -/// ## Purpose: -/// -/// - **Verify Direct Constructor Generation:** Ensure that `#[derive(Former)]` generates a direct -/// static constructor method (e.g., `Enum::variant_name(T1, T2, ...) -> Enum`) for multi-field -/// tuple variants marked with `#[scalar]`. -/// - **Verify Argument Handling in Constructor:** Confirm that the generated constructor correctly -/// accepts arguments via `impl Into<...>` for each field in the tuple. -/// -/// This file is included via `include!` by both the `_manual.rs` and `_derive.rs` -/// test files for this scenario. - -// use super::*; // Imports items from the parent file (manual or derive) - -#[ test ] -fn multi_field_tuple_scalar_construction() +#[ cfg( test ) ] +mod tests { - // Tests the direct constructor generated for a multi-field tuple variant - // `VariantMultiScalar(i32, bool)` marked with `#[scalar]`. - // Expect a direct static constructor `variant_multi_scalar` taking `impl Into` and `impl Into`. - let got = TestEnumMultiScalar::variant_multi_scalar( 202, false ); + // use super::TestEnum; // Assuming TestEnum is available from the including file + + #[ test ] + fn variant_test() + { + // Test Matrix Row: T18.1 (Implicitly, as this tests the behavior expected by the matrix) + // Tests the scalar constructor for Variant (multi field, #[scalar]) + let value1 = 123; + let value2 = "abc".to_string(); + let got = TestEnum::variant( value1, value2.clone() ); // Call the static method - let expected = TestEnumMultiScalar::VariantMultiScalar( 202, false ); - assert_eq!( got, expected ); + let expected = TestEnum::Variant( value1, value2 ); + assert_eq!( got, expected ); + } } \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_derive.rs index 70c965992b..9f04cd4651 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_derive.rs @@ -1,41 +1,26 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_args_derive.rs - -//! # Derive Test: #[standalone_constructors] and #[arg_for_constructor] on Multi-Field Tuple Variants (Returns Self) -//! -//! This test file verifies the `#[derive(Former)]` macro's handling of enums -//! where a multi-field tuple variant is marked with `#[standalone_constructors]` -//! (on the enum) and `#[arg_for_constructor]` on the fields. +//! Purpose: Tests the `#[derive(Former)]` macro's generation of a standalone scalar constructor +//! for a multi-field tuple variant when the enum has `#[standalone_constructors]` and all fields +//! within the variant have `#[arg_for_constructor]`. This file focuses on verifying the derive-based implementation. //! -//! ## Purpose: +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Verifies the generation of the top-level constructor function (`variant`). +//! - Rule 4b (Option 2 Logic): Verifies that when all fields in a multi-field tuple variant have `#[arg_for_constructor]`, the standalone constructor takes arguments for those fields and returns the final enum instance (scalar style). +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly relevant as `Variant` is a multi-field tuple variant. //! -//! - **Verify Standalone Direct Constructor Generation:** Ensure that `#[derive(Former)]` generates a standalone -//! constructor function (e.g., `enum_name::variant_name(T1, T2, ...) -> Enum`) for multi-field -//! tuple variants under `#[standalone_constructors]` when fields *are* marked with `#[arg_for_constructor]`. -//! - **Verify Argument Handling in Constructor:** Confirm that the generated constructor correctly -//! accepts arguments via `impl Into<...>` for each field marked with `#[arg_for_constructor]`. -//! - It uses the shared test logic from `tuple_multi_standalone_args_only_test.rs`. - -#[ allow( unused_imports ) ] -use ::former::prelude::*; -use ::former::Former; // Import derive macro +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a multi-field tuple variant `Variant(u32, String)`. +//! - Applies `#[derive(Former)]` and `#[standalone_constructors]` to the enum. +//! - Applies `#[arg_for_constructor]` to both fields within the `Variant` variant. +//! - Includes shared test logic from `tuple_multi_standalone_args_only_test.rs`. +//! - The included test calls the derived standalone constructor function `variant(value1, value2)` and asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that the standalone constructor is generated correctly as a scalar function when all fields have `#[arg_for_constructor]`. -// === Enum Definition === +use former::Former; -/// Enum using derive for #[standalone_constructors] with #[arg_for_constructor] on multi-field tuple variants. -#[ derive( Debug, PartialEq, Clone, Former ) ] -#[ standalone_constructors ] // Enable standalone constructors -// #[ debug ] // Uncomment to see generated code later -pub enum TestEnumMultiStandaloneArgs // Consistent name +#[ derive( Former, Debug, PartialEq ) ] +#[ former( standalone_constructors ) ] +pub enum TestEnum { - /// A multi-field tuple variant with #[standalone_constructors] and #[arg_for_constructor]. - VariantMultiStandaloneArgs // Consistent name - ( - #[ arg_for_constructor ] // Mark field as constructor arg - i32, - #[ arg_for_constructor ] // Mark field as constructor arg - bool, - ), + Variant( #[ arg_for_constructor ] u32, #[ arg_for_constructor ] String ), } -// === Include Test Logic === include!( "tuple_multi_standalone_args_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_manual.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_manual.rs index b9bfa61326..740b7b9c6f 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_manual.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_manual.rs @@ -1,44 +1,37 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_args_manual.rs - -//! # Manual Test: #[standalone_constructors] and #[arg_for_constructor] on Multi-Field Tuple Variants (Returns Self) -//! -//! This file provides a manual implementation of the standalone constructor that takes arguments -//! and returns Self for an enum (`TestEnumMultiStandaloneArgs`) with a multi-field tuple variant -//! (`VariantMultiStandaloneArgs(i32, bool)`), demonstrating the expected behavior under -//! `#[standalone_constructors]` with `#[arg_for_constructor]` on the fields. +//! Purpose: Provides a hand-written implementation of the `Former` pattern's standalone scalar constructor +//! for a multi-field tuple variant (`Variant(u32, String)`) within an enum that has +//! `#[standalone_constructors]` and fields with `#[arg_for_constructor]`. This file focuses on +//! demonstrating the manual implementation corresponding to the derived behavior. //! -//! ## Purpose: +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Manually implements the top-level constructor function (`variant`). +//! - Rule 4b (Option 2 Logic): Manually implements the logic for a scalar standalone constructor that takes arguments for all fields in a multi-field tuple variant. +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly relevant as `Variant` is a multi-field tuple variant. //! -//! - To serve as a reference implementation demonstrating how the standalone constructor should -//! behave for multi-field tuple variants when it takes arguments and returns Self. -//! - To manually implement the standalone constructor function (`variant_multi_standalone_args`). -//! - To validate the logic used by the `#[derive(Former)]` macro by comparing its generated -//! code's behavior against this manual implementation using the shared tests in -//! `tuple_multi_standalone_args_only_test.rs`. +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum with the `Variant(u32, String)` variant. +//! - Provides a hand-written `variant` function that takes `u32` and `String` as arguments and returns `TestEnum::Variant(u32, String)`. This mimics the behavior expected when `#[standalone_constructors]` is on the enum and `#[arg_for_constructor]` is on all fields of the variant. +//! - Includes shared test logic from `tuple_multi_standalone_args_only_test.rs`. +//! - The included test calls this manually implemented standalone constructor and asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies the manual implementation of the scalar standalone constructor with field arguments. -// use super::*; // Imports testing infrastructure - -// === Enum Definition === +// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_args_manual.rs -/// Enum for manual testing of #[standalone_constructors] with #[arg_for_constructor] on multi-field tuple variants. -#[ derive( Debug, PartialEq, Clone ) ] -pub enum TestEnumMultiStandaloneArgs // Consistent name +// Define the enum without the derive macro +#[ derive( Debug, PartialEq ) ] +pub enum TestEnum { - /// A multi-field tuple variant with #[standalone_constructors] and #[arg_for_constructor]. - VariantMultiStandaloneArgs( i32, bool ), // Multi-field tuple variant + Variant( u32, String ), } -// === Manual implementation of static methods on TestEnumMultiStandaloneArgs === -impl TestEnumMultiStandaloneArgs +// Manually implement the standalone constructor for the variant +impl TestEnum { - /// Manually implemented standalone constructor for the VariantMultiStandaloneArgs variant. - /// Takes arguments for fields marked with #[arg_for_constructor] and returns Self. + /// Manually implemented standalone constructor for the Variant variant (scalar style with args). #[ inline( always ) ] - pub fn variant_multi_standalone_args( field1 : impl Into< i32 >, field2 : impl Into< bool > ) -> Self + pub fn variant( value1 : u32, value2 : String ) -> Self { - Self::VariantMultiStandaloneArgs( field1.into(), field2.into() ) + Self::Variant( value1, value2 ) } } -// === Include the Test Logic === include!( "tuple_multi_standalone_args_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_only_test.rs index e391cbaf46..c0da5327cc 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_args_only_test.rs @@ -1,33 +1,35 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_args_only_test.rs +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of standalone scalar constructors for multi-field tuple variants with `#[arg_for_constructor]` +//! fields. It tests that standalone constructors generated/implemented when the enum has +//! `#[standalone_constructors]` and all variant fields have `#[arg_for_constructor]` behave as +//! expected (scalar style, taking field arguments). +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Tests the existence and functionality of the top-level constructor function (`variant`). +//! - Rule 4b (Option 2 Logic): Tests that the standalone constructor takes arguments corresponding to the `#[arg_for_constructor]` fields and returns the final enum instance. +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly tested via the `Variant` variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum structure with a multi-field tuple variant `Variant(u32, String)`. +//! - Contains a test function (`variant_test`) that is included by the derive and manual test files. +//! - Calls the standalone constructor function `variant(value1, value2)` provided by the including file. +//! - Asserts that the returned enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that both derived and manual standalone constructors correctly handle field arguments and produce the final enum variant. -/// # Test Logic: #[standalone_constructors] and #[arg_for_constructor] on Multi-Field Tuple Variants -/// -/// This file contains the core test logic for verifying the `Former` derive macro's -/// handling of enums where a multi-field tuple variant is marked with -/// `#[standalone_constructors]` (on the enum) and `#[arg_for_constructor]` -/// on the fields. -/// -/// ## Purpose: -/// -/// - **Verify Standalone Direct Constructor Generation:** Ensure that `#[derive(Former)]` generates a standalone -/// constructor function (e.g., `enum_name::variant_name(T1, T2, ...) -> Enum`) for multi-field -/// tuple variants under `#[standalone_constructors]` when fields *are* marked with `#[arg_for_constructor]`. -/// - **Verify Argument Handling in Constructor:** Confirm that the generated constructor correctly -/// accepts arguments via `impl Into<...>` for each field marked with `#[arg_for_constructor]`. -/// -/// This file is included via `include!` by both the `_manual.rs` and `_derive.rs` -/// test files for this scenario. - -// use super::*; // Imports items from the parent file (manual or derive) - -#[ test ] -fn multi_field_tuple_standalone_args_construction() +#[ cfg( test ) ] +mod tests { - // Tests the standalone constructor generated for a multi-field tuple variant - // `VariantMultiStandaloneArgs(i32, bool)` with #[standalone_constructors] and #[arg_for_constructor]. - // Expect a standalone constructor `TestEnumMultiStandaloneArgs::variant_multi_standalone_args(i32, bool)` returning Self. - let got = TestEnumMultiStandaloneArgs::variant_multi_standalone_args( 303, false ); + // use super::TestEnum; // Assuming TestEnum is available from the including file + + #[ test ] + fn variant_test() + { + // Test Matrix Row: T19.1 (Implicitly, as this tests the behavior expected by the matrix) + // Tests the standalone scalar constructor for Variant (multi field, #[arg_for_constructor] on all fields) + let value1 = 123; + let value2 = "abc".to_string(); + let got = variant( value1, value2.clone() ); // Call the standalone constructor - let expected = TestEnumMultiStandaloneArgs::VariantMultiStandaloneArgs( 303, false ); - assert_eq!( got, expected ); + let expected = TestEnum::Variant( value1, value2 ); + assert_eq!( got, expected ); + } } \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_derive.rs index 5085002a39..a87c6dd29b 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_derive.rs @@ -1,35 +1,25 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_derive.rs - -//! # Derive Test: #[standalone_constructors] on Multi-Field Tuple Variants (Returns Former) -//! -//! This test file verifies the `#[derive(Former)]` macro's handling of enums -//! where a multi-field tuple variant is marked with `#[standalone_constructors]` -//! (on the enum) but *without* `#[arg_for_constructor]` on the fields. +//! Purpose: Tests the `#[derive(Former)]` macro's generation of a standalone former builder for a multi-field tuple variant when the enum has `#[standalone_constructors]` and no fields within the variants have the `#[arg_for_constructor]` attribute. This file focuses on verifying the derive-based implementation. //! -//! ## Purpose: +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Verifies the generation of the top-level constructor function (`variant`). +//! - Rule 4b (Option 2 Logic): Verifies that when no fields in a multi-field tuple variant have `#[arg_for_constructor]`, the standalone constructor returns a former builder for the variant. +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly relevant as `Variant` is a multi-field tuple variant. //! -//! - **Verify Standalone Former Generation:** Ensure that `#[derive(Former)]` generates a standalone -//! constructor function (e.g., `enum_name::variant_name() -> VariantFormer<...>`) for multi-field -//! tuple variants under `#[standalone_constructors]` when fields are *not* marked with `#[arg_for_constructor]`. -//! - **Verify Setter Handling:** Confirm that the returned Former instance provides setters for each -//! field in the tuple. -//! - It uses the shared test logic from `tuple_multi_standalone_only_test.rs`. - -#[ allow( unused_imports ) ] -use ::former::prelude::*; -use ::former::Former; // Import derive macro +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `TestEnum` with a multi-field tuple variant `Variant(u32, String)`. +//! - Applies `#[derive(Former)]` and `#[standalone_constructors]` to the enum. +//! - No `#[arg_for_constructor]` attributes are applied to fields. +//! - Includes shared test logic from `tuple_multi_standalone_only_test.rs`. +//! - The included test calls the derived standalone constructor function `variant()`, uses the returned former builders' setters (`._0()`, `._1()`), and calls `.form()`. +//! - Asserts that the resulting enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that the standalone constructor is generated correctly as a former builder when no field arguments are specified. -// === Enum Definition === +use former::Former; -/// Enum using derive for #[standalone_constructors] on multi-field tuple variants. -#[ derive( Debug, PartialEq, Clone, Former ) ] -#[ standalone_constructors ] // Enable standalone constructors -// #[ debug ] // Uncomment to see generated code later -pub enum TestEnumMultiStandalone // Consistent name +#[ derive( Former, Debug, PartialEq ) ] +#[ former( standalone_constructors ) ] +pub enum TestEnum { - /// A multi-field tuple variant. - VariantMultiStandalone( i32, bool ), // Multi-field tuple variant (no #[arg_for_constructor]) + Variant( u32, String ), } -// === Include Test Logic === include!( "tuple_multi_standalone_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_manual.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_manual.rs index 71fac49a66..916e0584a9 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_manual.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_manual.rs @@ -1,207 +1,171 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_manual.rs - -//! # Manual Test: #[standalone_constructors] on Multi-Field Tuple Variants (Returns Former) -//! -//! This file provides a manual implementation of the standalone constructor that returns a Former -//! for an enum (`TestEnumMultiStandalone`) with a multi-field tuple variant (`VariantMultiStandalone(i32, bool)`), -//! demonstrating the expected behavior under `#[standalone_constructors]` without `#[arg_for_constructor]`. +//! Purpose: Provides a hand-written implementation of the `Former` pattern's standalone former builder +//! for a multi-field tuple variant (`Variant(u32, String)`) within an enum that has +//! `#[standalone_constructors]` and no fields with `#[arg_for_constructor]`. This file focuses on +//! demonstrating the manual implementation corresponding to the derived behavior. //! -//! ## Purpose: +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Manually implements the top-level constructor function (`variant`). +//! - Rule 4b (Option 2 Logic): Manually implements the logic for a standalone former builder that allows setting fields via setters (`._0()`, `._1()`) and calling `.form()`. +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly relevant as `Variant` is a multi-field tuple variant. //! -//! - To serve as a reference implementation demonstrating how the standalone constructor should -//! behave for multi-field tuple variants when it returns a Former instance. -//! - To manually implement the necessary Former infrastructure and the standalone constructor -//! function (`variant_multi_standalone`). -//! - To validate the logic used by the `#[derive(Former)]` macro by comparing its generated -//! code's behavior against this manual implementation using the shared tests in -//! `tuple_multi_standalone_only_test.rs`. - -#[ allow( unused_imports ) ] -use ::former::prelude::*; -#[ allow( unused_imports ) ] -use ::former_types:: -{ - Storage, StoragePreform, - FormerDefinitionTypes, FormerMutator, FormerDefinition, - FormingEnd, ReturnPreformed, +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum with the `Variant(u32, String)` variant. +//! - Provides a hand-written `variant` function that returns a former builder type (`TestEnumVariantFormer`). +//! - Implements the former builder type with setters (`._0()`, `._1()`) and a `form()` method that constructs and returns `TestEnum::Variant(u32, String)`. This mimics the behavior expected when `#[standalone_constructors]` is on the enum and no fields have `#[arg_for_constructor]`. +//! - Includes shared test logic from `tuple_multi_standalone_only_test.rs`. +//! - The included test calls the manually implemented standalone constructor `variant()`, uses the returned former builders' setters, and calls `.form()`. +//! - Asserts that the resulting enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies the manual implementation of the standalone former builder. + +// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_manual.rs + +use former::{ + FormingEnd, + StoragePreform, + FormerDefinition, + FormerDefinitionTypes, + Storage, + ReturnPreformed, + FormerBegin, + FormerMutator, }; use std::marker::PhantomData; -// === Enum Definition === - -/// Enum for manual testing of #[standalone_constructors] on multi-field tuple variants. -#[ derive( Debug, PartialEq, Clone ) ] -pub enum TestEnumMultiStandalone // Consistent name +// Define the enum without the derive macro +#[ derive( Debug, PartialEq ) ] +pub enum TestEnum { - /// A multi-field tuple variant. - VariantMultiStandalone( i32, bool ), // Multi-field tuple variant + Variant( u32, String ), } -// === Manual Former Implementation for VariantMultiStandalone === +// --- Manual Former Setup for Variant --- +pub struct TestEnumVariantFormerStorage +{ + field0 : Option< u32 >, + field1 : Option< String >, +} -// Storage -#[ derive( Debug, Default ) ] -pub struct TestEnumMultiStandaloneVariantFormerStorage +impl Default for TestEnumVariantFormerStorage { - pub _0 : ::core::option::Option< i32 >, - pub _1 : ::core::option::Option< bool >, + fn default() -> Self + { + Self { field0 : None, field1 : None } + } } -impl Storage for TestEnumMultiStandaloneVariantFormerStorage +impl Storage for TestEnumVariantFormerStorage { - type Preformed = ( i32, bool ); + type Preformed = ( u32, String ); } -impl StoragePreform for TestEnumMultiStandaloneVariantFormerStorage +impl StoragePreform for TestEnumVariantFormerStorage { - #[ inline( always ) ] fn preform( mut self ) -> Self::Preformed { - ( self._0.take().unwrap_or_default(), self._1.take().unwrap_or_default() ) + let field0 = self.field0.take().unwrap_or_default(); + let field1 = self.field1.take().unwrap_or_default(); + ( field0, field1 ) } } -// Definition Types -#[ derive( Debug, Default ) ] -pub struct TestEnumMultiStandaloneVariantFormerDefinitionTypes< Context = (), Formed = TestEnumMultiStandalone > +#[ derive( Default, Debug ) ] +pub struct TestEnumVariantFormerDefinitionTypes< C = (), F = TestEnum > { - _phantom : core::marker::PhantomData< ( Context, Formed ) >, + _p : PhantomData< ( C, F ) >, } -impl< Context, Formed > FormerDefinitionTypes -for TestEnumMultiStandaloneVariantFormerDefinitionTypes< Context, Formed > +impl< C, F > FormerDefinitionTypes for TestEnumVariantFormerDefinitionTypes< C, F > { - type Storage = TestEnumMultiStandaloneVariantFormerStorage; - type Formed = Formed; - type Context = Context; + type Storage = TestEnumVariantFormerStorage; + type Context = C; + type Formed = F; } -// Mutator -impl< Context, Formed > FormerMutator -for TestEnumMultiStandaloneVariantFormerDefinitionTypes< Context, Formed > -{ -} +impl< C, F > FormerMutator for TestEnumVariantFormerDefinitionTypes< C, F > {} -// Definition -#[ derive( Debug, Default ) ] -pub struct TestEnumMultiStandaloneVariantFormerDefinition -< Context = (), Formed = TestEnumMultiStandalone, End = TestEnumMultiStandaloneVariantEnd > +#[ derive( Default, Debug ) ] +pub struct TestEnumVariantFormerDefinition< C = (), F = TestEnum, E = TestEnumVariantEnd > { - _phantom : core::marker::PhantomData< ( Context, Formed, End ) >, + _p : PhantomData< ( C, F, E ) >, } -impl< Context, Formed, End > FormerDefinition -for TestEnumMultiStandaloneVariantFormerDefinition< Context, Formed, End > +impl< C, F, E > FormerDefinition for TestEnumVariantFormerDefinition< C, F, E > where - End : FormingEnd< TestEnumMultiStandaloneVariantFormerDefinitionTypes< Context, Formed > >, + E : FormingEnd< TestEnumVariantFormerDefinitionTypes< C, F > >, { - type Storage = TestEnumMultiStandaloneVariantFormerStorage; - type Formed = Formed; - type Context = Context; - type Types = TestEnumMultiStandaloneVariantFormerDefinitionTypes< Context, Formed >; - type End = End; + type Storage = TestEnumVariantFormerStorage; + type Context = C; + type Formed = F; + type Types = TestEnumVariantFormerDefinitionTypes< C, F >; + type End = E; } -// Former -#[ derive( Debug ) ] -pub struct TestEnumMultiStandaloneVariantFormer< Definition = TestEnumMultiStandaloneVariantFormerDefinition > +pub struct TestEnumVariantFormer< Definition = TestEnumVariantFormerDefinition > where - Definition : FormerDefinition< Storage = TestEnumMultiStandaloneVariantFormerStorage >, + Definition : FormerDefinition< Storage = TestEnumVariantFormerStorage >, { storage : Definition::Storage, context : Option< Definition::Context >, on_end : Option< Definition::End >, } -impl< Definition > TestEnumMultiStandaloneVariantFormer< Definition > +impl< Definition > TestEnumVariantFormer< Definition > where - Definition : FormerDefinition< Storage = TestEnumMultiStandaloneVariantFormerStorage >, - Definition::Types : FormerDefinitionTypes< Storage = TestEnumMultiStandaloneVariantFormerStorage >, - Definition::Types : FormerMutator, + Definition : FormerDefinition< Storage = TestEnumVariantFormerStorage >, { - #[ inline( always ) ] - pub fn form( self ) -> < Definition::Types as FormerDefinitionTypes >::Formed - { - self.end() - } - - #[ inline( always ) ] - pub fn end( mut self ) -> < Definition::Types as FormerDefinitionTypes >::Formed + #[ inline( always ) ] pub fn form( self ) -> < Definition::Types as FormerDefinitionTypes >::Formed { self.end() } + #[ inline( always ) ] pub fn end( mut self ) -> < Definition::Types as FormerDefinitionTypes >::Formed { let on_end = self.on_end.take().unwrap(); let context = self.context.take(); < Definition::Types as FormerMutator >::form_mutation( &mut self.storage, &mut self.context ); on_end.call( self.storage, context ) } - - #[ inline( always ) ] - pub fn begin - ( - storage : Option< Definition::Storage >, - context : Option< Definition::Context >, - on_end : Definition::End, - ) -> Self - { - Self { storage : storage.unwrap_or_default(), context, on_end : Some( on_end ) } - } - - #[ inline( always ) ] - #[allow(dead_code)] - pub fn new( on_end : Definition::End ) -> Self - { - Self::begin( None, None, on_end ) - } - - /// Setter for the first tuple field. - #[ inline ] - pub fn _0( mut self, src : impl Into< i32 > ) -> Self - { - debug_assert!( self.storage._0.is_none(), "Field '_0' was already set" ); - self.storage._0 = Some( src.into() ); - self - } - - /// Setter for the second tuple field. - #[ inline ] - pub fn _1( mut self, src : impl Into< bool > ) -> Self - { - debug_assert!( self.storage._1.is_none(), "Field '_1' was already set" ); - self.storage._1 = Some( src.into() ); - self - } + #[ inline( always ) ] pub fn begin + ( storage : Option< Definition::Storage >, context : Option< Definition::Context >, on_end : Definition::End ) -> Self + { Self { storage : storage.unwrap_or_default(), context, on_end : Some( on_end ) } } + #[ allow( dead_code ) ] + #[ inline( always ) ] pub fn new( on_end : Definition::End ) -> Self { Self::begin( None, None, on_end ) } + + // Setters for fields + #[ inline ] pub fn _0( mut self, src : impl Into< u32 > ) -> Self + { self.storage.field0 = Some( src.into() ); self } + #[ inline ] pub fn _1( mut self, src : impl Into< String > ) -> Self + { self.storage.field1 = Some( src.into() ); self } } -// End Struct for VariantMultiStandalone -#[ derive( Debug, Default ) ] -pub struct TestEnumMultiStandaloneVariantEnd; +#[ derive( Default, Debug ) ] +pub struct TestEnumVariantEnd +{ +} -impl FormingEnd< TestEnumMultiStandaloneVariantFormerDefinitionTypes< (), TestEnumMultiStandalone > > -for TestEnumMultiStandaloneVariantEnd +impl FormingEnd< TestEnumVariantFormerDefinitionTypes< (), TestEnum > > +for TestEnumVariantEnd { #[ inline( always ) ] fn call ( &self, - storage : TestEnumMultiStandaloneVariantFormerStorage, + sub_storage : TestEnumVariantFormerStorage, _context : Option< () >, - ) -> TestEnumMultiStandalone + ) + -> TestEnum { - let ( val0, val1 ) = storage.preform(); - TestEnumMultiStandalone::VariantMultiStandalone( val0, val1 ) + let ( field0, field1 ) = sub_storage.preform(); + TestEnum::Variant( field0, field1 ) } } +// --- End Manual Former Setup for Variant --- -// === Standalone Constructor (Manual) === -/// Manual standalone constructor for TestEnumMultiStandalone::VariantMultiStandalone. -/// Returns a Former instance for the variant. -pub fn variant_multi_standalone() --> -TestEnumMultiStandaloneVariantFormer< TestEnumMultiStandaloneVariantFormerDefinition< (), TestEnumMultiStandalone, TestEnumMultiStandaloneVariantEnd > > +// Manually implement the standalone constructor for the variant +impl TestEnum { - TestEnumMultiStandaloneVariantFormer::begin( None, None, TestEnumMultiStandaloneVariantEnd ) + /// Manually implemented standalone constructor for the Variant variant (former builder style). + #[ inline( always ) ] + pub fn variant() -> TestEnumVariantFormer + { + TestEnumVariantFormer::begin( None, None, TestEnumVariantEnd::default() ) + } } - -// === Include Test Logic === include!( "tuple_multi_standalone_only_test.rs" ); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_only_test.rs index af0f659610..ac32edba02 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_multi_standalone_only_test.rs @@ -1,36 +1,40 @@ -// File: module/core/former/tests/inc/former_enum_tests/tuple_multi_standalone_only_test.rs +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of standalone former builders for multi-field tuple variants without `#[arg_for_constructor]` +//! fields. It tests that standalone constructors generated/implemented when the enum has +//! `#[standalone_constructors]` and no variant fields have `#[arg_for_constructor]` behave as +//! expected (former builder style, allowing field setting via setters). +//! +//! Coverage: +//! - Rule 4a (#[standalone_constructors]): Tests the existence and functionality of the top-level constructor function (`variant`). +//! - Rule 4b (Option 2 Logic): Tests that the standalone constructor returns a former builder for the variant and that its fields can be set using setters (`._0()`, `._1()`). +//! - Rule 3f (Tuple + Multi-Field + Default): Implicitly tested via the `Variant` variant. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `TestEnum` enum structure with a multi-field tuple variant `Variant(u32, String)`. +//! - Contains a test function (`variant_test`) that is included by the derive and manual test files. +//! - Calls the standalone constructor function `variant()` provided by the including file. +//! - Uses the returned former builder's setters (`._0()`, `._1()`) to set the fields. +//! - Calls `.form()` on the former builder to get the final enum instance. +//! - Asserts that the resulting enum instance matches a manually constructed `TestEnum::Variant(value1, value2)`. This verifies that both derived and manual standalone constructors correctly return former builders and allow setting fields via setters. -/// # Test Logic: #[standalone_constructors] on Multi-Field Tuple Variants -/// -/// This file contains the core test logic for verifying the `Former` derive macro's -/// handling of enums where a multi-field tuple variant is marked with -/// `#[standalone_constructors]` (on the enum) but *without* `#[arg_for_constructor]` -/// on the fields. -/// -/// ## Purpose: -/// -/// - **Verify Standalone Former Generation:** Ensure that `#[derive(Former)]` generates a standalone -/// constructor function (e.g., `enum_name::variant_name() -> VariantFormer<...>`) for multi-field -/// tuple variants under `#[standalone_constructors]` when fields are *not* marked with `#[arg_for_constructor]`. -/// - **Verify Setter Handling:** Confirm that the returned Former instance provides setters for each -/// field in the tuple. -/// -/// This file is included via `include!` by both the `_manual.rs` and `_derive.rs` -/// test files for this scenario. - -// use super::*; // Imports items from the parent file (manual or derive) - -#[ test ] -fn multi_field_tuple_standalone_construction() +#[ cfg( test ) ] +mod tests { - // Tests the standalone constructor generated for a multi-field tuple variant - // `VariantMultiStandalone(i32, bool)` with #[standalone_constructors] but no #[arg_for_constructor]. - // Expect a standalone constructor `TestEnumMultiStandalone::variant_multi_standalone()` returning a Former. - let got = TestEnumMultiStandalone::variant_multi_standalone() - ._0( 101 ) - ._1( true ) - .form(); + // use super::TestEnum; // Assuming TestEnum is available from the including file + + #[ test ] + fn variant_test() + { + // Test Matrix Row: T20.1 (Implicitly, as this tests the behavior expected by the matrix) + // Tests the standalone former builder for Variant (multi field, no #[arg_for_constructor]) + let value1 = 123; + let value2 = "abc".to_string(); + let got = variant() // Call the standalone constructor + ._0( value1 ) // Use the setter for the first field + ._1( value2.clone() ) // Use the setter for the second field + .form(); // Form the final enum instance - let expected = TestEnumMultiStandalone::VariantMultiStandalone( 101, true ); - assert_eq!( got, expected ); + let expected = TestEnum::Variant( value1, value2 ); + assert_eq!( got, expected ); + } } \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_derive.rs index 18eebb9e1f..16c6720dce 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_derive.rs @@ -1,3 +1,17 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of constructors for zero-field tuple variants, covering both default behavior and the effect of the `#[scalar]` attribute. This file focuses on verifying the derive-based implementation. +//! +//! Coverage: +//! - Rule 3b (Tuple + Zero-Field + Default): Verifies the derived static method `EnumWithZeroFieldTuple::variant_zero_default()` returns the enum instance. +//! - Rule 1b (Tuple + Zero-Field + `#[scalar]`): Verifies the derived static method `EnumWithZeroFieldTuple::variant_zero_scalar()` returns the enum instance. +//! - Rule 4a (#[standalone_constructors]): Implicitly covered by the tests in `_only_test.rs` which include standalone constructor tests, although the `#[standalone_constructors]` attribute is not currently on the enum in this file. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `EnumWithZeroFieldTuple` with zero-field tuple variants `VariantZeroDefault` and `VariantZeroScalar`. +//! - Applies `#[derive(Former)]` to the enum. +//! - Applies `#[scalar]` to `VariantZeroScalar`. +//! - Includes shared test logic from `tuple_zero_fields_only_test.rs`. +//! - The included tests call the derived static methods (`variant_zero_default`, `variant_zero_scalar`) and standalone constructors (if enabled on the enum) and assert that the returned enum instances match the direct enum variants. This verifies the constructor generation for zero-field tuple variants. + use former::Former; use test_tools::exposed::*; use core::fmt::Debug; @@ -12,6 +26,7 @@ pub struct InnerForSubform // The enum under test for zero-field tuple variants with #[derive(Former)] #[ derive( Debug, PartialEq, Former ) ] +#[former(standalone_constructors, debug)] // Added standalone_constructors and debug // #[ derive( Default ) ] // Do not derive Default here, it caused issues before. pub enum EnumWithZeroFieldTuple { diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_manual.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_manual.rs index e77cbb23ce..5183b220b6 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_manual.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_manual.rs @@ -1,17 +1,59 @@ -#[ allow( unused_imports ) ] +//! Purpose: Provides a hand-written implementation of the `Former` pattern's static constructors +//! for zero-field tuple variants, demonstrating the manual implementation corresponding to both +//! default behavior and the effect of the `#[scalar]` attribute. +//! +//! Coverage: +//! - Rule 3b (Tuple + Zero-Field + Default): Manually implements the static method `EnumWithZeroFieldTuple::variant_zero_default()` to return the enum instance. +//! - Rule 1b (Tuple + Zero-Field + `#[scalar]`): Manually implements the static method `EnumWithZeroFieldTuple::variant_zero_scalar()` to return the enum instance. +//! - Rule 4a (#[standalone_constructors]): Manually implements standalone constructor functions (`enum_with_zero_field_tuple_variant_zero_default`, `enum_with_zero_field_tuple_variant_zero_scalar`) to return the enum instance, corresponding to the tests in `_only_test.rs`. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `EnumWithZeroFieldTuple` with zero-field tuple variants `VariantZeroDefault` and `VariantZeroScalar`. +//! - Provides hand-written static methods (`variant_zero_default`, `variant_zero_scalar`) and standalone functions (`enum_with_zero_field_tuple_variant_zero_default`, `enum_with_zero_field_tuple_variant_zero_scalar`) that mimic the behavior expected from the `#[derive(Former)]` macro for zero-field tuple variants. +//! - Includes shared test logic from `tuple_zero_fields_only_test.rs`. +//! - The included tests call these manually implemented methods/functions and assert that the returned enum instances match the direct enum variants. This verifies the manual implementation of constructors for zero-field tuple variants. + +#[allow(unused_imports)] use ::former::prelude::*; use test_tools::exposed::*; use core::fmt::Debug; use core::marker::PhantomData; -// Helper struct used in tests -#[ derive( Debug, PartialEq, Default ) ] -pub struct InnerForSubform -{ - pub value : i32, +// Helper struct used in tests (though not directly by this enum's variants) +#[derive(Debug, PartialEq, Default)] +pub struct InnerForSubform { + pub value: i32, +} + +// Define the enum without the derive macro +#[derive(Debug, PartialEq)] +pub enum EnumWithZeroFieldTuple { + VariantZeroDefault, + VariantZeroScalar, // Conceptually, this is the one that would have #[scalar] in derive } -// qqq : ... implement ... +impl EnumWithZeroFieldTuple { + #[inline(always)] + pub fn variant_zero_default() -> Self { + Self::VariantZeroDefault + } + + #[inline(always)] + pub fn variant_zero_scalar() -> Self { // Manual equivalent of scalar behavior + Self::VariantZeroScalar + } +} + +// Standalone constructors (matching derive macro output) +#[inline(always)] +pub fn variant_zero_default() -> EnumWithZeroFieldTuple { // Name matches derive output + EnumWithZeroFieldTuple::VariantZeroDefault +} + +#[inline(always)] +pub fn variant_zero_scalar() -> EnumWithZeroFieldTuple { // Name matches derive output + EnumWithZeroFieldTuple::VariantZeroScalar +} // Include the shared test logic -include!( "./tuple_zero_fields_only_test.rs" ); \ No newline at end of file +include!("./tuple_zero_fields_only_test.rs"); \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_only_test.rs index 3afaed2e82..82b3daf3f7 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/tuple_zero_fields_only_test.rs @@ -1,39 +1,33 @@ -// Test Matrix Row: T0.1 (Default, None) -#[ test ] -fn test_zero_field_default() -{ - use super::*; - let got = EnumWithZeroFieldTuple::variant_zero_default(); - let expected = EnumWithZeroFieldTuple::VariantZeroDefault; - assert_eq!( got, expected ); +// Purpose: Provides shared test assertions for zero-field tuple variants. +// Assumes the including file defines: +// 1. `EnumWithZeroFieldTuple` enum with `VariantZeroDefault` and `VariantZeroScalar`. +// 2. Static methods `variant_zero_default()` and `variant_zero_scalar()` on `EnumWithZeroFieldTuple`. +// 3. Standalone functions `standalone_variant_zero_default()` and `standalone_variant_zero_scalar()`. + +#[test] +fn test_zero_field_default_static_constructor() { + let got = EnumWithZeroFieldTuple::variant_zero_default(); + let expected = EnumWithZeroFieldTuple::VariantZeroDefault; + assert_eq!(got, expected); } -// Test Matrix Row: T0.2 (#[scalar], None) -#[ test ] -fn test_zero_field_scalar() -{ - use super::*; - let got = EnumWithZeroFieldTuple::variant_zero_scalar(); - let expected = EnumWithZeroFieldTuple::VariantZeroScalar; - assert_eq!( got, expected ); +#[test] +fn test_zero_field_scalar_static_constructor() { + let got = EnumWithZeroFieldTuple::variant_zero_scalar(); + let expected = EnumWithZeroFieldTuple::VariantZeroScalar; + assert_eq!(got, expected); } -// Test Matrix Row: T0.3 (Default, #[standalone_constructors]) -#[ test ] -fn test_zero_field_default_standalone() -{ - use super::*; - let got = standalone_variant_zero_default(); - let expected = EnumWithZeroFieldTuple::VariantZeroDefault; - assert_eq!( got, expected ); +#[test] +fn test_zero_field_default_standalone_constructor() { + let got = variant_zero_default(); // Name matches derive output + let expected = EnumWithZeroFieldTuple::VariantZeroDefault; + assert_eq!(got, expected); } -// Test Matrix Row: T0.4 (#[scalar], #[standalone_constructors]) -#[ test ] -fn test_zero_field_scalar_standalone() -{ - use super::*; - let got = standalone_variant_zero_scalar(); - let expected = EnumWithZeroFieldTuple::VariantZeroScalar; - assert_eq!( got, expected ); +#[test] +fn test_zero_field_scalar_standalone_constructor() { + let got = variant_zero_scalar(); // Name matches derive output + let expected = EnumWithZeroFieldTuple::VariantZeroScalar; + assert_eq!(got, expected); } \ No newline at end of file diff --git a/module/core/former/tests/inc/enum_unnamed_tests/usecase1.rs b/module/core/former/tests/inc/enum_unnamed_tests/usecase1.rs index a9d5b8d6b4..52b3779bf9 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/usecase1.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/usecase1.rs @@ -1,3 +1,20 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of subformer starter methods for an enum +//! with multiple single-field tuple variants, where the inner types also derive `Former`. This file +//! verifies that the default behavior for single-field tuple variants is to generate a subformer, +//! allowing nested building. +//! +//! Coverage: +//! - Rule 3d (Tuple + Single-Field + Default): Verifies that for single-field tuple variants without specific attributes, the derived constructor is a subformer starter method. +//! - Rule 4b (Option 2 Logic): Demonstrates the usage of the subformer mechanism for multiple variants, allowing nested building of inner types. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `FunctionStep` with multiple single-field tuple variants (`Prompt`, `Break`, `InstructionsApplyToFiles`, `Run`). +//! - The inner types (`Prompt`, `Break`, etc.) also derive `Former`. +//! - Applies `#[derive(Former)]` to the `FunctionStep` enum. +//! - Contains test functions that call the derived static methods (e.g., `FunctionStep::prompt()`, `FunctionStep::r#break()`). +//! - Uses the returned subformers to set fields of the inner types and calls `.form()` on the subformers to get the final `FunctionStep` enum instance. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the default behavior for single-field tuple variants is to generate subformer starters that correctly integrate with the inner types' formers. + use super::*; use former::Former; @@ -32,6 +49,7 @@ enum FunctionStep #[ test ] fn enum_variant_subformer_construction() { + // Test Matrix Row: T22.1 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Prompt variant using the generated subformer starter let prompt_step = FunctionStep::prompt() // Expects subformer starter .content( "Explain the code." ) @@ -39,6 +57,7 @@ fn enum_variant_subformer_construction() let expected_prompt = FunctionStep::Prompt( Prompt { content: "Explain the code.".to_string() } ); assert_eq!( prompt_step, expected_prompt ); + // Test Matrix Row: T22.2 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Break variant using the generated subformer starter let break_step = FunctionStep::r#break() // Expects subformer starter (using raw identifier) .condition( true ) @@ -46,6 +65,7 @@ fn enum_variant_subformer_construction() let expected_break = FunctionStep::Break( Break { condition: true } ); assert_eq!( break_step, expected_break ); + // Test Matrix Row: T22.3 (Implicitly, as this tests the behavior expected by the matrix) // Construct the InstructionsApplyToFiles variant using the generated subformer starter let apply_step = FunctionStep::instructions_apply_to_files() // Expects subformer starter .instruction( "Apply formatting." ) @@ -53,6 +73,7 @@ fn enum_variant_subformer_construction() let expected_apply = FunctionStep::InstructionsApplyToFiles( InstructionsApplyToFiles { instruction: "Apply formatting.".to_string() } ); assert_eq!( apply_step, expected_apply ); + // Test Matrix Row: T22.4 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Run variant using the generated subformer starter let run_step = FunctionStep::run() // Expects subformer starter .command( "cargo check" ) @@ -66,6 +87,7 @@ fn enum_variant_subformer_construction() #[ test ] fn enum_variant_manual_construction() { + // Test Matrix Row: T22.5 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Prompt variant let prompt_step = FunctionStep::Prompt ( @@ -76,6 +98,7 @@ fn enum_variant_manual_construction() let expected_prompt = FunctionStep::Prompt( Prompt { content: "Explain the code.".to_string() } ); assert_eq!( prompt_step, expected_prompt ); + // Test Matrix Row: T22.6 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Break variant let break_step = FunctionStep::Break ( @@ -86,6 +109,7 @@ fn enum_variant_manual_construction() let expected_break = FunctionStep::Break( Break { condition: true } ); assert_eq!( break_step, expected_break ); + // Test Matrix Row: T22.7 (Implicitly, as this tests the behavior expected by the matrix) // Construct the InstructionsApplyToFiles variant let apply_step = FunctionStep::InstructionsApplyToFiles ( @@ -96,6 +120,7 @@ fn enum_variant_manual_construction() let expected_apply = FunctionStep::InstructionsApplyToFiles( InstructionsApplyToFiles { instruction: "Apply formatting.".to_string() } ); assert_eq!( apply_step, expected_apply ); + // Test Matrix Row: T22.8 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Run variant let run_step = FunctionStep::Run ( diff --git a/module/core/former/tests/inc/enum_unnamed_tests/usecase1_derive.rs b/module/core/former/tests/inc/enum_unnamed_tests/usecase1_derive.rs index 0b6230c738..82434c16a4 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/usecase1_derive.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/usecase1_derive.rs @@ -1,3 +1,19 @@ +//! Purpose: Tests the `#[derive(Former)]` macro's generation of subformer starter methods for an enum +//! with multiple single-field tuple variants, where the inner types also derive `Former`. This file +//! focuses on verifying the derive-based implementation. +//! +//! Coverage: +//! - Rule 3d (Tuple + Single-Field + Default): Verifies that for single-field tuple variants without specific attributes, the derived constructor is a subformer starter method. +//! - Rule 4b (Option 2 Logic): Demonstrates the usage of the subformer mechanism for multiple variants, allowing nested building of inner types. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `FunctionStep` with multiple single-field tuple variants (`Prompt`, `Break`, `InstructionsApplyToFiles`, `Run`). +//! - The inner types (`Prompt`, `Break`, etc.) also derive `Former`. +//! - Applies `#[derive(Former)]` to the `FunctionStep` enum. +//! - Includes shared test logic from `usecase1_only_test.rs`. +//! - The included tests call the derived static methods (e.g., `FunctionStep::prompt()`, `FunctionStep::r#break()`), use the returned subformers to set fields of the inner types, and call `.form()` on the subformers to get the final `FunctionStep` enum instance. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the derived subformer starters correctly integrate with the inner types' formers. + use super::*; use former::Former; diff --git a/module/core/former/tests/inc/enum_unnamed_tests/usecase1_manual.rs b/module/core/former/tests/inc/enum_unnamed_tests/usecase1_manual.rs index 7b4d6f5a96..f379bc2549 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/usecase1_manual.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/usecase1_manual.rs @@ -1,3 +1,22 @@ +//! Purpose: Provides a hand-written implementation of the `Former` pattern's subformer starter methods +//! for an enum with multiple single-field tuple variants, where the inner types also derive `Former`. +//! This file demonstrates the manual implementation corresponding to the derived behavior, showing how +//! to manually create the starter methods and the `FormerEnd` implementations to allow nested building. +//! +//! Coverage: +//! - Rule 3d (Tuple + Single-Field + Default): Manually implements the subformer starter methods for single-field tuple variants. +//! - Rule 4b (Option 2 Logic): Manually implements the `FormerEnd` trait for `ReturnContainer` for each inner type, allowing the inner formers to return the outer enum instance. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines an enum `FunctionStep` with multiple single-field tuple variants (`Prompt`, `Break`, `InstructionsApplyToFiles`, `Run`). +//! - The inner types (`Prompt`, `Break`, etc.) also derive `Former`. +//! - Provides a hand-written `FunctionStepFormer` struct and implements `former::Former` for `FunctionStep` to return it. +//! - Implements methods on `FunctionStepFormer` (e.g., `prompt()`, `r#break()`) that return formers for the inner types, configured with `ReturnContainer` as the end type. +//! - Implements `FormerEnd` for `ReturnContainer` for each inner type, defining how to construct the `FunctionStep` variant from the formed inner type. +//! - Includes shared test logic from `usecase1_only_test.rs`. +//! - The included tests call the manually implemented static methods (e.g., `FunctionStep::prompt()`), use the returned subformers to set fields of the inner types, and call `.form()` on the subformers. +//! - Asserts that the resulting enum instances match manually constructed expected values. This verifies that the manual implementation correctly provides subformer starters and integrates with the inner types' formers. + use super::*; use former::Former; use former::FormerEnd; // Import necessary traits diff --git a/module/core/former/tests/inc/enum_unnamed_tests/usecase1_only_test.rs b/module/core/former/tests/inc/enum_unnamed_tests/usecase1_only_test.rs index 56759b3268..44f55985c9 100644 --- a/module/core/former/tests/inc/enum_unnamed_tests/usecase1_only_test.rs +++ b/module/core/former/tests/inc/enum_unnamed_tests/usecase1_only_test.rs @@ -1,7 +1,25 @@ +//! Purpose: Provides shared test assertions and logic for both the derived and manual implementations +//! of subformer starter methods for an enum with multiple single-field tuple variants, where the +//! inner types also derive `Former`. It tests that the constructors generated/implemented for this +//! scenario behave as expected (returning subformers for nested building). +//! +//! Coverage: +//! - Rule 3d (Tuple + Single-Field + Default): Tests that the constructor for single-field tuple variants without specific attributes is a subformer starter method. +//! - Rule 4b (Option 2 Logic): Tests that the subformer mechanism works correctly for multiple variants, allowing nested building of inner types and returning the outer enum instance via `.form()`. +//! +//! Test Relevance/Acceptance Criteria: +//! - Defines the `FunctionStep` enum structure with multiple single-field tuple variants (`Prompt`, `Break`, `InstructionsApplyToFiles`, `Run`). +//! - The inner types (`Prompt`, `Break`, etc.) are assumed to also derive `Former`. +//! - Contains test functions (`enum_variant_subformer_construction`, `enum_variant_manual_construction`) that are included by the derive and manual test files. +//! - The `enum_variant_subformer_construction` test calls the static methods (e.g., `FunctionStep::prompt()`, `FunctionStep::r#break()`) provided by the including file, uses the returned subformers to set fields, and calls `.form()`. +//! - The `enum_variant_manual_construction` test demonstrates the equivalent manual construction using `InnerType::former()...form()`. +//! - Both tests assert that the resulting enum instances match manually constructed expected values. This verifies that both derived and manual implementations correctly provide subformer starters and integrate with the inner types' formers for nested building. + // Renamed test to reflect its purpose: testing the subformer construction #[ test ] fn enum_variant_subformer_construction() { + // Test Matrix Row: T22.1 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Prompt variant using the generated subformer starter let prompt_step = FunctionStep::prompt() // Expects subformer starter .content( "Explain the code." ) @@ -9,6 +27,7 @@ fn enum_variant_subformer_construction() let expected_prompt = FunctionStep::Prompt( Prompt { content: "Explain the code.".to_string() } ); assert_eq!( prompt_step, expected_prompt ); + // Test Matrix Row: T22.2 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Break variant using the generated subformer starter let break_step = FunctionStep::r#break() // Expects subformer starter (using raw identifier) .condition( true ) @@ -16,6 +35,7 @@ fn enum_variant_subformer_construction() let expected_break = FunctionStep::Break( Break { condition: true } ); assert_eq!( break_step, expected_break ); + // Test Matrix Row: T22.3 (Implicitly, as this tests the behavior expected by the matrix) // Construct the InstructionsApplyToFiles variant using the generated subformer starter let apply_step = FunctionStep::instructions_apply_to_files() // Expects subformer starter .instruction( "Apply formatting." ) @@ -23,6 +43,7 @@ fn enum_variant_subformer_construction() let expected_apply = FunctionStep::InstructionsApplyToFiles( InstructionsApplyToFiles { instruction: "Apply formatting.".to_string() } ); assert_eq!( apply_step, expected_apply ); + // Test Matrix Row: T22.4 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Run variant using the generated subformer starter let run_step = FunctionStep::run() // Expects subformer starter .command( "cargo check" ) @@ -36,6 +57,7 @@ fn enum_variant_subformer_construction() #[ test ] fn enum_variant_manual_construction() { + // Test Matrix Row: T22.5 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Prompt variant let prompt_step = FunctionStep::Prompt ( @@ -46,6 +68,7 @@ fn enum_variant_manual_construction() let expected_prompt = FunctionStep::Prompt( Prompt { content: "Explain the code.".to_string() } ); assert_eq!( prompt_step, expected_prompt ); + // Test Matrix Row: T22.6 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Break variant let break_step = FunctionStep::Break ( @@ -56,6 +79,7 @@ fn enum_variant_manual_construction() let expected_break = FunctionStep::Break( Break { condition: true } ); assert_eq!( break_step, expected_break ); + // Test Matrix Row: T22.7 (Implicitly, as this tests the behavior expected by the matrix) // Construct the InstructionsApplyToFiles variant let apply_step = FunctionStep::InstructionsApplyToFiles ( @@ -66,6 +90,7 @@ fn enum_variant_manual_construction() let expected_apply = FunctionStep::InstructionsApplyToFiles( InstructionsApplyToFiles { instruction: "Apply formatting.".to_string() } ); assert_eq!( apply_step, expected_apply ); + // Test Matrix Row: T22.8 (Implicitly, as this tests the behavior expected by the matrix) // Construct the Run variant let run_step = FunctionStep::Run ( @@ -75,4 +100,5 @@ fn enum_variant_manual_construction() ); let expected_run = FunctionStep::Run( Run { command: "cargo check".to_string() } ); assert_eq!( run_step, expected_run ); -} \ No newline at end of file +} +// qqq : xxx : uncomment and make it working \ No newline at end of file diff --git a/module/core/former/tests/inc/mod.rs b/module/core/former/tests/inc/mod.rs index e8d43a933f..2109b1dac8 100644 --- a/module/core/former/tests/inc/mod.rs +++ b/module/core/former/tests/inc/mod.rs @@ -5,11 +5,24 @@ use test_tools::exposed::*; #[ cfg( feature = "derive_former" ) ] mod struct_tests; +// Tests for enum variants. +// These are categorized by the kind of variant fields. + #[ cfg( feature = "derive_former" ) ] +/// Tests for true unit variants (e.g., `Variant`). pub mod enum_unit_tests; + #[ cfg( feature = "derive_former" ) ] +/// Tests for enum variants with unnamed (tuple) fields (e.g., `Variant(i32)`, `Variant()`). +/// Includes zero-field tuple variants. pub mod enum_unnamed_tests; + #[ cfg( feature = "derive_former" ) ] +/// Tests for enum variants with named (struct-like) fields (e.g., `Variant { val: i32 }`). +/// Includes zero-field struct variants. pub mod enum_named_tests; + #[ cfg( feature = "derive_former" ) ] +/// Tests for complex enum scenarios, combinations of features, or advanced use cases +/// not fitting neatly into unit/unnamed/named categories. pub mod enum_complex_tests; diff --git a/module/core/former_meta/Cargo.toml b/module/core/former_meta/Cargo.toml index 28baaad9cf..3eff0d819d 100644 --- a/module/core/former_meta/Cargo.toml +++ b/module/core/former_meta/Cargo.toml @@ -51,6 +51,7 @@ derive_former = [ "convert_case" ] # derive_from_components = [] proc-macro-debug = [ "macro_tools/diag" ] # Added proc-macro-debug feature +former_diagnostics_print_generated = [] [dependencies] macro_tools = { workspace = true, features = [ "attr", "attr_prop", "ct", "item_struct", "container_kind", "diag", "phantom", "generic_params", "generic_args", "typ", "derive", "ident" ] } # qqq : zzz : optimize set of features diff --git a/module/core/former_meta/src/derive_former.rs b/module/core/former_meta/src/derive_former.rs index 3921e8dabf..c8f9a926db 100644 --- a/module/core/former_meta/src/derive_former.rs +++ b/module/core/former_meta/src/derive_former.rs @@ -3,7 +3,7 @@ use super::*; use macro_tools:: { - attr, diag, typ, Result, + diag, typ, Result, proc_macro2::TokenStream, quote::{ format_ident, quote }, syn::spanned::Spanned, }; @@ -28,8 +28,8 @@ use struct_attrs::*; #[ allow( clippy::format_in_format_args, clippy::unnecessary_wraps ) ] pub fn mutator ( - item : &syn::Ident, - original_input : ¯o_tools::proc_macro2::TokenStream, + _item : &syn::Ident, // Prefixed as it's only used when former_diagnostics_print_generated is active + _original_input : ¯o_tools::proc_macro2::TokenStream, // Prefixed mutator : &AttributeMutator, former_definition_types : &syn::Ident, former_definition_types_generics_impl : &syn::punctuated::Punctuated< syn::GenericParam, syn::token::Comma >, @@ -57,10 +57,13 @@ pub fn mutator } }; - // If debug is enabled for the mutator attribute, print a helpful example. + // If debug is enabled for the mutator attribute, print a helpful example, + // but only if the `former_diagnostics_print_generated` feature is enabled. if mutator.debug.value( false ) { - let debug = format! + #[cfg(feature = "former_diagnostics_print_generated")] + { + let debug = format! ( r" = Example of custom mutator @@ -89,10 +92,11 @@ where ); let about = format! ( -r"derive : Former -item : {item}", - ); - diag::report_print( about, original_input, debug ); + r"derive : Former + item : {_item}", // Use prefixed name + ); + diag::report_print( about, _original_input, debug ); // Use prefixed name + } } Ok( former_mutator_code ) @@ -130,18 +134,24 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > { let original_input : TokenStream = input.clone().into(); let ast = syn::parse::< syn::DeriveInput >( input )?; - let has_debug = attr::has_debug( ast.attrs.iter() )?; + + // Parse ItemAttributes ONCE here from all attributes on the item + let item_attributes = struct_attrs::ItemAttributes::from_attrs( ast.attrs.iter() )?; + // Determine has_debug based on the parsed item_attributes + let has_debug = item_attributes.debug.is_some(); // Dispatch based on whether the input is a struct, enum, or union. let result = match ast.data { syn::Data::Struct( ref data_struct ) => { - former_for_struct( &ast, data_struct, &original_input, has_debug ) + // Pass the parsed item_attributes and the correctly determined has_debug + former_for_struct( &ast, data_struct, &original_input, &item_attributes, has_debug ) }, syn::Data::Enum( ref data_enum ) => { - former_for_enum( &ast, data_enum, &original_input, has_debug ) + // Pass the parsed item_attributes and the correctly determined has_debug + former_for_enum( &ast, data_enum, &original_input, &item_attributes, has_debug ) }, syn::Data::Union( _ ) => { @@ -150,11 +160,15 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > } }?; - // If the top-level `#[debug]` attribute was found, print the final generated code. + // If the top-level `#[debug]` attribute was found, print the final generated code, + // but only if the `former_diagnostics_print_generated` feature is enabled. if has_debug { - let about = format!( "derive : Former\nstructure : {}", ast.ident ); - diag::report_print( about, &original_input, &result ); + #[cfg(feature = "former_diagnostics_print_generated")] + { + let about = format!( "derive : Former\nstructure : {}", ast.ident ); + diag::report_print( about, &original_input, &result ); + } } Ok( result ) diff --git a/module/core/former_meta/src/derive_former/former_enum.rs b/module/core/former_meta/src/derive_former/former_enum.rs index 598a723255..c9ef2bcd9c 100644 --- a/module/core/former_meta/src/derive_former/former_enum.rs +++ b/module/core/former_meta/src/derive_former/former_enum.rs @@ -154,15 +154,24 @@ pub(super) fn former_for_enum ast : &syn::DeriveInput, data_enum : &syn::DataEnum, original_input : &TokenStream, + item_attributes : &ItemAttributes, // Changed: Accept parsed ItemAttributes has_debug : bool ) -> Result< TokenStream > { let enum_name = &ast.ident; let vis = &ast.vis; let generics = &ast.generics; - let struct_attrs = ItemAttributes::from_attrs( ast.attrs.iter() )?; + // let struct_attrs = ItemAttributes::from_attrs( ast.attrs.iter() )?; // REMOVED: Use passed item_attributes + let struct_attrs = item_attributes; // Use the passed-in item_attributes // qqq : Ensure ItemAttributes and FieldAttributes are accessible/imported + // Diagnostic print for has_debug status (has_debug is now correctly determined by the caller) + if has_debug { + diag::report_print("DEBUG former_for_enum: has_debug is TRUE at start (passed in).", original_input, "e!{ struct DebugFlagWasTrue; }); + } else { + diag::report_print("DEBUG former_for_enum: has_debug is FALSE at start (passed in).", original_input, "e!{ struct DebugFlagWasFalse; }); + } + let mut methods = Vec::new(); let mut end_impls = Vec::new(); let mut standalone_constructors = Vec::new(); @@ -314,8 +323,8 @@ pub(super) fn former_for_enum } // Standalone constructors and end impls should be placed here, outside the impl block. - // #( #standalone_constructors )* - // #( #end_impls )* + #( #standalone_constructors )* + #( #end_impls )* // Uncommented to emit VariantFormer definitions }; if has_debug diff --git a/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs b/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs index f80b2e7b80..397b34d2d9 100644 --- a/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs +++ b/module/core/former_meta/src/derive_former/former_enum/struct_single_field_subform.rs @@ -14,53 +14,105 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< let variant_ident = &ctx.variant.ident; let enum_ident = &ctx.enum_name; - let vis = &ctx.vis; // Get visibility + let vis = &ctx.vis; - // Get the single field's type and identifier - let field = 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.") + // 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); + + // 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! {}, + }; + + // 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_ident = &field.ident; - let _field_ty = &field.ty; + 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 - let variant_former_name = format_ident!("{}{}Former", enum_ident, variant_ident); + // 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 > } + }; - // Convert variant identifier to snake_case for the method name using convert_case - let method_ident_string = variant_ident.to_string().to_case( Case::Snake ); - let method_ident = syn::Ident::new( &method_ident_string, variant_ident.span() ); // Create new Ident with correct span + // 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()) + } + } + }; // Generate the static method: Enum::variant_name() -> VariantFormer<...> + // Signature needs to be generic if the enum is generic. + // The return type `Self` for the static method is not correct here, it should be the VariantFormer type. let generated_method = quote! { #[ inline( always ) ] - pub fn #method_ident() -> #variant_former_name // Return type is the implicit variant former + pub fn #method_ident () -> #variant_former_name_generic // Return type is the implicit variant former { - #variant_former_name::default() // Assuming the implicit former has a default constructor - // qqq : Need to handle cases where the implicit former doesn't have Default + #variant_former_name_generic::default() } }; - let mut generated_tokens = generated_method; - - // Generate standalone constructor if #[standalone_constructors] is present on the enum + // Generate standalone constructor if #[standalone_constructors] is present if ctx.struct_attrs.standalone_constructors.is_some() { + let fn_signature_generics = if ctx.generics.params.is_empty() { quote!{} } else { quote!{ < #impl_generics > } }; + // Standalone constructor also returns the VariantFormer let generated_standalone = quote! { #[ inline( always ) ] - #vis fn #method_ident() -> #variant_former_name // Return type is the implicit variant former + #vis fn #method_ident #fn_signature_generics () -> #variant_former_name_generic + #top_level_where_clause // Use the correctly formed where clause { - #variant_former_name::default() // Assuming the implicit former has a default constructor - // qqq : Need to handle cases where the implicit former doesn't have Default + #variant_former_name_generic::default() } }; - generated_tokens.extend(generated_standalone); + ctx.standalone_constructors.push(generated_standalone); } - // qqq : Need to generate the implicit variant former struct and its impl block. - // This will likely involve using common_emitters or dedicated logic here. - // For now, just returning the method/constructor tokens. + // Generate a MINIMAL definition for the implicit VariantFormer struct + // This is NOT a full Former implementation, just enough to resolve type errors. + let former_fields_def = quote! { pub #field_name_original : #field_ty }; + // let former_fields_init = quote! { #field_name_original : Default::default() }; // Unused, commented out + + let variant_former_def = quote! + { + #[derive(Debug, Default)] // Add Default for .default() call + #vis struct #variant_former_ident< #impl_generics > // Make former struct generic + #top_level_where_clause // Use the correctly formed where clause + { + #former_fields_def, + // If T is a parameter, PhantomData might be needed if T is not used in fields + // For MixedEnum { Complex { data: i32 } }, T is not used, so no PhantomData needed for this specific case. + // If Complex was Complex { data: T }, then PhantomData might be needed if T is not Default. + } + // Basic impl to satisfy construction, not a full Former impl + // impl< #impl_generics > #variant_former_name_generic // This would be for impl Former + // #where_clause + // { + // // pub fn new() -> Self { Self { #former_fields_init } } // Example constructor + // } + }; + ctx.end_impls.push(variant_former_def); // Add to end_impls to be emitted at top level - Ok( generated_tokens ) + Ok( generated_method ) // Return only the static method for the main impl block } \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs index ace1bcbd93..42c06c1dcc 100644 --- a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs +++ b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_scalar.rs @@ -15,7 +15,17 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< let variant_ident = &ctx.variant.ident; let enum_ident = &ctx.enum_name; - let vis = &ctx.vis; // Get visibility + let vis = &ctx.vis; + + // 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); + + // Use merged_where_clause from the context for the standalone constructor's where clause + let where_clause = match ctx.merged_where_clause { + Some(clause) => quote! { #clause }, // clause is &WhereClause here + None => quote! {}, + }; // Get the single field's type and identifier let field = ctx.variant_field_info.get(0).ok_or_else(|| { @@ -24,39 +34,61 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< let field_ty = &field.ty; let field_ident = &field.ident; // Use the generated identifier like _0 - // Convert variant identifier to snake_case for the method name using convert_case - let method_ident_string = variant_ident.to_string().to_case( Case::Snake ); - let method_ident = syn::Ident::new( &method_ident_string, variant_ident.span() ); // Create new Ident with correct span + // Correctly create method_ident, handling raw identifiers + let method_ident = { + let name_str = variant_ident.to_string(); + 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 constructor method: Enum::variant_name(FieldType) -> Enum + // Static method: pub fn method_name(field: impl Into) -> Self + // `Self` correctly refers to `EnumName` within the impl block let generated_method = quote! { #[ inline( always ) ] - pub fn #method_ident( #field_ident : impl Into< #field_ty > ) -> #enum_ident + pub fn #method_ident( #field_ident : impl Into< #field_ty > ) -> Self { - #enum_ident::#variant_ident( #field_ident.into() ) + Self::#variant_ident( #field_ident.into() ) } }; - let mut generated_tokens = generated_method; - - // Generate standalone constructor if #[standalone_constructors] is present on the enum + // Standalone constructor if ctx.struct_attrs.standalone_constructors.is_some() { + 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 > } }; + // enum_path_for_construction is not strictly needed here as we use #enum_ident #return_type_generics for return + // and #enum_ident::#variant_ident for construction path (generics inferred or explicit on #enum_ident if needed by context) + let generated_standalone = quote! { #[ inline( always ) ] - #vis fn #method_ident( #field_ident : impl Into< #field_ty > ) -> #enum_ident + #vis fn #method_ident #fn_signature_generics ( #field_ident : impl Into< #field_ty > ) -> #enum_ident #return_type_generics + #where_clause { - #enum_ident::#variant_ident( #field_ident.into() ) + #enum_ident::#variant_ident( #field_ident.into() ) // Generics for #enum_ident will be inferred by return type or must be specified if ambiguous } }; - generated_tokens.extend(generated_standalone); + // Instead of generated_tokens.extend(), push to ctx.standalone_constructors + ctx.standalone_constructors.push(generated_standalone); } + // This handler only returns the static method. Standalone constructors are collected in ctx. + // let mut generated_tokens = generated_method; // Not needed anymore + // qqq : Consider using common_emitters::generate_direct_constructor_for_variant // This handler's logic is simple enough that direct generation is fine for now. // If more complex direct constructors are needed, refactor into common_emitters. - Ok( generated_tokens ) + Ok( generated_method ) // Return only the static method tokens } \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs index 5c27a0de01..b17fb0773f 100644 --- a/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs +++ b/module/core/former_meta/src/derive_former/former_enum/tuple_single_field_subform.rs @@ -22,44 +22,75 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< })?; let field_ty = &field.ty; - // Check if the field type is a path (e.g., MyStruct) and derives Former - // qqq : Need a way to check if a type derives Former. This might require - // inspecting the type's definition or relying on a helper from macro_tools. - // For now, assume the type is a path and generate the former name. - // A proper check should be added here later. + 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 inner_former_name = quote!{ #field_ty::Former }; // Assuming Former is derived and accessible - - // Convert variant identifier to snake_case for the method name using convert_case let method_ident_string = variant_ident.to_string().to_case( Case::Snake ); - let method_ident = syn::Ident::new( &method_ident_string, variant_ident.span() ); // Create new Ident with correct span + let method_ident = syn::Ident::new( &method_ident_string, variant_ident.span() ); + + let mut generated_tokens = TokenStream::new(); - // Generate the static method: Enum::variant_name() -> InnerFormer<...> - let generated_method = quote! - { - #[ inline( always ) ] - pub fn #method_ident() -> #inner_former_name // Return type is the inner former - { - #inner_former_name::default() // Assuming the inner former has a default constructor - // qqq : Need to handle cases where the inner former doesn't have Default - } - }; + if is_phantom_data_field { + // If the field is PhantomData, generate a scalar-like constructor for the variant. + // Enum::variant_name() -> Self { Self::VariantName(core::marker::PhantomData) } + let variant_construction = quote! { Self::#variant_ident(core::marker::PhantomData) }; + let generated_method = quote! + { + #[ inline( always ) ] + #vis fn #method_ident() -> Self + { + #variant_construction + } + }; + generated_tokens.extend(generated_method); - let mut generated_tokens = generated_method; + if ctx.struct_attrs.standalone_constructors.is_some() { + let ( impl_generics, ty_generics, where_clause ) = ctx.generics.split_for_impl(); // Renamed back to ty_generics + let enum_name_ident = ctx.enum_name; + let standalone_constructor_name = format_ident!( "{}_{}", enum_name_ident.to_string().to_case( Case::Snake ), method_ident ); - // Generate standalone constructor if #[standalone_constructors] is present on the enum - if ctx.struct_attrs.standalone_constructors.is_some() - { - let generated_standalone = quote! - { - #[ inline( always ) ] - #vis fn #method_ident() -> #inner_former_name // Return type is the inner former + let generated_standalone = quote! + { + #[ inline( always ) ] + #vis fn #standalone_constructor_name #impl_generics () -> #enum_name_ident #ty_generics #where_clause + { + #enum_name_ident :: #variant_ident ( core::marker::PhantomData ) + } + }; + generated_tokens.extend(generated_standalone); + } + } else { + // Original logic for non-PhantomData fields + let inner_former_name = quote!{ #field_ty::Former }; + + let generated_method = quote! { - #inner_former_name::default() // Assuming the inner former has a default constructor - // qqq : Need to handle cases where the inner former doesn't have Default + #[ inline( always ) ] + #vis fn #method_ident() -> #inner_former_name + { + #inner_former_name::default() + } + }; + generated_tokens.extend(generated_method); + + if ctx.struct_attrs.standalone_constructors.is_some() { + let ( impl_generics, _ty_generics, where_clause ) = ctx.generics.split_for_impl(); // Prefixed _ty_generics as it's not used in -> #inner_former_name + let enum_name_ident = ctx.enum_name; + // For standalone, the method name is typically just the snake_case variant name if not prefixed by enum + // However, the original code used #method_ident for standalone too. + // Let's make it consistent with the PhantomData case for naming. + let standalone_constructor_name = format_ident!( "{}_{}", enum_name_ident.to_string().to_case( Case::Snake ), method_ident ); + + let generated_standalone = quote! + { + #[ inline( always ) ] + #vis fn #standalone_constructor_name #impl_generics () -> #inner_former_name #where_clause // Standalone returns InnerFormer + { + #inner_former_name::default() + } + }; + generated_tokens.extend(generated_standalone); } - }; - generated_tokens.extend(generated_standalone); } Ok( generated_tokens ) diff --git a/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs b/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs index 944954554f..927b6df7d0 100644 --- a/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs +++ b/module/core/former_meta/src/derive_former/former_enum/tuple_zero_fields_handler.rs @@ -20,38 +20,72 @@ pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< let variant_ident = &ctx.variant.ident; let enum_ident = &ctx.enum_name; - let vis = &ctx.vis; // Get visibility + let vis = &ctx.vis; - // Convert variant identifier to snake_case for the method name using convert_case - let method_ident_string = variant_ident.to_string().to_case( Case::Snake ); - let method_ident = syn::Ident::new( &method_ident_string, variant_ident.span() ); // Create new Ident with correct span + // 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); - // Generate the static constructor method: Enum::variant_name() -> Enum - // This applies for both #[scalar] and default behavior on zero-field tuple variants. + // 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 + Some(clause) => quote! { where #clause }, // clause is &WhereClause here + None => quote! {}, + }; + + // Correctly create method_ident, handling raw identifiers + let method_ident = { + let name_str = variant_ident.to_string(); + 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()) + } + } + }; + + // Static method: pub fn method_name() -> Self (Self will be EnumName) let generated_method = quote! { #[ inline( always ) ] - pub fn #method_ident() -> #enum_ident + pub fn #method_ident() -> Self { - #enum_ident::#variant_ident() + Self::#variant_ident() } }; - let mut generated_tokens = generated_method; - - // Generate standalone constructor if #[standalone_constructors] is present on the enum + // Standalone constructor if ctx.struct_attrs.standalone_constructors.is_some() { + 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 > } } + }; + + // 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 generated_standalone = quote! { #[ inline( always ) ] - #vis fn #method_ident() -> #enum_ident + #vis fn #standalone_method_ident #fn_signature_generics () -> #enum_ident #return_type_generics + #top_level_where_clause { - #enum_ident::#variant_ident() + #enum_path_for_construction ::#variant_ident() } }; - generated_tokens.extend(generated_standalone); + ctx.standalone_constructors.push(generated_standalone); } - Ok( generated_tokens ) + Ok( generated_method ) // Return only the static method tokens } \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs b/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs index 67e46a566a..2996959db8 100644 --- a/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs +++ b/module/core/former_meta/src/derive_former/former_enum/unit_variant_handler.rs @@ -1,56 +1,86 @@ -// qqq : Implement logic for Unit variants - use super::*; -use macro_tools::{ Result, quote, syn }; +use macro_tools:: +{ + Result, + diag, // For diag::return_syn_err! + generic_params::GenericsRef, // For enhanced generics handling + ident, // For proposed ident::new_ident_from_cased_str + qt, // For qt! macro, if preferred over quote::quote! + syn, + quote::quote_spanned, // Keep for specific span control if needed, or replace with qt! +}; use super::EnumVariantHandlerContext; -// use heck::ToSnakeCase; // Removed heck -use convert_case::{ Case, Casing }; // Import Case and Casing from convert_case -use proc_macro2::TokenStream; // Import TokenStream +use convert_case::{ Case, Casing }; // Keep for Case::Snake +use proc_macro2::TokenStream; -#[allow(dead_code)] // Suppress warning about unused function pub( crate ) fn handle( ctx : &mut EnumVariantHandlerContext< '_ > ) -> Result< TokenStream > { - // qqq : Implement skeleton body - - // Check for #[subform_scalar] on unit variants and return a specific error - if ctx.variant_attrs.subform_scalar.is_some() + // Handle #[subform_scalar] attribute error + // Assumes ctx.variant_attrs.subform_scalar is an Option<(AttributeValue, Span)> or similar + // For now, using ctx.variant.span() as a placeholder if specific attribute span isn't easily available. + // This part depends on how FieldAttributes is structured and if it stores spans for attributes. + // If `ctx.variant_attrs.subform_scalar` is simply an `Option` or `Option`, + // we might need to iterate attributes here to find the span, or use a broader span. + // For this refactoring, we'll assume `FieldAttributes` can provide a span for `subform_scalar` if present. + // If not, `ctx.variant.span()` is a fallback. + if let Some( attr_property ) = &ctx.variant_attrs.subform_scalar // Assuming FieldAttributes stores it as Option { - return Err( syn::Error::new_spanned( ctx.variant, "#[subform_scalar] cannot be used on unit variants." ) ); + // If AttributeProperty has a span() method or field: + // return diag::return_syn_err!( attr_property.span(), "Attribute `subform_scalar` is not applicable to unit variants" ); + // Otherwise, using variant span as a fallback: + return diag::return_syn_err!( ctx.variant.span(), "Attribute `subform_scalar` is not applicable to unit variants" ); } let variant_ident = &ctx.variant.ident; - let enum_ident = &ctx.enum_name; - let vis = &ctx.vis; // Get visibility + let enum_name = &ctx.enum_name; // This is syn::Ident + let vis = &ctx.vis; - // Convert variant identifier to snake_case for the method name using convert_case - let method_ident_string = variant_ident.to_string().to_case( Case::Snake ); - let method_ident = syn::Ident::new( &method_ident_string, variant_ident.span() ); // Create new Ident with correct span + // Generate method_ident (for static method and standalone constructor) + let variant_ident_str = variant_ident.to_string(); + let is_raw_prefix = variant_ident_str.starts_with( "r#" ); + let core_name_str = if is_raw_prefix { &variant_ident_str[ 2.. ] } else { &variant_ident_str }; + let snake_case_name = core_name_str.to_case( Case::Snake ); - // Generate the static constructor method - let generated_method = quote! + // Use the proposed (conceptual) macro_tools utility + // This will fail to compile until Increment 6 implements this utility. + let method_ident = ident::new_ident_from_cased_str( + &snake_case_name, + variant_ident.span(), + is_raw_prefix + )?; + + // Prepare generics using the proposed (conceptual) GenericsRef enhancements + // These will also fail to compile until Increment 6. + let generics_ref = GenericsRef::new_borrowed( &ctx.generics ); + let fn_signature_generics = generics_ref.impl_generics_tokens_if_any()?; + let return_type_generics = generics_ref.ty_generics_tokens_if_any()?; + let enum_path_for_construction = generics_ref.type_path_tokens_if_any( enum_name )?; + let where_clause_tokens = generics_ref.where_clause_tokens_if_any()?; + + // Generate the static constructor method on the enum itself + let generated_method = qt! { #[ inline( always ) ] - pub fn #method_ident() -> #enum_ident // Added pub and return type + pub fn #method_ident () -> Self { - #enum_ident::#variant_ident + Self::#variant_ident } }; - ctx.methods.push( generated_method ); // Will be collected in former_for_enum - - // Generate standalone constructor if #[standalone_constructors] is present on the enum + // Generate standalone constructor if #[standalone_constructors] is present if ctx.struct_attrs.standalone_constructors.is_some() { - let generated_standalone = quote! + let generated_standalone = qt! { #[ inline( always ) ] - #vis fn #method_ident() -> #enum_ident + #vis fn #method_ident #fn_signature_generics () -> #enum_name #return_type_generics + #where_clause_tokens { - #enum_ident::#variant_ident + #enum_path_for_construction :: #variant_ident } }; - ctx.standalone_constructors.push( generated_standalone ); // Will be collected in former_for_enum + ctx.standalone_constructors.push( generated_standalone ); } - Ok( quote!() ) // Return empty TokenStream as tokens are collected in ctx + Ok( generated_method ) } \ No newline at end of file diff --git a/module/core/former_meta/src/derive_former/former_struct.rs b/module/core/former_meta/src/derive_former/former_struct.rs index 723ed27b81..8fed04ad23 100644 --- a/module/core/former_meta/src/derive_former/former_struct.rs +++ b/module/core/former_meta/src/derive_former/former_struct.rs @@ -17,14 +17,17 @@ pub fn former_for_struct ast : &syn::DeriveInput, _data_struct : &syn::DataStruct, original_input : ¯o_tools::proc_macro2::TokenStream, - _has_debug : bool, + item_attributes : &ItemAttributes, // Changed: Accept parsed ItemAttributes + _has_debug : bool, // This is the correctly determined has_debug - now unused locally ) -> Result< TokenStream > { use macro_tools::IntoGenericArgs; use convert_case::{ Case, Casing }; // Added for snake_case naming // Space before ; - // Parse struct-level attributes like `storage_fields`, `mutator`, `perform`. - let struct_attrs = ItemAttributes::from_attrs( ast.attrs.iter() )?; + // Use the passed-in item_attributes + let struct_attrs = item_attributes; + // The _has_debug parameter is now replaced by the has_debug bool, + // and struct_attrs.debug.is_some() can also be used if needed locally. /* names: Generate identifiers for the Former components based on the struct name. */ let vis = &ast.vis; // Visibility of the original struct. 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 f82e8b95bc..dee59783e3 100644 --- a/module/core/former_meta/src/derive_former/struct_attrs.rs +++ b/module/core/former_meta/src/derive_former/struct_attrs.rs @@ -16,79 +16,88 @@ use macro_tools:: use component_model_types::{ Assign, OptionExt }; /// Represents the attributes of a struct, including storage fields, mutator, perform, and standalone constructor attributes. // <<< Updated doc -#[ derive( Debug, Default ) ] +#[ derive( Debug ) ] // Removed Default from derive pub struct ItemAttributes { /// 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 >, - /// 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, - /// 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 >, - - /// Optional attribute to enable generation of standalone constructor functions. // <<< Added field + /// Optional attribute to enable generation of standalone constructor functions. pub standalone_constructors : AttributePropertyStandaloneConstructors, + /// Optional attribute to enable debug output from the macro. + pub debug : AttributePropertyDebug, // Added debug field +} + +// Default impl needs to include the new debug field +impl Default for ItemAttributes { + fn default() -> Self { + Self { + storage_fields: Default::default(), + mutator: Default::default(), + perform: Default::default(), + standalone_constructors: Default::default(), + debug: Default::default(), // Initialize debug + } + } } impl ItemAttributes { - /// Parses attributes from an iterator. - pub fn from_attrs< 'a >( attrs : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > + /// This function now expects to find #[former(debug, standalone_constructors, ...)] + /// and also handles top-level #[storage_fields(...)], #[mutator(...)], #[perform(...)] + pub fn from_attrs< 'a >( attrs_iter : impl Iterator< Item = &'a syn::Attribute > ) -> Result< Self > { let mut result = Self::default(); - - let error = | attr : &syn::Attribute | -> syn::Error - { - let known_attributes = ct::concatcp! - ( - "Known attirbutes are : ", - "debug", - ", ", AttributeStorageFields::KEYWORD, - ", ", AttributeMutator::KEYWORD, - ", ", AttributePerform::KEYWORD, - ", ", AttributePropertyStandaloneConstructors::KEYWORD, // <<< Added keyword - ".", - ); - syn_err! - ( - attr, - "Expects an attribute of format '#[ attribute( key1 = val1, key2 = val2 ) ]'\n {known_attributes}\n But got: '{}'", - qt!{ #attr } - ) - }; - - for attr in attrs - { - - let key_ident = attr.path().get_ident().ok_or_else( || error( attr ) )?; - let key_str = format!( "{key_ident}" ); - - // attributes does not have to be known - // if attr::is_standard( &key_str ) - // { - // continue; - // } - - match key_str.as_ref() - { - AttributeStorageFields::KEYWORD => result.assign( AttributeStorageFields::from_meta( attr )? ), - AttributeMutator::KEYWORD => result.assign( AttributeMutator::from_meta( attr )? ), - AttributePerform::KEYWORD => result.assign( AttributePerform::from_meta( attr )? ), - // <<< Added case for standalone_constructors - AttributePropertyStandaloneConstructors::KEYWORD => result.assign( AttributePropertyStandaloneConstructors::from( true ) ), - // "debug" => {} // Assuming debug is handled elsewhere or implicitly - _ => {}, - // _ => return Err( error( attr ) ), // Allow unknown attributes - } + // let mut former_attr_processed = false; // Flag to check if #[former(...)] was processed // REMOVED + + for attr in attrs_iter { + let path = attr.path(); + if path.is_ident("former") { + // former_attr_processed = true; // Mark that we found and processed #[former] // REMOVED + match &attr.meta { + syn::Meta::List(meta_list) => { + let tokens_inside_former = meta_list.tokens.clone(); + // panic!("DEBUG PANIC: Inside #[former] parsing. Tokens: '{}'", tokens_inside_former.to_string()); + + // Use the Parse impl for ItemAttributes to parse contents of #[former(...)] + let parsed_former_attrs = syn::parse2::(tokens_inside_former)?; + + // Temporary panic to see what was parsed by ItemAttributes::parse + // panic!("DEBUG PANIC: Parsed inner attributes. Debug: {:?}, Standalone: {:?}", parsed_former_attrs.debug.is_some(), parsed_former_attrs.standalone_constructors.is_some()); + + // Assign only the flags that are meant to be inside #[former] + result.debug.assign(parsed_former_attrs.debug); + result.standalone_constructors.assign(parsed_former_attrs.standalone_constructors); + // Note: This assumes other fields like storage_fields, mutator, perform + // are NOT set via #[former(storage_fields=...)], but by their own top-level attributes. + // If they can also be in #[former], the Parse impl for ItemAttributes needs to be more comprehensive. + } + _ => return_syn_err!(attr, "Expected #[former(...)] to be a list attribute like #[former(debug)]"), + } + } else if path.is_ident(AttributeStorageFields::KEYWORD) { + result.assign(AttributeStorageFields::from_meta(attr)?); + } else if path.is_ident(AttributeMutator::KEYWORD) { + result.assign(AttributeMutator::from_meta(attr)?); + } else if path.is_ident(AttributePerform::KEYWORD) { + result.assign(AttributePerform::from_meta(attr)?); + } else if path.is_ident(AttributePropertyDebug::KEYWORD) { // Handle top-level #[debug] + result.debug.assign(AttributePropertyDebug::from(true)); + } else if path.is_ident(AttributePropertyStandaloneConstructors::KEYWORD) { // Handle top-level #[standalone_constructors] + result.standalone_constructors.assign(AttributePropertyStandaloneConstructors::from(true)); + } + // Other attributes (like derive, allow, etc.) are ignored. } - Ok( result ) + // After processing all attributes, former_attr_processed indicates if #[former()] was seen. + // The result.{debug/standalone_constructors} flags are set either by parsing #[former(...)] + // or by parsing top-level #[debug] / #[standalone_constructors]. + // No further panics needed here as the flags should be correctly set now. + + Ok(result) } /// @@ -200,7 +209,6 @@ where } } -// <<< Added Assign impl for the new property impl< IntoT > Assign< AttributePropertyStandaloneConstructors, IntoT > for ItemAttributes where IntoT : Into< AttributePropertyStandaloneConstructors >, @@ -213,6 +221,18 @@ where } } +// Added Assign impl for AttributePropertyDebug +impl< IntoT > Assign< AttributePropertyDebug, IntoT > for ItemAttributes +where + IntoT : Into< AttributePropertyDebug >, +{ + #[ inline( always ) ] + fn assign( &mut self, component : IntoT ) + { + let component = component.into(); + self.debug.assign( component ); + } +} /// /// Attribute to hold storage-specific fields. @@ -413,6 +433,44 @@ impl syn::parse::Parse for AttributeMutator } } +// Add syn::parse::Parse for ItemAttributes to parse contents of #[former(...)] +// This simplified version only looks for `debug` and `standalone_constructors` as flags. +impl syn::parse::Parse for ItemAttributes { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { + let mut result = Self { + // Initialize fields that are NOT parsed from inside #[former()] here + // to their defaults, as this Parse impl is only for former's args. + storage_fields: None, + mutator: Default::default(), + perform: None, + // These will be overwritten if found + standalone_constructors: Default::default(), + debug: Default::default(), + }; + + while !input.is_empty() { + let key_ident: syn::Ident = input.parse()?; + let key_str = key_ident.to_string(); + + match key_str.as_str() { + AttributePropertyDebug::KEYWORD => result.debug.assign(AttributePropertyDebug::from(true)), + AttributePropertyStandaloneConstructors::KEYWORD => result.standalone_constructors.assign(AttributePropertyStandaloneConstructors::from(true)), + // Add other #[former(...)] keys here if needed, e.g. former(storage = ...), former(perform = ...) + // For now, other keys inside #[former(...)] are errors. + _ => return_syn_err!(key_ident, "Unknown key '{}' for #[former(...)] attribute. Expected 'debug' or 'standalone_constructors'.", key_str), + } + + if input.peek(syn::Token![,]) { + input.parse::()?; + } else if !input.is_empty() { + // If there's more input but no comma, it's a syntax error + return Err(input.error("Expected comma between #[former(...)] arguments or end of arguments.")); + } + } + Ok(result) + } +} + /// /// Attribute to hold information about method to call after form. /// diff --git a/module/core/macro_tools/src/generic_params.rs b/module/core/macro_tools/src/generic_params.rs index b54e5787b9..45c7d87eac 100644 --- a/module/core/macro_tools/src/generic_params.rs +++ b/module/core/macro_tools/src/generic_params.rs @@ -93,6 +93,204 @@ mod private } } + /// A wrapper around a reference to `syn::Generics` to provide convenient helper methods + /// for generating token streams related to generic parameters. + /// + /// This is particularly useful in procedural macros for constructing parts of function + /// signatures, type paths, and where clauses that involve generics. + #[derive(Debug, Clone, Copy)] + pub struct GenericsRef<'a> + { + syn_generics: &'a syn::Generics, + } + + impl<'a> GenericsRef<'a> + { + /// Creates a new `GenericsRef` from a reference to `syn::Generics`. + #[must_use] + pub fn new_borrowed(syn_generics: &'a syn::Generics) -> Self + { + Self { syn_generics } + } + + /// Returns the `impl_generics` part (e.g., ``) + /// as a `TokenStream` if generics are present, otherwise an empty `TokenStream`. + /// + /// This is suitable for use in `impl <#impl_generics> Struct ...` contexts. + /// It includes bounds and lifetimes. + /// + /// # Errors + /// + /// Currently, this method is not expected to return an error, but returns `Result` + /// for future-proofing and consistency with other token-generating methods. + pub fn impl_generics_tokens_if_any(&self) -> Result + { + if self.syn_generics.params.is_empty() + { + return Ok(quote::quote! {}); + } + let (_, impl_g, _, _) = decompose_item_soft(self.syn_generics); + Ok(quote::quote! { < #impl_g > }) + } + + /// Returns the `ty_generics` part (e.g., ``) as a `TokenStream` + /// if generics are present, otherwise an empty `TokenStream`. + /// + /// This is suitable for use in type paths like `Struct::<#ty_generics>`. + /// It includes only the identifiers of the generic parameters (types, lifetimes, consts). + /// + /// # Errors + /// + /// Currently, this method is not expected to return an error, but returns `Result` + /// for future-proofing and consistency. + pub fn ty_generics_tokens_if_any(&self) -> Result + { + if self.syn_generics.params.is_empty() + { + return Ok(quote::quote! {}); + } + let (_, _, ty_g, _) = decompose_item_soft(self.syn_generics); + Ok(quote::quote! { < #ty_g > }) + } + + /// Returns the `where_clause` (e.g., `where T: Trait`) as a `TokenStream` + /// if a where clause is present in the original generics, otherwise an empty `TokenStream`. + /// + /// # Errors + /// + /// Currently, this method is not expected to return an error, but returns `Result` + /// for future-proofing and consistency. + pub fn where_clause_tokens_if_any(&self) -> Result + { + let (_, _, _, where_c_punctuated) = decompose_item_soft(self.syn_generics); + if where_c_punctuated.is_empty() { + Ok(quote::quote! {}) + } else { + Ok(quote::quote! { where #where_c_punctuated }) + } + } + + /// Returns a token stream representing a path to a type, including its generic arguments + /// if present (e.g., `MyType::`). If no generics are present, it returns + /// just the `base_ident`. + /// + /// # Arguments + /// + /// * `base_ident`: The identifier of the base type (e.g., `MyType`). + /// + /// # Errors + /// + /// Currently, this method is not expected to return an error, but returns `Result` + /// for future-proofing and consistency. + pub fn type_path_tokens_if_any(&self, base_ident: &syn::Ident) -> Result + { + if self.syn_generics.params.is_empty() + { + Ok(quote::quote! { #base_ident }) + } else + { + let (_, _, ty_g, _) = decompose_item_soft(self.syn_generics); + Ok(quote::quote! { #base_ident ::< #ty_g > }) + } + } + } + + // Helper function similar to the original `decompose`. + #[allow(clippy::type_complexity)] + fn decompose_item_soft + ( + generics: &syn::Generics, + ) -> + ( + syn::punctuated::Punctuated, // with_defaults + syn::punctuated::Punctuated, // for_impl + syn::punctuated::Punctuated, // for_ty + syn::punctuated::Punctuated, // where_clause + ) + { + let mut generics_with_defaults = generics.params.clone(); + punctuated::ensure_trailing_comma(&mut generics_with_defaults); + + let mut generics_for_impl = syn::punctuated::Punctuated::new(); + let mut generics_for_ty = syn::punctuated::Punctuated::new(); + + for param in &generics.params { + match param { + syn::GenericParam::Type(type_param) => { + let impl_param = syn::GenericParam::Type(syn::TypeParam { + attrs: vec![], + ident: type_param.ident.clone(), + colon_token: type_param.colon_token, + bounds: type_param.bounds.clone(), + eq_token: None, + default: None, + }); + generics_for_impl.push_value(impl_param); + generics_for_impl.push_punct(syn::token::Comma::default()); + + let ty_param = syn::GenericParam::Type(syn::TypeParam { + attrs: vec![], + ident: type_param.ident.clone(), + colon_token: None, + bounds: syn::punctuated::Punctuated::new(), + eq_token: None, + default: None, + }); + generics_for_ty.push_value(ty_param); + generics_for_ty.push_punct(syn::token::Comma::default()); + } + syn::GenericParam::Const(const_param) => { + let impl_param = syn::GenericParam::Const(syn::ConstParam { + attrs: vec![], + const_token: const_param.const_token, + ident: const_param.ident.clone(), + colon_token: const_param.colon_token, + ty: const_param.ty.clone(), + eq_token: None, + default: None, + }); + generics_for_impl.push_value(impl_param); + generics_for_impl.push_punct(syn::token::Comma::default()); + + let ty_param = syn::GenericParam::Type(syn::TypeParam { // Const params are represented by their idents for ty_generics + attrs: vec![], + ident: const_param.ident.clone(), + colon_token: None, + bounds: syn::punctuated::Punctuated::new(), + eq_token: None, + default: None, + }); + generics_for_ty.push_value(ty_param); + generics_for_ty.push_punct(syn::token::Comma::default()); + } + syn::GenericParam::Lifetime(lifetime_param) => { + generics_for_impl.push_value(syn::GenericParam::Lifetime(lifetime_param.clone())); + generics_for_impl.push_punct(syn::token::Comma::default()); + + let ty_param = syn::GenericParam::Lifetime(syn::LifetimeParam { + attrs: vec![], + lifetime: lifetime_param.lifetime.clone(), + colon_token: None, + bounds: syn::punctuated::Punctuated::new(), + }); + generics_for_ty.push_value(ty_param); + generics_for_ty.push_punct(syn::token::Comma::default()); + } + } + } + + let generics_where = if let Some(where_clause) = &generics.where_clause { + let mut predicates = where_clause.predicates.clone(); + punctuated::ensure_trailing_comma(&mut predicates); + predicates + } else { + syn::punctuated::Punctuated::new() + }; + + (generics_with_defaults, generics_for_impl, generics_for_ty, generics_where) + } + + /// Merges two `syn::Generics` instances into a new one. /// /// This function takes two references to `syn::Generics` and combines their @@ -147,7 +345,6 @@ mod private }; // Merge params - // result.params.extend( a.params.iter().chain( b.params.iter() ) ); for param in &a.params { result.params.push( param.clone() ); @@ -213,7 +410,6 @@ mod private #[ must_use ] pub fn only_names( generics : &syn::Generics ) -> syn::Generics { - // use syn::{ Generics, GenericParam, LifetimeDef, TypeParam, ConstParam }; use syn::{ Generics, GenericParam, LifetimeParam, TypeParam, ConstParam }; let result = Generics @@ -291,11 +487,6 @@ mod private #[ must_use ] pub fn names( generics : &syn::Generics ) -> impl IterTrait< '_, &syn::Ident > - // -> std::iter::Map - // < - // syn::punctuated::Iter< 'a, syn::GenericParam >, - // impl FnMut( &'a syn::GenericParam ) -> &'a syn::Ident + 'a, - // > { generics.params.iter().map( | param | match param { @@ -531,6 +722,7 @@ pub mod own only_names, names, decompose, + GenericsRef, }; } diff --git a/module/core/macro_tools/src/ident.rs b/module/core/macro_tools/src/ident.rs index e919e46d7b..3b475f38d4 100644 --- a/module/core/macro_tools/src/ident.rs +++ b/module/core/macro_tools/src/ident.rs @@ -44,6 +44,67 @@ mod private ident.clone() } } + + /// Creates a `syn::Ident` from a string that is already in the target case. + /// Handles Rust keywords and original raw identifier status. + /// If `cased_name_str` is a keyword, or if `source_had_raw_prefix` is true, + /// `syn::Ident::new_raw` is used. Otherwise, `syn::Ident::new` is used. + /// + /// Returns an error if `cased_name_str` is empty or an invalid identifier. + pub fn new_ident_from_cased_str + ( + cased_name_str: &str, + span: proc_macro2::Span, + source_had_raw_prefix: bool + ) -> Result // Use local Result alias + { + if cased_name_str.is_empty() { + return Err(syn::Error::new(span, "Cannot create identifier from empty string")); + } + + // Comprehensive list of Rust 2021 keywords that are problematic as idents. + // Based on https://doc.rust-lang.org/reference/keywords.html + const RUST_KEYWORDS: &[&str] = &[ + // Strict keywords + "as", "break", "const", "continue", "crate", "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", + // Reserved keywords + "abstract", "async", "await", "become", "box", "do", "final", "macro", "override", + "priv", "try", "typeof", "unsized", "virtual", "yield", + // Weak keywords + "dyn", "union", + ]; + + let is_keyword = RUST_KEYWORDS.contains(&cased_name_str); + + if source_had_raw_prefix || is_keyword { + // Validate if the string is permissible for new_raw, even if it's a keyword. + // For example, "123" is not a keyword but also not valid for new_raw("123", span). + // A simple validation is to check if it would parse if it *weren't* a keyword. + // This is tricky because `syn::parse_str` would fail for actual keywords. + // Let's rely on `syn::Ident::new_raw` to do its job, but catch obvious non-ident chars. + if cased_name_str.chars().any(|c| !c.is_alphanumeric() && c != '_') { + if !( cased_name_str.starts_with('_') && cased_name_str.chars().skip(1).all(|c| c.is_alphanumeric() || c == '_') ) && cased_name_str != "_" { + return Err(syn::Error::new(span, format!("Invalid characters in identifier string for raw creation: {}", cased_name_str))); + } + } + Ok(syn::Ident::new_raw(cased_name_str, span)) + } else { + // Not a keyword and source was not raw. Try to create a normal identifier. + // syn::Ident::new would panic on keywords, but we've established it's not a keyword. + // It will also panic on other invalid idents like "123" or "with space". + // To provide a Result, we attempt to parse it. + match syn::parse_str::(cased_name_str) { + Ok(ident) => Ok(ident), + Err(_e) => { + // Construct a new error, because the error from parse_str might not have the right span or context. + Err(syn::Error::new(span, format!("Invalid identifier string: '{}'", cased_name_str))) + } + } + } + } } #[ doc( inline ) ] @@ -59,7 +120,9 @@ pub mod own #[ doc( inline ) ] pub use orphan::*; #[ doc( inline ) ] - pub use private::ident_maybe_raw; // Export the renamed function + pub use private::ident_maybe_raw; + #[ doc( inline ) ] + pub use private::new_ident_from_cased_str; } /// Orphan namespace of the module. diff --git a/module/core/macro_tools/tests/inc/generic_params_ref_test.rs b/module/core/macro_tools/tests/inc/generic_params_ref_test.rs new file mode 100644 index 0000000000..fec86bb645 --- /dev/null +++ b/module/core/macro_tools/tests/inc/generic_params_ref_test.rs @@ -0,0 +1,98 @@ +#[cfg(test)] +mod tests { + use macro_tools::syn::{self, parse_quote}; + use macro_tools::quote::{self, quote}; // Ensure quote is in scope + use macro_tools::generic_params::GenericsRef; // The struct being tested + + #[test] + fn t6_8_impl_generics_std() { + // ID: T6.8 (`impl_generics_tokens_if_any` with `generics_std`) + let generics_std: syn::Generics = parse_quote! { where T: Debug > }; + let generics_ref = GenericsRef::new_borrowed(&generics_std); + let tokens = generics_ref.impl_generics_tokens_if_any().unwrap(); + let expected: proc_macro2::TokenStream = quote! { }; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + #[test] + fn t6_9_impl_generics_empty() { + // ID: T6.9 (`impl_generics_tokens_if_any` with `generics_empty`) + let generics_empty: syn::Generics = parse_quote! {}; + let generics_ref = GenericsRef::new_borrowed(&generics_empty); + let tokens = generics_ref.impl_generics_tokens_if_any().unwrap(); + let expected: proc_macro2::TokenStream = quote! {}; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + #[test] + fn t6_10_ty_generics_std() { + // ID: T6.10 (`ty_generics_tokens_if_any` with `generics_std`) + let generics_std: syn::Generics = parse_quote! { where T: Debug > }; + let generics_ref = GenericsRef::new_borrowed(&generics_std); + let tokens = generics_ref.ty_generics_tokens_if_any().unwrap(); + let expected: proc_macro2::TokenStream = quote! { }; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + #[test] + fn t6_11_ty_generics_empty() { + // ID: T6.11 (`ty_generics_tokens_if_any` with `generics_empty`) + let generics_empty: syn::Generics = parse_quote! {}; + let generics_ref = GenericsRef::new_borrowed(&generics_empty); + let tokens = generics_ref.ty_generics_tokens_if_any().unwrap(); + let expected: proc_macro2::TokenStream = quote! {}; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + #[test] + fn t6_12_where_clause_std() { + // ID: T6.12 (`where_clause_tokens_if_any` with `generics_std`) + let generics_std: syn::Generics = parse_quote! { where T: Debug > }; + let generics_ref = GenericsRef::new_borrowed(&generics_std); + let tokens = generics_ref.where_clause_tokens_if_any().unwrap(); + let expected: proc_macro2::TokenStream = quote! { where T: Debug }; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + #[test] + fn t6_13_where_clause_empty() { + // ID: T6.13 (`where_clause_tokens_if_any` with `generics_empty`) + let generics_empty: syn::Generics = parse_quote! {}; + let generics_ref = GenericsRef::new_borrowed(&generics_empty); + let tokens = generics_ref.where_clause_tokens_if_any().unwrap(); + let expected: proc_macro2::TokenStream = quote! {}; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + #[test] + fn t6_13b_where_clause_no_clause_but_generics() { + let generics_no_where: syn::Generics = parse_quote! { }; + let generics_ref = GenericsRef::new_borrowed(&generics_no_where); + let tokens = generics_ref.where_clause_tokens_if_any().unwrap(); + let expected: proc_macro2::TokenStream = quote! {}; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + + #[test] + fn t6_14_type_path_std() { + // ID: T6.14 (`type_path_tokens_if_any` with `generics_std`, `enum_name`) + let generics_std: syn::Generics = parse_quote! { where T: Debug > }; + let enum_name: syn::Ident = parse_quote! { MyEnum }; + let generics_ref = GenericsRef::new_borrowed(&generics_std); + let tokens = generics_ref.type_path_tokens_if_any(&enum_name).unwrap(); + let expected: proc_macro2::TokenStream = quote! { MyEnum:: }; + assert_eq!(tokens.to_string(), expected.to_string()); + } + + #[test] + fn t6_15_type_path_empty() { + // ID: T6.15 (`type_path_tokens_if_any` with `generics_empty`, `enum_name`) + let generics_empty: syn::Generics = parse_quote! {}; + let enum_name: syn::Ident = parse_quote! { MyEnum }; + let generics_ref = GenericsRef::new_borrowed(&generics_empty); + let tokens = generics_ref.type_path_tokens_if_any(&enum_name).unwrap(); + let expected: proc_macro2::TokenStream = quote! { MyEnum }; + assert_eq!(tokens.to_string(), expected.to_string()); + } +} \ No newline at end of file diff --git a/module/core/macro_tools/tests/inc/ident_new_from_cased_str_test.rs b/module/core/macro_tools/tests/inc/ident_new_from_cased_str_test.rs new file mode 100644 index 0000000000..e87fe93dbf --- /dev/null +++ b/module/core/macro_tools/tests/inc/ident_new_from_cased_str_test.rs @@ -0,0 +1,113 @@ +#[cfg(test)] +mod tests { + use macro_tools::ident; + use syn::spanned::Spanned; // Corrected import for Spanned + + // Helper to create a dummy span + fn dummy_span() -> proc_macro2::Span { + proc_macro2::Span::call_site() + } + + #[test] + fn t6_1_normal_ident() { + // ID: T6.1, Input: ("normal_ident", span, false), Expected: Ok(syn::Ident::new("normal_ident", span)) + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("normal_ident", span, false); + assert!(result.is_ok(), "Test T6.1 failed: {:?}", result.err()); + let ident = result.unwrap(); + assert_eq!(ident.to_string(), "normal_ident"); + // Removed problematic span start comparison: assert_eq!(ident.span().start(), span.start()); + // Verifying the span was passed can be done by checking if ident.span() is roughly equal, + // but for call_site(), it's often enough that it was used. + // For more robust span testing, one might compare source_file if available and different. + // Here, we trust the span is passed through. + } + + #[test] + fn t6_2_keyword_becomes_raw() { + // ID: T6.2, Input: ("fn", span, false), Expected: Ok(syn::Ident::new_raw("fn", span)) + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("fn", span, false); + assert!(result.is_ok(), "Test T6.2 failed: {:?}", result.err()); + let ident = result.unwrap(); + assert_eq!(ident.to_string(), "r#fn"); + } + + #[test] + fn t6_3_original_raw_keyword_stays_raw() { + // ID: T6.3, Input: ("fn", span, true), Expected: Ok(syn::Ident::new_raw("fn", span)) + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("fn", span, true); + assert!(result.is_ok(), "Test T6.3 failed: {:?}", result.err()); + let ident = result.unwrap(); + assert_eq!(ident.to_string(), "r#fn"); + } + + #[test] + fn t6_4_original_raw_non_keyword_stays_raw() { + // ID: T6.4, Input: ("my_raw_ident", span, true), Expected: Ok(syn::Ident::new_raw("my_raw_ident", span)) + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("my_raw_ident", span, true); + assert!(result.is_ok(), "Test T6.4 failed: {:?}", result.err()); + let ident = result.unwrap(); + assert_eq!(ident.to_string(), "r#my_raw_ident"); + } + + #[test] + fn t6_5_empty_string_err() { + // ID: T6.5, Input: ("", span, false), Expected: Err(_) + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("", span, false); + assert!(result.is_err(), "Test T6.5 failed: expected error for empty string"); + } + + #[test] + fn t6_6_invalid_chars_err() { + // ID: T6.6, Input: ("with space", span, false), Expected: Err(_) + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("with space", span, false); + assert!(result.is_err(), "Test T6.6 failed: expected error for string with space"); + } + + #[test] + fn t6_7_valid_pascal_case_ident() { + // ID: T6.7, Input: ("ValidIdent", span, false), Expected: Ok(syn::Ident::new("ValidIdent", span)) + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("ValidIdent", span, false); + assert!(result.is_ok(), "Test T6.7 failed: {:?}", result.err()); + let ident = result.unwrap(); + assert_eq!(ident.to_string(), "ValidIdent"); + } + + #[test] + fn underscore_ident() { + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("_", span, false); + assert!(result.is_ok(), "Test for '_' failed: {:?}", result.err()); + assert_eq!(result.unwrap().to_string(), "_"); + } + + #[test] + fn underscore_prefixed_ident() { + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("_my_ident", span, false); + assert!(result.is_ok(), "Test for '_my_ident' failed: {:?}", result.err()); + assert_eq!(result.unwrap().to_string(), "_my_ident"); + } + + #[test] + fn keyword_if_becomes_raw() { + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("if", span, false); + assert!(result.is_ok(), "Test for 'if' keyword failed: {:?}", result.err()); + assert_eq!(result.unwrap().to_string(), "r#if"); + } + + #[test] + fn keyword_if_original_raw_stays_raw() { + let span = dummy_span(); + let result = ident::new_ident_from_cased_str("if", span, true); + assert!(result.is_ok(), "Test for 'if' keyword (original raw) failed: {:?}", result.err()); + assert_eq!(result.unwrap().to_string(), "r#if"); + } +} \ No newline at end of file diff --git a/module/core/macro_tools/tests/inc/mod.rs b/module/core/macro_tools/tests/inc/mod.rs index a7e982e2c8..ee8fdc9264 100644 --- a/module/core/macro_tools/tests/inc/mod.rs +++ b/module/core/macro_tools/tests/inc/mod.rs @@ -29,8 +29,12 @@ mod if_enabled mod generic_args_test; #[ cfg( feature = "generic_params" ) ] mod generic_params_test; + #[ cfg( feature = "generic_params" ) ] + mod generic_params_ref_test; // Added new test file #[ cfg( feature = "ident" ) ] // Use new feature name - mod ident_test; // Add the new test file + mod ident_test; + #[ cfg( feature = "ident" ) ] + mod ident_new_from_cased_str_test; // Added new test file #[ cfg( feature = "item" ) ] mod item_test; #[ cfg( feature = "item_struct" ) ]