fp_macros/lib.rs
1#![warn(missing_docs)]
2
3//! Procedural macros for the [`fp-library`](https://docs.rs/fp-library/latest/fp_library/) crate.
4//!
5//! This crate provides macros for generating and working with Higher-Kinded Type (HKT) traits.
6
7pub(crate) mod analysis; // Type and trait analysis
8pub(crate) mod codegen; // Code generation (includes re-exports)
9pub(crate) mod core; // Core infrastructure (config, error, result)
10pub(crate) mod documentation; // Documentation generation macros
11pub(crate) mod hkt; // Higher-Kinded Type macros
12pub(crate) mod hm; // Hindley-Milner type conversion
13pub(crate) mod resolution; // Type resolution
14pub(crate) mod support; // Support utilities (attributes, syntax, validation, errors)
15
16#[cfg(test)]
17mod property_tests;
18
19use crate::core::ToCompileError;
20use codegen::{FunctionFormatter, ReExportInput, TraitFormatter, generate_re_exports_worker};
21use documentation::{
22 document_fields_worker, document_module_worker, document_parameters_worker,
23 document_signature_worker, document_type_parameters_worker,
24};
25use hkt::{
26 ApplyInput, AssociatedTypes, ImplKindInput, apply_worker, generate_name, impl_kind_worker,
27 trait_kind_worker,
28};
29use proc_macro::TokenStream;
30use quote::quote;
31use syn::parse_macro_input;
32
33/// Generates the name of a `Kind` trait based on its signature.
34///
35/// This macro takes a list of associated type definitions, similar to a trait definition.
36///
37/// ### Syntax
38///
39/// ```ignore
40/// Kind!(
41/// type AssocName<Params>: Bounds;
42/// // ...
43/// )
44/// ```
45///
46/// ### Parameters
47///
48/// * `Associated Types`: A list of associated type definitions (e.g., `type Of<T>;`) that define the signature of the Kind.
49///
50/// ### Generates
51///
52/// The name of the generated `Kind` trait (e.g., `Kind_0123456789abcdef`).
53/// The name is deterministic and based on a hash of the signature.
54///
55/// ### Examples
56///
57/// ```ignore
58/// // Invocation
59/// let name = Kind!(type Of<T>;);
60///
61/// // Expanded code
62/// let name = Kind_...; // e.g., Kind_a1b2c3d4e5f67890
63/// ```
64///
65/// ```ignore
66/// // Invocation
67/// let name = Kind!(type Of<'a, T: Display>: Debug;);
68///
69/// // Expanded code
70/// let name = Kind_...; // Unique hash based on signature
71/// ```
72///
73/// ```ignore
74/// // Invocation
75/// let name = Kind!(
76/// type Of<T>;
77/// type SendOf<T>: Send;
78/// );
79///
80/// // Expanded code
81/// let name = Kind_...; // Unique hash based on signature
82/// ```
83///
84/// ### Limitations
85///
86/// Due to Rust syntax restrictions, this macro cannot be used directly in positions where a
87/// concrete path is expected by the parser, such as:
88/// * Supertrait bounds: `trait MyTrait: Kind!(...) {}` (Invalid)
89/// * Type aliases: `type MyKind = Kind!(...);` (Invalid)
90/// * Trait aliases: `trait MyKind = Kind!(...);` (Invalid)
91///
92/// In these cases, you must use the generated name directly (e.g., `Kind_...`).
93#[proc_macro]
94#[allow(non_snake_case)]
95pub fn Kind(input: TokenStream) -> TokenStream {
96 let input = parse_macro_input!(input as AssociatedTypes);
97 let name = match generate_name(&input) {
98 Ok(name) => name,
99 Err(e) => return e.to_compile_error().into(),
100 };
101 quote!(#name).into()
102}
103
104/// Defines a new `Kind` trait.
105///
106/// This macro generates a trait definition for a Higher-Kinded Type signature.
107///
108/// ### Syntax
109///
110/// ```ignore
111/// trait_kind!(
112/// type AssocName<Params>: Bounds;
113/// // ...
114/// )
115/// ```
116///
117/// ### Parameters
118///
119/// * `Associated Types`: A list of associated type definitions (e.g., `type Of<T>;`) that define the signature of the Kind.
120///
121/// ### Generates
122///
123/// A public trait definition with a unique name derived from the signature (format: `Kind_{hash}`).
124///
125/// ### Examples
126///
127/// ```ignore
128/// // Invocation
129/// trait_kind!(type Of<T>;);
130///
131/// // Expanded code
132/// pub trait Kind_... { // e.g., Kind_a1b2c3d4e5f67890
133/// type Of<T>;
134/// }
135/// ```
136///
137/// ```ignore
138/// // Invocation
139/// trait_kind!(type Of<'a, T: Display>: Debug;);
140///
141/// // Expanded code
142/// pub trait Kind_... {
143/// type Of<'a, T: Display>: Debug;
144/// }
145/// ```
146///
147/// ```ignore
148/// // Invocation
149/// trait_kind!(
150/// type Of<T>;
151/// type SendOf<T>: Send;
152/// );
153///
154/// // Expanded code
155/// pub trait Kind_... {
156/// type Of<T>;
157/// type SendOf<T>: Send;
158/// }
159/// ```
160#[proc_macro]
161pub fn trait_kind(input: TokenStream) -> TokenStream {
162 let input = parse_macro_input!(input as AssociatedTypes);
163 match trait_kind_worker(input) {
164 Ok(tokens) => tokens.into(),
165 Err(e) => e.to_compile_error().into(),
166 }
167}
168
169/// Implements a `Kind` trait for a brand.
170///
171/// This macro simplifies the implementation of a generated `Kind` trait for a specific
172/// brand type. It infers the correct `Kind` trait to implement based on the signature
173/// of the associated types provided in the block.
174///
175/// The signature (names, parameters, and bounds) of the associated types must match
176/// the definition used in [`trait_kind!`] or [`Kind!`] to ensure the correct trait is implemented.
177///
178/// ### Syntax
179///
180/// ```ignore
181/// impl_kind! {
182/// // Optional impl generics
183/// impl<Generics> for BrandType
184/// // Optional where clause
185/// where Bounds
186/// {
187/// type AssocName<Params> = ConcreteType;
188/// // ... more associated types
189/// }
190/// }
191/// ```
192///
193/// ### Parameters
194///
195/// * `Generics`: Optional generic parameters for the implementation.
196/// * `BrandType`: The brand type to implement the Kind for.
197/// * `Bounds`: Optional where clause bounds.
198/// * `Associated Types`: The associated type assignments (e.g., `type Of<A> = Option<A>;`).
199///
200/// ### Generates
201///
202/// An implementation of the appropriate `Kind` trait for the brand.
203///
204/// ### Attributes
205///
206/// Inside the `impl_kind!` block, you can use documentation-specific attributes on associated types:
207///
208/// * `#[document_default]`: Marks this associated type as the default for resolving bare `Self` in
209/// the generated documentation for this brand within the module.
210///
211/// ### Examples
212///
213/// ```ignore
214/// // Invocation
215/// impl_kind! {
216/// for OptionBrand {
217/// #[document_default]
218/// type Of<A> = Option<A>;
219/// }
220/// }
221///
222/// // Expanded code
223/// impl Kind_... for OptionBrand { // e.g., Kind_a1b2c3d4e5f67890
224/// type Of<A> = Option<A>;
225/// }
226/// ```
227///
228/// ```ignore
229/// // Invocation
230/// impl_kind! {
231/// impl<E> for ResultBrand<E> {
232/// type Of<A> = Result<A, E>;
233/// }
234/// }
235///
236/// // Expanded code
237/// impl<E> Kind_... for ResultBrand<E> {
238/// type Of<A> = Result<A, E>;
239/// }
240/// ```
241///
242/// ```ignore
243/// // Invocation
244/// impl_kind! {
245/// impl<E> for MyBrand<E> where E: Clone {
246/// type Of<A> = MyType<A, E>;
247/// type SendOf<A> = MySendType<A, E>;
248/// }
249/// }
250///
251/// // Expanded code
252/// impl<E> Kind_... for MyBrand<E> where E: Clone {
253/// type Of<A> = MyType<A, E>;
254/// type SendOf<A> = MySendType<A, E>;
255/// }
256/// ```
257///
258/// ```ignore
259/// // Invocation
260/// // Corresponds to: trait_kind!(type Of<T: Display>;);
261/// impl_kind! {
262/// for DisplayBrand {
263/// // Bounds here are used to infer the correct `Kind` trait name
264/// type Of<T: Display> = DisplayType<T>;
265/// }
266/// }
267///
268/// // Expanded code
269/// impl Kind_... for DisplayBrand {
270/// type Of<T: Display> = DisplayType<T>;
271/// }
272/// ```
273#[proc_macro]
274pub fn impl_kind(input: TokenStream) -> TokenStream {
275 let input = parse_macro_input!(input as ImplKindInput);
276 match impl_kind_worker(input) {
277 Ok(tokens) => tokens.into(),
278 Err(e) => e.to_compile_error().into(),
279 }
280}
281
282/// Applies a brand to type arguments.
283///
284/// This macro projects a brand type to its concrete type using the appropriate
285/// `Kind` trait. It uses a syntax that mimics a fully qualified path, where the
286/// `Kind` trait is specified by its signature.
287///
288/// ### Syntax
289///
290/// ```ignore
291/// Apply!(<Brand as Kind!( KindSignature )>::AssocType<Args>)
292/// ```
293///
294/// ### Parameters
295///
296/// * `Brand`: The brand type (e.g., `OptionBrand`).
297/// * `KindSignature`: A list of associated type definitions defining the `Kind` trait schema.
298/// * `AssocType`: The associated type to project (e.g., `Of`).
299/// * `Args`: The concrete arguments to apply.
300///
301/// ### Generates
302///
303/// The concrete type resulting from applying the brand to the arguments.
304///
305/// ### Examples
306///
307/// ```ignore
308/// // Invocation
309/// // Applies MyBrand to lifetime 'static and type String.
310/// type Concrete = Apply!(<MyBrand as Kind!( type Of<'a, T>; )>::Of<'static, String>);
311///
312/// // Expanded code
313/// type Concrete = <MyBrand as Kind_...>::Of<'static, String>;
314/// ```
315///
316/// ```ignore
317/// // Invocation
318/// // Applies MyBrand to a generic type T with bounds.
319/// type Concrete = Apply!(<MyBrand as Kind!( type Of<T: Clone>; )>::Of<T>);
320///
321/// // Expanded code
322/// type Concrete = <MyBrand as Kind_...>::Of<T>;
323/// ```
324///
325/// ```ignore
326/// // Invocation
327/// // Complex example with lifetimes, types, and output bounds.
328/// type Concrete = Apply!(<MyBrand as Kind!( type Of<'a, T: Clone + Debug>: Display; )>::Of<'a, T>);
329///
330/// // Expanded code
331/// type Concrete = <MyBrand as Kind_...>::Of<'a, T>;
332/// ```
333///
334/// ```ignore
335/// // Invocation
336/// // Use a custom associated type for projection.
337/// type Concrete = Apply!(<MyBrand as Kind!( type Of<T>; type SendOf<T>; )>::SendOf<T>);
338///
339/// // Expanded code
340/// type Concrete = <MyBrand as Kind_...>::SendOf<T>;
341/// ```
342#[proc_macro]
343#[allow(non_snake_case)]
344pub fn Apply(input: TokenStream) -> TokenStream {
345 let input = parse_macro_input!(input as ApplyInput);
346 match apply_worker(input) {
347 Ok(tokens) => tokens.into(),
348 Err(e) => e.to_compile_error().into(),
349 }
350}
351
352/// Generates re-exports for all public free functions in a directory.
353///
354/// This macro scans the specified directory for Rust files, parses them to find public free functions,
355/// and generates `pub use` statements for them. It supports aliasing to resolve name conflicts.
356///
357/// ### Syntax
358///
359/// ```ignore
360/// generate_function_re_exports!("path/to/directory", {
361/// original_name: aliased_name,
362/// ...
363/// })
364/// ```
365///
366/// ### Parameters
367///
368/// * `path/to/directory`: The path to the directory containing the modules, relative to the crate root.
369/// * `aliases`: A map of function names to their desired aliases.
370///
371/// ### Generates
372///
373/// `pub use` statements for each public function found in the directory.
374///
375/// ### Examples
376///
377/// ```ignore
378/// // Invocation
379/// generate_function_re_exports!("src/classes", {
380/// identity: category_identity,
381/// new: fn_new,
382/// });
383///
384/// // Expanded code
385/// pub use src::classes::category::identity as category_identity;
386/// pub use src::classes::function::new as fn_new;
387/// // ... other re-exports
388/// ```
389#[proc_macro]
390pub fn generate_function_re_exports(input: TokenStream) -> TokenStream {
391 let input = parse_macro_input!(input as ReExportInput);
392 generate_re_exports_worker(&input, &FunctionFormatter).into()
393}
394
395/// Generates re-exports for all public traits in a directory.
396///
397/// This macro scans the specified directory for Rust files, parses them to find public traits,
398/// and generates `pub use` statements for them.
399///
400/// ### Syntax
401///
402/// ```ignore
403/// generate_trait_re_exports!("path/to/directory", {
404/// original_name: aliased_name,
405/// ...
406/// })
407/// ```
408///
409/// ### Parameters
410///
411/// * `path/to/directory`: The path to the directory containing the modules, relative to the crate root.
412/// * `aliases`: A map of trait names to their desired aliases (optional).
413///
414/// ### Generates
415///
416/// `pub use` statements for each public trait found in the directory.
417///
418/// ### Examples
419///
420/// ```ignore
421/// // Invocation
422/// generate_trait_re_exports!("src/classes", {});
423///
424/// // Expanded code
425/// pub use src::classes::functor::Functor;
426/// pub use src::classes::monad::Monad;
427/// // ... other re-exports
428/// ```
429#[proc_macro]
430pub fn generate_trait_re_exports(input: TokenStream) -> TokenStream {
431 let input = parse_macro_input!(input as ReExportInput);
432 generate_re_exports_worker(&input, &TraitFormatter).into()
433}
434
435/// Generates a Hindley-Milner style type signature for a function.
436///
437/// This macro analyzes the function signature and generates a documentation comment
438/// containing the corresponding Hindley-Milner type signature.
439///
440/// When used within a module annotated with [`#[document_module]`](macro@document_module),
441/// it automatically resolves `Self` and associated types based on the module's projection map.
442///
443/// ### Syntax
444///
445/// ```ignore
446/// #[document_signature]
447/// pub fn function_name<Generics>(params) -> ReturnType { ... }
448/// ```
449///
450/// When applying this macro to a method inside a trait, you can provide the trait name
451/// as an argument to correctly generate the `Trait self` constraint.
452///
453/// ### Generates
454///
455/// A documentation comment with the generated signature, prepended to the function definition.
456///
457/// ### Examples
458///
459/// ```ignore
460/// // Invocation
461/// #[document_signature]
462/// pub fn map<F: Functor, A, B>(f: impl Fn(A) -> B, fa: F::Of<A>) -> F::Of<B> { ... }
463///
464/// // Expanded code
465/// /// `forall f a b. Functor f => (a -> b, f a) -> f b`
466/// pub fn map<F: Functor, A, B>(f: impl Fn(A) -> B, fa: F::Of<A>) -> F::Of<B> { ... }
467/// ```
468///
469/// ```ignore
470/// // Invocation
471/// #[document_signature]
472/// pub fn foo(x: impl Iterator<Item = String>) -> i32 { ... }
473///
474/// // Expanded code
475/// /// `iterator -> i32`
476/// pub fn foo(x: impl Iterator<Item = String>) -> i32 { ... }
477/// ```
478///
479/// ```ignore
480/// // Invocation
481/// trait Functor {
482/// #[document_signature]
483/// fn map<A, B>(f: impl Fn(A) -> B, fa: Self::Of<A>) -> Self::Of<B>;
484/// }
485///
486/// // Expanded code
487/// trait Functor {
488/// /// `forall self a b. Functor self => (a -> b, self a) -> self b`
489/// fn map<A, B>(f: impl Fn(A) -> B, fa: Self::Of<A>) -> Self::Of<B>;
490/// }
491/// ```
492///
493/// ### Configuration
494///
495/// This macro can be configured via `Cargo.toml` under `[package.metadata.document_signature]`.
496///
497/// * `brand_mappings`: A map of brand struct names to their display names in the signature.
498/// * `apply_macro_aliases`: A list of macro names that should be treated as `Apply!`.
499/// * `ignored_traits`: A list of traits to ignore in the signature constraints.
500///
501/// Example:
502/// ```toml
503/// [package.metadata.document_signature]
504/// brand_mappings = { "OptionBrand" = "Option", "VecBrand" = "Vec" }
505/// apply_macro_aliases = ["MyApply"]
506/// ignored_traits = ["Clone", "Debug"]
507/// ```
508#[proc_macro_attribute]
509pub fn document_signature(
510 attr: TokenStream,
511 item: TokenStream,
512) -> TokenStream {
513 match document_signature_worker(attr.into(), item.into()) {
514 Ok(tokens) => tokens.into(),
515 Err(e) => e.to_compile_error().into(),
516 }
517}
518
519/// Generates documentation for type parameters.
520///
521/// This macro analyzes the item's signature (function, struct, enum, impl block, etc.)
522/// and generates a documentation comment list based on the provided descriptions.
523///
524/// When used within a module annotated with [`#[document_module]`](macro@document_module),
525/// it benefits from automatic `Self` resolution and is applied as part of the module-level
526/// documentation pass.
527///
528/// ### Syntax
529///
530/// ```ignore
531/// #[document_type_parameters(
532/// "Description for first parameter",
533/// ("OverriddenName", "Description for second parameter"),
534/// ...
535/// )]
536/// pub fn function_name<Generics>(params) -> ReturnType { ... }
537/// ```
538///
539/// It can also be used on other items like `impl` blocks:
540///
541/// ```ignore
542/// #[document_type_parameters("Description for T")]
543/// impl<T> MyType<T> { ... }
544/// ```
545///
546/// ### Parameters
547///
548/// * `Descriptions`: A comma-separated list. Each entry can be either a string literal
549/// or a tuple of two string literals `(Name, Description)`.
550///
551/// ### Generates
552///
553/// A list of documentation comments, one for each generic parameter, prepended to the
554/// function definition.
555///
556/// ### Examples
557///
558/// ```ignore
559/// // Invocation
560/// #[document_type_parameters(
561/// "The type of the elements.",
562/// ("E", "The error type.")
563/// )]
564/// pub fn map<T, ERR>(...) { ... }
565///
566/// // Expanded code
567/// /// * `T`: The type of the elements.
568/// /// * `E`: The error type.
569/// pub fn map<T, ERR>(...) { ... }
570/// ```
571///
572/// ### Constraints
573///
574/// * The number of arguments must exactly match the number of generic parameters
575/// (including lifetimes, types, and const generics) in the function signature.
576#[proc_macro_attribute]
577pub fn document_type_parameters(
578 attr: TokenStream,
579 item: TokenStream,
580) -> TokenStream {
581 match document_type_parameters_worker(attr.into(), item.into()) {
582 Ok(tokens) => tokens.into(),
583 Err(e) => e.to_compile_error().into(),
584 }
585}
586
587/// Generates documentation for a function's parameters.
588///
589/// This macro analyzes the function signature and generates a documentation comment
590/// list based on the provided descriptions. It also handles curried return types.
591///
592/// It can also be used on `impl` blocks to provide a common description for the receiver (`self`)
593/// parameter of methods within the block.
594///
595/// ### Syntax
596///
597/// For functions:
598/// ```ignore
599/// #[document_parameters(
600/// "Description for first parameter",
601/// ("overridden_name", "Description for second parameter"),
602/// ...
603/// )]
604/// pub fn function_name(params) -> impl Fn(...) { ... }
605/// ```
606///
607/// For `impl` blocks:
608/// ```ignore
609/// #[document_parameters("Description for receiver")]
610/// impl MyType {
611/// #[document_parameters]
612/// pub fn method_with_receiver(&self) { ... }
613///
614/// #[document_parameters("Description for arg")]
615/// pub fn method_with_args(&self, arg: i32) { ... }
616/// }
617/// ```
618///
619/// ### Parameters
620///
621/// * `Descriptions`: A comma-separated list. Each entry can be either a string literal
622/// or a tuple of two string literals `(Name, Description)`.
623/// * For `impl` blocks: Exactly one string literal describing the receiver parameter.
624///
625/// ### Generates
626///
627/// A list of documentation comments, one for each parameter, prepended to the
628/// function definition.
629///
630/// ### Examples
631///
632/// ```ignore
633/// // Invocation
634/// #[document_parameters(
635/// "The first input value.",
636/// ("y", "The second input value.")
637/// )]
638/// pub fn foo(x: i32) -> impl Fn(i32) -> i32 { ... }
639///
640/// // Expanded code
641/// /// * `x`: The first input value.
642/// /// * `y`: The second input value.
643/// pub fn foo(x: i32) -> impl Fn(i32) -> i32 { ... }
644/// ```
645///
646/// ```ignore
647/// // Invocation on impl block
648/// #[document_parameters("The list instance")]
649/// impl<A> MyList<A> {
650/// #[document_parameters("The element to push")]
651/// pub fn push(&mut self, item: A) { ... }
652/// }
653///
654/// // Expanded code
655/// impl<A> MyList<A> {
656/// /// * `&mut self`: The list instance
657/// /// * `item`: The element to push
658/// pub fn push(&mut self, item: A) { ... }
659/// }
660/// ```
661///
662/// ### Constraints
663///
664/// * The number of arguments must exactly match the number of function parameters
665/// (excluding `self` but including parameters from curried return types).
666///
667/// ### Configuration
668///
669/// This macro can be configured via `Cargo.toml` under `[package.metadata.document_signature]`.
670///
671/// * `apply_macro_aliases`: A list of macro names that should be treated as `Apply!` for curried parameter extraction.
672///
673/// Example:
674/// ```toml
675/// [package.metadata.document_signature]
676/// apply_macro_aliases = ["MyApply"]
677/// ```
678#[proc_macro_attribute]
679pub fn document_parameters(
680 attr: TokenStream,
681 item: TokenStream,
682) -> TokenStream {
683 match document_parameters_worker(attr.into(), item.into()) {
684 Ok(tokens) => tokens.into(),
685 Err(e) => e.to_compile_error().into(),
686 }
687}
688
689/// Generates documentation for struct fields or enum variant fields.
690///
691/// This macro analyzes a struct or enum and generates documentation comments for its fields.
692/// It can be used on named structs, tuple structs, and enums with variants that have fields.
693///
694/// ### Syntax
695///
696/// For named structs:
697/// ```ignore
698/// #[document_fields(
699/// field_name: "Description for field_name",
700/// other_field: "Description for other_field",
701/// ...
702/// )]
703/// pub struct MyStruct {
704/// pub field_name: Type1,
705/// pub other_field: Type2,
706/// }
707/// ```
708///
709/// For tuple structs:
710/// ```ignore
711/// #[document_fields(
712/// "Description for first field",
713/// "Description for second field",
714/// ...
715/// )]
716/// pub struct MyTuple(Type1, Type2);
717/// ```
718///
719/// For enums (similar to [`#[document_module]`](macro@document_module)):
720/// ```ignore
721/// #[document_fields]
722/// pub enum MyEnum {
723/// #[document_fields(
724/// field1: "Description for field1",
725/// field2: "Description for field2"
726/// )]
727/// Variant1 {
728/// field1: Type1,
729/// field2: Type2,
730/// },
731///
732/// #[document_fields(
733/// "Description for tuple field"
734/// )]
735/// Variant2(Type3),
736/// }
737/// ```
738///
739/// ### Parameters
740///
741/// * For structs with named fields: A comma-separated list of `field_ident: "description"` pairs.
742/// * For structs with tuple fields: A comma-separated list of string literal descriptions, in order.
743/// * For enums: No arguments on the enum itself. Use `#[document_fields(...)]` on individual variants.
744///
745/// ### Generates
746///
747/// A list of documentation comments, one for each field, prepended to the struct or variant definition.
748///
749/// ### Examples
750///
751/// ```ignore
752/// // Invocation (named struct)
753/// #[document_fields(
754/// x: "The x coordinate",
755/// y: "The y coordinate"
756/// )]
757/// pub struct Point {
758/// pub x: i32,
759/// pub y: i32,
760/// }
761///
762/// // Expanded code
763/// /// * `x`: The x coordinate
764/// /// * `y`: The y coordinate
765/// pub struct Point {
766/// pub x: i32,
767/// pub y: i32,
768/// }
769/// ```
770///
771/// ```ignore
772/// // Invocation (tuple struct)
773/// #[document_fields(
774/// "The wrapped morphism"
775/// )]
776/// pub struct Endomorphism<'a, C, A>(
777/// pub Apply!(<C as Kind!(type Of<'a, T, U>;)>::Of<'a, A, A>),
778/// );
779///
780/// // Expanded code
781/// /// * `0`: The wrapped morphism
782/// pub struct Endomorphism<'a, C, A>(
783/// pub Apply!(<C as Kind!(type Of<'a, T, U>;)>::Of<'a, A, A>),
784/// );
785/// ```
786///
787/// ```ignore
788/// // Invocation (enum with variants)
789/// #[document_fields]
790/// pub enum FreeInner<F, A> {
791/// Pure(A),
792///
793/// #[document_fields(
794/// head: "The initial computation.",
795/// continuations: "The list of continuations."
796/// )]
797/// Bind {
798/// head: Box<Free<F, A>>,
799/// continuations: CatList<Continuation<F>>,
800/// },
801/// }
802///
803/// // Expanded code
804/// pub enum FreeInner<F, A> {
805/// Pure(A),
806///
807/// /// * `head`: The initial computation.
808/// /// * `continuations`: The list of continuations.
809/// Bind {
810/// head: Box<Free<F, A>>,
811/// continuations: CatList<Continuation<F>>,
812/// },
813/// }
814/// ```
815///
816/// ### Constraints
817///
818/// * All fields must be documented - the macro will error if any field is missing documentation.
819/// * The macro cannot be used on zero-sized types (unit structs/variants or structs/variants with no fields).
820/// * For named fields, you must use the `field_name: "description"` syntax.
821/// * For tuple fields, you must use just `"description"` (no field names).
822/// * For enums, the outer `#[document_fields]` must have no arguments.
823/// * The macro will error if the wrong syntax is used for the field type.
824#[proc_macro_attribute]
825pub fn document_fields(
826 attr: TokenStream,
827 item: TokenStream,
828) -> TokenStream {
829 match document_fields_worker(attr.into(), item.into()) {
830 Ok(tokens) => tokens.into(),
831 Err(e) => e.to_compile_error().into(),
832 }
833}
834
835/// Orchestrates documentation generation for an entire module.
836///
837/// This macro provides a centralized way to handle documentation for Higher-Kinded Type (HKT)
838/// implementations. It performs a two-pass analysis of the module:
839///
840/// 1. **Context Extraction**: It scans for `impl_kind!` invocations and standard `impl` blocks
841/// to build a comprehensive mapping of associated types (a "projection map").
842/// 2. **Documentation Generation**: It processes all methods annotated with [`#[document_signature]`](macro@document_signature)
843/// or [`#[document_type_parameters]`](macro@document_type_parameters), resolving `Self` and associated types
844/// using the collected context.
845/// 3. **Validation** (Optional): Checks that impl blocks and methods have appropriate documentation
846/// attributes and emits compile-time warnings for missing documentation.
847///
848/// ### Syntax
849///
850/// Due to inner macro attributes being unstable, use the following wrapper pattern:
851///
852/// ```ignore
853/// #[fp_macros::document_module]
854/// mod inner {
855/// // ... module content ...
856/// }
857/// pub use inner::*;
858/// ```
859///
860/// To disable validation warnings:
861///
862/// ```ignore
863/// #[fp_macros::document_module(no_validation)]
864/// mod inner {
865/// // ... module content ...
866/// }
867/// pub use inner::*;
868/// ```
869///
870/// ### Generates
871///
872/// In-place replacement of [`#[document_signature]`](macro@document_signature) and
873/// [`#[document_type_parameters]`](macro@document_type_parameters) attributes with generated documentation
874/// comments. It also resolves `Self` and `Self::AssocType` references to their concrete
875/// types based on the module's projection map.
876///
877/// ### Attributes
878///
879/// The macro supports several documentation-specific attributes for configuration:
880///
881/// * `#[document_default]`: (Used inside `impl` or `impl_kind!`) Marks an associated type as the
882/// default to use when resolving bare `Self` references.
883/// * `#[document_use = "AssocName"]`: (Used on `impl` or `fn`) Explicitly specifies which
884/// associated type definition to use for resolution within that scope.
885///
886/// ### Validation
887///
888/// By default, `document_module` validates that impl blocks and methods have appropriate
889/// documentation attributes and emits compile-time errors for missing documentation.
890///
891/// To disable validation, use `#[document_module(no_validation)]`.
892///
893/// #### Validation Rules
894///
895/// An impl block should have:
896/// * `#[document_type_parameters]` if it has type parameters
897/// * `#[document_parameters]` if it contains methods with receiver parameters (self, &self, &mut self)
898///
899/// A method should have:
900/// * `#[document_signature]` - always recommended for documenting the Hindley-Milner signature
901/// * `#[document_type_parameters]` if it has type parameters
902/// * `#[document_parameters]` if it has non-receiver parameters
903///
904/// #### Examples of Validation
905///
906/// ```ignore
907/// // This will emit warnings:
908/// #[fp_macros::document_module]
909/// mod inner {
910/// pub struct MyType;
911///
912/// // WARNING: Impl block contains methods with receiver parameters
913/// // but no #[document_parameters] attribute
914/// impl MyType {
915/// // WARNING: Method should have #[document_signature] attribute
916/// pub fn process(&self, x: i32) -> i32 { x }
917/// }
918/// }
919/// ```
920///
921/// ```ignore
922/// // Properly documented (no warnings):
923/// #[fp_macros::document_module]
924/// mod inner {
925/// pub struct MyType;
926///
927/// #[document_parameters("The MyType instance")]
928/// impl MyType {
929/// #[document_signature]
930/// #[document_parameters("The input value")]
931/// pub fn process(&self, x: i32) -> i32 { x }
932/// }
933/// }
934/// ```
935///
936/// ```ignore
937/// // Disable validation to suppress warnings:
938/// #[fp_macros::document_module(no_validation)]
939/// mod inner {
940/// // ... undocumented code won't produce warnings ...
941/// }
942/// ```
943///
944/// ### Hierarchical Configuration
945///
946/// When resolving the concrete type of `Self`, the macro follows this precedence:
947///
948/// 1. **Method Override**: `#[document_use = "AssocName"]` on the method.
949/// 2. **Impl Block Override**: `#[document_use = "AssocName"]` on the `impl` block.
950/// 3. **(Type, Trait)-Scoped Default**: `#[document_default]` on the associated type definition
951/// in a trait `impl` block.
952/// 4. **Module Default**: `#[document_default]` on the associated type definition in `impl_kind!`.
953///
954/// ### Examples
955///
956/// ```ignore
957/// // Invocation
958/// #[fp_macros::document_module]
959/// mod inner {
960/// use super::*;
961///
962/// impl_kind! {
963/// for MyBrand {
964/// #[document_default]
965/// type Of<'a, T: 'a>: 'a = MyType<T>;
966/// }
967/// }
968///
969/// impl Functor for MyBrand {
970/// #[document_signature]
971/// fn map<'a, A: 'a, B: 'a, Func>(
972/// f: Func,
973/// fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
974/// ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
975/// where
976/// Func: Fn(A) -> B + 'a
977/// {
978/// todo!()
979/// }
980/// }
981/// }
982/// pub use inner::*;
983///
984/// // Expanded code
985/// mod inner {
986/// use super::*;
987///
988/// // ... generated Kind implementations ...
989///
990/// impl Functor for MyBrand {
991/// /// `forall a b. (a -> b, MyType a) -> MyType b`
992/// fn map<'a, A: 'a, B: 'a, Func>(
993/// f: Func,
994/// fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
995/// ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
996/// where
997/// Func: Fn(A) -> B + 'a
998/// {
999/// todo!()
1000/// }
1001/// }
1002/// }
1003/// pub use inner::*;
1004/// ```
1005#[proc_macro_attribute]
1006pub fn document_module(
1007 attr: TokenStream,
1008 item: TokenStream,
1009) -> TokenStream {
1010 match document_module_worker(attr.into(), item.into()) {
1011 Ok(tokens) => tokens.into(),
1012 Err(e) => e.to_compile_error().into(),
1013 }
1014}