Skip to main content

fp_macros/
lib.rs

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