mod extension_method;

/// Creates an "extension" method for a type by implementing a custom trait with a single method.
/// This is a workaround to enable chaining utility functions without modifying the original type.
/// The first parameter of the annotated function will be used as `self` in the trait method.
///
/// If it is a generic type parameter (e.g., `T`, `*const T`, `&mut T`, etc.),
/// the same type parameter and its lifetime (if any) will be used as the trait generics.
///
/// If the first parameter type is `impl Trait`, it will be converted to a generic type parameter with a trait bound.
/// - To specify a custom name for the generated trait, use `trait_name = "MyTraitName"`
/// - To specify a custom name for the generic type parameter for `impl Trait`, use `impl_type_param = "MyT"`
/// - The original function will be preserved by default, use `remove_fn = true` to remove it
///
/// Note: The annotated function cannot be `extern`, and must have at least one input parameter. The input parameter cannot be of type `Self`.
/// Example:
/// ```rust no_run
/// use core::ops::Add;
///
/// #[extension_method(trait_name = "Double", remove_fn = true)]
/// pub fn double<T>(val: T) -> T where T: Add<Output = T> + Copy {
///     val + val
/// }
///
/// let a = 2;
/// assert_eq!(a.double(), 4);
#[proc_macro_attribute]
pub fn extension_method(
    attr: proc_macro::TokenStream,
    item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    extension_method::main(attr, item)
}
