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/// /// ### Type Signature
472/// /// `forall f a b. Functor f => (a -> b, f a) -> f b`
473/// pub fn map<F: Functor, A, B>(f: impl Fn(A) -> B, fa: F::Of<A>) -> F::Of<B> { ... }
474/// ```
475///
476/// ```ignore
477/// // Invocation
478/// #[document_signature]
479/// pub fn foo(x: impl Iterator<Item = String>) -> i32 { ... }
480///
481/// // Expanded code
482/// /// ### Type Signature
483/// /// `iterator -> i32`
484/// pub fn foo(x: impl Iterator<Item = String>) -> i32 { ... }
485/// ```
486///
487/// ```ignore
488/// // Invocation
489/// trait Functor {
490///     #[document_signature]
491///     fn map<A, B>(f: impl Fn(A) -> B, fa: Self::Of<A>) -> Self::Of<B>;
492/// }
493///
494/// // Expanded code
495/// trait Functor {
496///     /// ### Type Signature
497///     /// `forall self a b. Functor self => (a -> b, self a) -> self b`
498///     fn map<A, B>(f: impl Fn(A) -> B, fa: Self::Of<A>) -> Self::Of<B>;
499/// }
500/// ```
501///
502/// ### Configuration
503///
504/// This macro can be configured via `Cargo.toml` under `[package.metadata.document_signature]`.
505///
506/// * `brand_mappings`: A map of brand struct names to their display names in the signature.
507/// * `apply_macro_aliases`: A list of macro names that should be treated as `Apply!`.
508/// * `ignored_traits`: A list of traits to ignore in the signature constraints.
509///
510/// Example:
511/// ```toml
512/// [package.metadata.document_signature]
513/// brand_mappings = { "OptionBrand" = "Option", "VecBrand" = "Vec" }
514/// apply_macro_aliases = ["MyApply"]
515/// ignored_traits = ["Clone", "Debug"]
516/// ```
517#[proc_macro_attribute]
518pub fn document_signature(
519	attr: TokenStream,
520	item: TokenStream,
521) -> TokenStream {
522	match document_signature_worker(attr.into(), item.into()) {
523		Ok(tokens) => tokens.into(),
524		Err(e) => e.to_compile_error().into(),
525	}
526}
527
528/// Generates documentation for type parameters.
529///
530/// This macro analyzes the item's signature (function, struct, enum, impl block, etc.)
531/// and generates a documentation comment list based on the provided descriptions.
532///
533/// When used within a module annotated with [`#[document_module]`](macro@document_module),
534/// it benefits from automatic `Self` resolution and is applied as part of the module-level
535/// documentation pass.
536///
537/// ### Syntax
538///
539/// ```ignore
540/// #[document_type_parameters(
541///     "Description for first parameter",
542///     ("OverriddenName", "Description for second parameter"),
543///     ...
544/// )]
545/// pub fn function_name<Generics>(params) -> ReturnType { ... }
546/// ```
547///
548/// It can also be used on other items like `impl` blocks:
549///
550/// ```ignore
551/// #[document_type_parameters("Description for T")]
552/// impl<T> MyType<T> { ... }
553/// ```
554///
555/// * `Descriptions`: A comma-separated list. Each entry can be either a string literal
556///   or a tuple of two string literals `(Name, Description)`.
557///
558/// ### Generates
559///
560/// A list of documentation comments, one for each generic parameter, prepended to the
561/// function definition.
562///
563/// ### Examples
564///
565/// ```ignore
566/// // Invocation
567/// #[document_type_parameters(
568///     "The type of the elements.",
569///     ("E", "The error type.")
570/// )]
571/// pub fn map<T, ERR>(...) { ... }
572///
573/// // Expanded code
574/// /// ### Type Parameters
575/// /// * `T`: The type of the elements.
576/// /// * `E`: The error type.
577/// pub fn map<T, ERR>(...) { ... }
578/// ```
579///
580/// ### Constraints
581///
582/// * The number of arguments must exactly match the number of generic parameters
583///   (including lifetimes, types, and const generics) in the function signature.
584#[proc_macro_attribute]
585pub fn document_type_parameters(
586	attr: TokenStream,
587	item: TokenStream,
588) -> TokenStream {
589	match document_type_parameters_worker(attr.into(), item.into()) {
590		Ok(tokens) => tokens.into(),
591		Err(e) => e.to_compile_error().into(),
592	}
593}
594
595/// Generates documentation for a function's parameters.
596///
597/// This macro analyzes the function signature and generates a documentation comment
598/// list based on the provided descriptions. It also handles curried return types.
599///
600/// It can also be used on `impl` blocks to provide a common description for the receiver (`self`)
601/// parameter of methods within the block.
602///
603/// ### Syntax
604///
605/// For functions:
606/// ```ignore
607/// #[document_parameters(
608///     "Description for first parameter",
609///     ("overridden_name", "Description for second parameter"),
610///     ...
611/// )]
612/// pub fn function_name(params) -> impl Fn(...) { ... }
613/// ```
614///
615/// For `impl` blocks:
616/// ```ignore
617/// #[document_parameters("Description for receiver")]
618/// impl MyType {
619///     #[document_parameters]
620///     pub fn method_with_receiver(&self) { ... }
621///
622///     #[document_parameters("Description for arg")]
623///     pub fn method_with_args(&self, arg: i32) { ... }
624/// }
625/// ```
626///
627/// * `Descriptions`: A comma-separated list. Each entry can be either a string literal
628///   or a tuple of two string literals `(Name, Description)`.
629/// * For `impl` blocks: Exactly one string literal describing the receiver parameter.
630///
631/// ### Generates
632///
633/// A list of documentation comments, one for each parameter, prepended to the
634/// function definition.
635///
636/// ### Examples
637///
638/// ```ignore
639/// // Invocation
640/// #[document_parameters(
641///     "The first input value.",
642///     ("y", "The second input value.")
643/// )]
644/// pub fn foo(x: i32) -> impl Fn(i32) -> i32 { ... }
645///
646/// // Expanded code
647/// /// ### Parameters
648/// /// * `x`: The first input value.
649/// /// * `y`: The second input value.
650/// pub fn foo(x: i32) -> impl Fn(i32) -> i32 { ... }
651/// ```
652///
653/// ```ignore
654/// // Invocation on impl block
655/// #[document_parameters("The list instance")]
656/// impl<A> MyList<A> {
657///     #[document_parameters("The element to push")]
658///     pub fn push(&mut self, item: A) { ... }
659/// }
660///
661/// // Expanded code
662/// impl<A> MyList<A> {
663///     /// ### Parameters
664///     /// * `&mut self`: The list instance
665///     /// * `item`: The element to push
666///     pub fn push(&mut self, item: A) { ... }
667/// }
668/// ```
669///
670/// ### Constraints
671///
672/// * The number of arguments must exactly match the number of function parameters
673///   (excluding `self` but including parameters from curried return types).
674///
675/// ### Configuration
676///
677/// This macro can be configured via `Cargo.toml` under `[package.metadata.document_signature]`.
678///
679/// * `apply_macro_aliases`: A list of macro names that should be treated as `Apply!` for curried parameter extraction.
680///
681/// Example:
682/// ```toml
683/// [package.metadata.document_signature]
684/// apply_macro_aliases = ["MyApply"]
685/// ```
686#[proc_macro_attribute]
687pub fn document_parameters(
688	attr: TokenStream,
689	item: TokenStream,
690) -> TokenStream {
691	match document_parameters_worker(attr.into(), item.into()) {
692		Ok(tokens) => tokens.into(),
693		Err(e) => e.to_compile_error().into(),
694	}
695}
696
697/// Generates documentation for the return value of a function.
698///
699/// This macro adds a "Returns" section to the function's documentation.
700///
701/// ### Syntax
702///
703/// ```ignore
704/// #[document_returns("Description of the return value.")]
705/// pub fn foo() -> i32 { ... }
706/// ```
707///
708/// ### Generates
709///
710/// A documentation comment describing the return value.
711///
712/// ### Examples
713///
714/// ```ignore
715/// // Invocation
716/// #[document_returns("The sum of x and y.")]
717/// pub fn add(x: i32, y: i32) -> i32 { ... }
718///
719/// // Expanded code
720/// /// ### Returns
721/// /// The sum of x and y.
722/// pub fn add(x: i32, y: i32) -> i32 { ... }
723/// ```
724#[proc_macro_attribute]
725pub fn document_returns(
726	attr: TokenStream,
727	item: TokenStream,
728) -> TokenStream {
729	match document_returns_worker(attr.into(), item.into()) {
730		Ok(tokens) => tokens.into(),
731		Err(e) => e.to_compile_error().into(),
732	}
733}
734
735/// Inserts a `### Examples` heading and validates doc comment code blocks.
736///
737/// This attribute macro expands in-place to a `### Examples` heading. Example
738/// code is written as regular doc comments using fenced code blocks after the
739/// attribute. Every Rust code block must contain at least one assertion macro
740/// invocation (e.g., `assert_eq!`, `assert!`).
741///
742/// ### Syntax
743///
744/// ```ignore
745/// #[document_examples]
746/// ///
747/// /// ```
748/// /// let result = add(1, 2);
749/// /// assert_eq!(result, 3);
750/// /// ```
751/// pub fn add(x: i32, y: i32) -> i32 { ... }
752/// ```
753///
754/// ### Generates
755///
756/// A `### Examples` heading is inserted at the attribute's position. The code
757/// blocks in the doc comments are validated but not modified.
758///
759/// ### Errors
760///
761/// * Arguments are provided to the attribute.
762/// * No Rust code block is found in the doc comments.
763/// * A Rust code block does not contain an assertion macro invocation.
764/// * The attribute is applied more than once to the same function.
765#[proc_macro_attribute]
766pub fn document_examples(
767	attr: TokenStream,
768	item: TokenStream,
769) -> TokenStream {
770	match document_examples_worker(attr.into(), item.into()) {
771		Ok(tokens) => tokens.into(),
772		Err(e) => e.to_compile_error().into(),
773	}
774}
775
776/// Generates documentation for struct fields or enum variant fields.
777///
778/// This macro analyzes a struct or enum and generates documentation comments for its fields.
779/// It can be used on named structs, tuple structs, and enums with variants that have fields.
780///
781/// ### Syntax
782///
783/// For named structs:
784/// ```ignore
785/// #[document_fields(
786///     field_name: "Description for field_name",
787///     other_field: "Description for other_field",
788///     ...
789/// )]
790/// pub struct MyStruct {
791///     pub field_name: Type1,
792///     pub other_field: Type2,
793/// }
794/// ```
795///
796/// For tuple structs:
797/// ```ignore
798/// #[document_fields(
799///     "Description for first field",
800///     "Description for second field",
801///     ...
802/// )]
803/// pub struct MyTuple(Type1, Type2);
804/// ```
805///
806/// For enums (similar to [`#[document_module]`](macro@document_module)):
807/// ```ignore
808/// #[document_fields]
809/// pub enum MyEnum {
810///     #[document_fields(
811///         field1: "Description for field1",
812///         field2: "Description for field2"
813///     )]
814///     Variant1 {
815///         field1: Type1,
816///         field2: Type2,
817///     },
818///
819///     #[document_fields(
820///         "Description for tuple field"
821///     )]
822///     Variant2(Type3),
823/// }
824/// ```
825///
826/// * For structs with named fields: A comma-separated list of `field_ident: "description"` pairs.
827/// * For structs with tuple fields: A comma-separated list of string literal descriptions, in order.
828/// * For enums: No arguments on the enum itself. Use `#[document_fields(...)]` on individual variants.
829///
830/// ### Generates
831///
832/// A list of documentation comments, one for each field, prepended to the struct or variant definition.
833///
834/// ### Examples
835///
836/// ```ignore
837/// // Invocation (named struct)
838/// #[document_fields(
839///     x: "The x coordinate",
840///     y: "The y coordinate"
841/// )]
842/// pub struct Point {
843///     pub x: i32,
844///     pub y: i32,
845/// }
846///
847/// // Expanded code
848/// /// ### Fields
849/// /// * `x`: The x coordinate
850/// /// * `y`: The y coordinate
851/// pub struct Point {
852///     pub x: i32,
853///     pub y: i32,
854/// }
855/// ```
856///
857/// ```ignore
858/// // Invocation (tuple struct)
859/// #[document_fields(
860///     "The wrapped morphism"
861/// )]
862/// pub struct Endomorphism<'a, C, A>(
863///     pub Apply!(<C as Kind!(type Of<'a, T, U>;)>::Of<'a, A, A>),
864/// );
865///
866/// // Expanded code
867/// /// ### Fields
868/// /// * `0`: The wrapped morphism
869/// pub struct Endomorphism<'a, C, A>(
870///     pub Apply!(<C as Kind!(type Of<'a, T, U>;)>::Of<'a, A, A>),
871/// );
872/// ```
873///
874/// ```ignore
875/// // Invocation (enum with variants)
876/// #[document_fields]
877/// pub enum FreeInner<F, A> {
878///     Pure(A),
879///
880///     #[document_fields(
881///         head: "The initial computation.",
882///         continuations: "The list of continuations."
883///     )]
884///     Bind {
885///         head: Box<Free<F, A>>,
886///         continuations: CatList<Continuation<F>>,
887///     },
888/// }
889///
890/// // Expanded code
891/// pub enum FreeInner<F, A> {
892///     Pure(A),
893///
894///     /// * `head`: The initial computation.
895///     /// * `continuations`: The list of continuations.
896///     Bind {
897///         head: Box<Free<F, A>>,
898///         continuations: CatList<Continuation<F>>,
899///     },
900/// }
901/// ```
902///
903/// ### Constraints
904///
905/// * All fields must be documented - the macro will error if any field is missing documentation.
906/// * The macro cannot be used on zero-sized types (unit structs/variants or structs/variants with no fields).
907/// * For named fields, you must use the `field_name: "description"` syntax.
908/// * For tuple fields, you must use just `"description"` (no field names).
909/// * For enums, the outer `#[document_fields]` must have no arguments.
910/// * The macro will error if the wrong syntax is used for the field type.
911#[proc_macro_attribute]
912pub fn document_fields(
913	attr: TokenStream,
914	item: TokenStream,
915) -> TokenStream {
916	match document_fields_worker(attr.into(), item.into()) {
917		Ok(tokens) => tokens.into(),
918		Err(e) => e.to_compile_error().into(),
919	}
920}
921
922/// Orchestrates documentation generation for an entire module.
923///
924/// This macro provides a centralized way to handle documentation for Higher-Kinded Type (HKT)
925/// implementations. It performs a two-pass analysis of the module:
926///
927/// 1. **Context Extraction**: It scans for `impl_kind!` invocations and standard `impl` blocks
928///    to build a comprehensive mapping of associated types (a "projection map").
929/// 2. **Documentation Generation**: It processes all methods annotated with [`#[document_signature]`](macro@document_signature)
930///    or [`#[document_type_parameters]`](macro@document_type_parameters), resolving `Self` and associated types
931///    using the collected context.
932/// 3. **Validation** (Optional): Checks that impl blocks and methods have appropriate documentation
933///    attributes and emits compile-time warnings for missing documentation.
934///
935/// ### Syntax
936///
937/// Due to inner macro attributes being unstable, use the following wrapper pattern:
938///
939/// ```ignore
940/// #[fp_macros::document_module]
941/// mod inner {
942///     // ... module content ...
943/// }
944/// pub use inner::*;
945/// ```
946///
947/// To disable validation warnings:
948///
949/// ```ignore
950/// #[fp_macros::document_module(no_validation)]
951/// mod inner {
952///     // ... module content ...
953/// }
954/// pub use inner::*;
955/// ```
956///
957/// ### Generates
958///
959/// In-place replacement of [`#[document_signature]`](macro@document_signature) and
960/// [`#[document_type_parameters]`](macro@document_type_parameters) attributes with generated documentation
961/// comments. It also resolves `Self` and `Self::AssocType` references to their concrete
962/// types based on the module's projection map.
963///
964/// ### Attributes
965///
966/// The macro supports several documentation-specific attributes for configuration:
967///
968/// * `#[document_default]`: (Used inside `impl` or `impl_kind!`) Marks an associated type as the
969///   default to use when resolving bare `Self` references.
970/// * `#[document_use = "AssocName"]`: (Used on `impl` or `fn`) Explicitly specifies which
971///   associated type definition to use for resolution within that scope.
972///
973/// ### Validation
974///
975/// By default, `document_module` validates that impl blocks and methods have appropriate
976/// documentation attributes and emits compile-time warnings for missing documentation.
977///
978/// To disable validation, use `#[document_module(no_validation)]`.
979///
980/// #### Validation Rules
981///
982/// An impl block or trait definition should have:
983/// * `#[document_type_parameters]` if it has type parameters
984/// * `#[document_parameters]` if it contains methods with receiver parameters (self, &self, &mut self)
985///
986/// A method should have:
987/// * `#[document_signature]` - always recommended for documenting the Hindley-Milner signature
988/// * `#[document_type_parameters]` if it has type parameters
989/// * `#[document_parameters]` if it has non-receiver parameters
990/// * `#[document_returns]` if it has a return type
991/// * `#[document_examples]` - always recommended
992///
993/// A free function should have:
994/// * `#[document_examples]` - always recommended
995///
996/// Documentation attributes must not be duplicated and must appear in canonical order:
997/// `#[document_signature]` → `#[document_type_parameters]` → `#[document_parameters]` →
998/// `#[document_returns]` → `#[document_examples]`.
999///
1000/// Additionally, a lint warns when a named generic type parameter could be replaced with
1001/// `impl Trait` (i.e., it has trait bounds, appears in exactly one parameter position, does
1002/// not appear in the return type, and is not cross-referenced by other type parameters).
1003/// This lint skips trait implementations. Suppress it on individual functions or methods
1004/// with `#[allow_named_generics]`.
1005///
1006/// #### Examples of Validation
1007///
1008/// ```ignore
1009/// // This will emit warnings:
1010/// #[fp_macros::document_module]
1011/// mod inner {
1012///     pub struct MyType;
1013///
1014///     // WARNING: Impl block contains methods with receiver parameters
1015///     // but no #[document_parameters] attribute
1016///     impl MyType {
1017///         // WARNING: Method should have #[document_signature] attribute
1018///         // WARNING: Method has parameters but no #[document_parameters] attribute
1019///         // WARNING: Method has a return type but no #[document_returns] attribute
1020///         // WARNING: Method should have a #[document_examples] attribute
1021///         pub fn process(&self, x: i32) -> i32 { x }
1022///     }
1023/// }
1024/// ```
1025///
1026/// ```ignore
1027/// // Properly documented (no warnings):
1028/// #[fp_macros::document_module]
1029/// mod inner {
1030///     pub struct MyType;
1031///
1032///     #[document_parameters("The MyType instance")]
1033///     impl MyType {
1034///         #[document_signature]
1035///         #[document_parameters("The input value")]
1036///         #[document_returns("The input value unchanged.")]
1037///         #[document_examples]
1038///         ///
1039///         /// ```
1040///         /// # use my_crate::MyType;
1041///         /// let t = MyType;
1042///         /// assert_eq!(t.process(42), 42);
1043///         /// ```
1044///         pub fn process(&self, x: i32) -> i32 { x }
1045///     }
1046/// }
1047/// ```
1048///
1049/// ```ignore
1050/// // Disable validation to suppress warnings:
1051/// #[fp_macros::document_module(no_validation)]
1052/// mod inner {
1053///     // ... undocumented code won't produce warnings ...
1054/// }
1055/// ```
1056///
1057/// ### Hierarchical Configuration
1058///
1059/// When resolving the concrete type of `Self`, the macro follows this precedence:
1060///
1061/// 1. **Method Override**: `#[document_use = "AssocName"]` on the method.
1062/// 2. **Impl Block Override**: `#[document_use = "AssocName"]` on the `impl` block.
1063/// 3. **(Type, Trait)-Scoped Default**: `#[document_default]` on the associated type definition
1064///    in a trait `impl` block.
1065/// 4. **Module Default**: `#[document_default]` on the associated type definition in `impl_kind!`.
1066///
1067/// ### Examples
1068///
1069/// ```ignore
1070/// // Invocation
1071/// #[fp_macros::document_module]
1072/// mod inner {
1073///     use super::*;
1074///
1075///     impl_kind! {
1076///         for MyBrand {
1077///             #[document_default]
1078///             type Of<'a, T: 'a>: 'a = MyType<T>;
1079///         }
1080///     }
1081///
1082///     impl Functor for MyBrand {
1083///         #[document_signature]
1084///         fn map<'a, A: 'a, B: 'a, Func>(
1085///             f: Func,
1086///             fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
1087///         ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
1088///         where
1089///             Func: Fn(A) -> B + 'a
1090///         {
1091///             todo!()
1092///         }
1093///     }
1094/// }
1095/// pub use inner::*;
1096///
1097/// // Expanded code
1098/// mod inner {
1099///     use super::*;
1100///
1101///     // ... generated Kind implementations ...
1102///
1103///     impl Functor for MyBrand {
1104///         /// ### Type Signature
1105///         /// `forall a b. (a -> b, MyType a) -> MyType b`
1106///         fn map<'a, A: 'a, B: 'a, Func>(
1107///             f: Func,
1108///             fa: Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, A>),
1109///         ) -> Apply!(<Self as Kind!(type Of<'a, T: 'a>: 'a;)>::Of<'a, B>)
1110///         where
1111///             Func: Fn(A) -> B + 'a
1112///         {
1113///             todo!()
1114///         }
1115///     }
1116/// }
1117/// pub use inner::*;
1118/// ```
1119#[proc_macro_attribute]
1120pub fn document_module(
1121	attr: TokenStream,
1122	item: TokenStream,
1123) -> TokenStream {
1124	match document_module_worker(attr.into(), item.into()) {
1125		Ok(tokens) => tokens.into(),
1126		Err(e) => e.to_compile_error().into(),
1127	}
1128}