Skip to main content

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}