-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add minimal documentation to CGP framework #46
Conversation
Signed-off-by: Marvin Hansen <[email protected]>
…cro components Addresses issue: contextgeneric#45 Add detailed Rust docstrings to core macro implementation files, improving code understanding and maintainability. Documentation follows Rust best practices with clear examples and detailed explanations. Each file's documentation includes: - Clear overview and purpose - Detailed function/struct documentation - Arguments and return value descriptions - Practical code examples - Implementation notes and edge cases - Type parameter explanations where applicable All examples are marked with `ignore` where they depend on the full CGP framework context. Documentation has been verified with `cargo test --doc` and `cargo doc`. Part of the ongoing effort to improve CGP framework documentation and usability. Signed-off-by: Marvin Hansen <[email protected]>
…nent Change the type parameter name from `N` to `Name` in DelegateComponent trait to better reflect its purpose as the component type being delegated. This makes the code more self-documenting and follows Rust naming conventions for type parameters. The change is purely cosmetic and does not affect functionality: - Improves code readability - Better communicates parameter purpose - Maintains backward compatibility - Follows Rust type parameter naming guidelines Signed-off-by: Marvin Hansen <[email protected]>
Add detailed documentation for all procedural macros in the CGP component system. The documentation follows Rust's best practices and includes: Crate Level: - Overview of macro functionality and purpose - Organized sections for different macro categories - Complete examples for each macro type Individual Macros: - cgp_component: Attribute macro for component definition - delegate_components: Macro for component delegation - cgp_preset: Macro for component configuration presets - for_each_replace: Utility for type replacement iteration - replace_with: Utility for type substitution Each macro is documented with: - Clear descriptions of functionality - Practical usage examples - Proper macro linking syntax using macro@ - Implementation notes and best practices Fixed documentation warnings: - Corrected ambiguous macro references in doc links - Added proper macro@ prefix for attribute macros - Ensured consistent formatting across all examples Part of the ongoing effort to improve CGP framework documentation. Signed-off-by: Marvin Hansen <[email protected]>
Add detailed documentation throughout the cgp-field crate to improve usability and understanding. This includes: Core Types: - Field: Type-safe field representation with phantom types - Char: Type-level character representation for field names - Index: Type-safe indexing with const generics - Either/Void: Sum types for variant handling - Cons/Nil: Product types for heterogeneous lists Traits: - HasField/FieldGetter: Read-only field access traits - HasFieldMut/MutFieldGetter: Mutable field access traits Implementations: - UseField: Type provider pattern for field access - WithField: Provider-wrapped field access utilities Module Documentation: - types/: Type definitions and constructors - traits/: Field access trait definitions - impls/: Concrete implementations and providers Each component is documented with: - Clear descriptions of purpose and functionality - Type parameter explanations - Practical usage examples - Implementation details - Cross-references between related items Also fixes documentation link in types/mod.rs to use proper mod@ prefix for module references. Part of the ongoing effort to improve CGP framework documentation. Signed-off-by: Marvin Hansen <[email protected]>
Add detailed documentation to the internal macro implementation crate, explaining the core functionality and implementation details: Core Components: - field: Field access trait derivation with type-safe accessors - product: Product and sum type construction utilities - symbol: Type-level symbol generation from strings Key Features Documented: - Trait derivation implementation for HasField and HasFieldMut - Nested type construction for product and sum types - Type-level symbol generation with character-level precision - Parser implementations for macro input processing Implementation Details: - Clear explanation of token stream handling - Type generation and manipulation patterns - Integration with syn and quote for macro expansion - Error handling and edge cases Each module and function includes: - Purpose and functionality description - Type parameter documentation - Return value specifications - Practical usage examples - Implementation notes This documentation helps maintainers understand the internal workings of the CGP field macros while keeping the code itself unchanged. Signed-off-by: Marvin Hansen <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@marvin-hansen I just saw your pull request. Thanks a lot on the effort you put in to help document the crate!
I have looked through some of your documentation, however it seems like there are quite a number of misunderstanding on the use of the constructs, especially when they are not yet covered by the book that I am writing. Also, the PR is pretty large and can be challenging to discuss and approve everything together.
I'd suggest that you break down the pull requests by topics covered by each chapter in the book. As for the constructs that are not yet covered by the book, I think it might be better if you hold off the documentation until the relevant chapter is ready.
/// | ||
/// ```rust,ignore | ||
/// cgp_preset! { | ||
/// struct LoggingPreset { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no struct
keyword in front of the preset name.
/// cgp_preset! { | ||
/// struct LoggingPreset { | ||
/// logger: ConsoleLogger, | ||
/// metrics: PrometheusMetrics, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example mapping here should follow the same naming convention for the name type of CGP components. i.e.:
cgp_preset! {
LoggerComponent: LogToConsole,
MetricsComponent: UsePrometheusMetrics,
}
/// [T] in [String, i32, bool] { | ||
/// fn process(value: T) -> T { value } | ||
/// } | ||
/// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual syntax for this macro is:
for_each_replace! {
[ FooComponent, BarComponent, BazComponent ],
| Component | {
impl DelegateComponent<Component> for TargetProvider {
type Delegate = SourceProvider;
}
}
}
which would be expanded to:
impl DelegateComponent<FooComponent> for TargetProvider {
type Delegate = SourceProvider;
}
impl DelegateComponent<BarComponent> for TargetProvider {
type Delegate = SourceProvider;
}
impl DelegateComponent<BazComponent> for TargetProvider {
type Delegate = SourceProvider;
}
/// | ||
/// ```rust,ignore | ||
/// replace_with! { | ||
/// type NewType = OldType<String>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The actual syntax for this macro is:
replace_with! {
[ FooComponent, BarComponent, BazComponent ],
| Components | {
delegate_components! {
TargetProvider {
Components: SourceProvider,
}
}
}
}
Which would be expanded into:
delegate_components! {
TargetProvider {
[ FooComponent, BarComponent, BazComponent ]:
SourceProvider,
}
}
/// println!("[{}] {}", self.context, message); | ||
/// } | ||
/// } | ||
/// ``` | ||
pub struct UseContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, the UseContext
pattern is used for implementing a provider that simply uses the context to provide the implementation. Something like:
#[cgp_component {
provider: RequestHandler,
}]
pub trait CanHandleRequest {
fn handle_request(&self, request: &Request) -> Response;
}
impl<Context> RequestHandler<Context> for UseContext
where
Context: CanHandleRequest,
{
fn handle_request(context: &Context, request: &Request) -> Response {
context.handle_request
}
}
The main use is for higher-order providers, where providers are passed explitly as "arguments" via generic parameters, which we have not covered in the book. In that case, the UseContext
provider means that we want to provide the implementation via the context, instead of via the custom provider argument.
/// | ||
/// ```rust,ignore | ||
/// let name_symbol = symbol!(name); | ||
/// let age_symbol = symbol!(age); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The symbol!
macro is a way to lift string values to the type level. So something like symbol!("foo")
is a type that uniquely represents the string "foo"
.
/// # Examples | ||
/// | ||
/// ```rust,ignore | ||
/// Product! { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Product!
macro generates anonymous structs as type-level lists. So something like Product![String, u32, bool]
is desugared to Cons<String, Cons<u32, Cons<bool, Nil>>>
.
/// match shape { | ||
/// Shape::Circle(r) => println!("Circle with radius {}", r), | ||
/// Shape::Rectangle(w, h) => println!("Rectangle {}x{}", w, h), | ||
/// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Sum!
macro is similar to Product!
that it generates anonymous sum types. So something like Sum![String, u32, bool]
is desugared to Either<String, Either<u32, Either<bool, Void>>>
.
/// y: 2.0, | ||
/// } | ||
/// }; | ||
/// ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The product!
macro is used for value-level pattern matching and construction of product values. So something like product![foo, bar, baz]
is desugared to Cons(foo, Cons(bar, Cons(baz, Nil)))
.
/// | ||
/// struct Name; | ||
/// let provider = UseField(PhantomData::<Name>); | ||
/// ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The UseField
pattern is used for implementing getter traits using HasField
. Something like:
#[cgp_component {
provider: NameGetter,
}]
pub trait HasName {
fn get_name(&self) -> &String;
}
impl<Context, Tag> NameGetter<Context> for UseField<Tag>
where
Context: HasField<Tag, Value = String>,
{
fn get_name(context: &Context) -> &String {
context.get_field(PhantomData)
}
}
pub type GetNameFromNameField = UseField<symbol!("name")>;
We will cover the pattern in later chapters of the book.
No problem. I close this PR for good, and then gradually re-submit one crate at a time with the docs and your suggestions and probably add applicable references to the book
|
Addresses issue #45
Add detailed Rust documentation across multiple CGP crates:
cgp-component-macro:
cgp-field:
cgp-field-macro-lib:
All documentation follows Rust best practices including:
Changes are documentation-only, improving code clarity without
modifying functionality.