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