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}