nade 0.3.3

Adding named and default arguments to Rust functions
Documentation
# nade

[![Crates.io version](https://img.shields.io/crates/v/nade.svg?style=flat-square)](https://crates.io/crates/nade)
[![docs.rs docs](https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square)](https://docs.rs/nade)

English | [简体中文]./README-zh_cn.md

`nade` is a attribute macro that adds ***na***med and ***de***fault arguments to Rust functions.

## Usage

```rust
// some_crate/src/lib.rs
pub use nade::base::*;
use nade::nade;

pub fn one() -> u32 {
    1
}

#[nade]
pub fn foo(
    /// You can add doc comments to the parameter. It will be shown in the doc of the macro.
    ///
    /// The world is 42.
    #[nade(42)] a: u32,

    /// Call a function
    #[nade(one())] b: u32,

    /// Default value of u32
    #[nade] c: u32,

    d: u32
) -> u32 {
    a + b + c + d
}

assert_eq!(foo!(1, 2, 3, 4), 10);         // foo(1,  2,     3,                  4)
assert_eq!(foo!(d = 2), 45);              // foo(42, one(), Default::default(), 2)
assert_eq!(foo!(1, c = 2, b = 3, 4), 10); // foo(1,  3,     2,                  4)
```

## How it works

If you write a function like this:

```rust
// some_crate/src/lib.rs
pub use nade::base::*;
use nade::nade;

pub fn one() -> u32 {
    1
}

#[nade]
pub fn foo(
    #[nade(42)]
    a: u32,

    #[nade(one())]
    b: u32,

    #[nade]
    c: u32,

    d: u32
) -> u32 {
    a + b + c + d
}
```

it will be expanded to:

```rust
// some_crate/src/lib.rs
// ⓵
pub use nade::base::*;
use nade::nade;

pub fn one() -> u32 {
    1
}

pub fn foo(a: u32, b: u32, c: u32, d: u32) -> u32 {
    a + b + c + d
}

// ⓶
#[::nade::__internal::macro_v(pub)]
macro_rules! foo {
    ($($arguments:tt)*) => {
        // ⓷
        $crate::nade_helper!(
            ($($arguments)*)
            (a: u32 = 42, b: u32 = one(), c: u32 = Default::default(), d: u32)
            (foo)
        )
    };
}
```

Then, when you call the macro `foo` like this:

```rust
use some_crate::{foo, one};

foo!(32, d = 1, c = 2);
```

it will be expanded to:

```rust
use some_crate::{foo, one};

foo(32, one(), 2, 1);
```

### Note

As you can see in [How it works](#how-it-works), there are 3 things to be aware of in the code generated by `#[nade]`.

- ⓵, ⓷

    `nade_helper` is a declarative macro used to generate function call expressions based on arguments, parameters, and function path.

    Its path defaults is `$crate::nade_helper`, so you need to import the macro in the root of crate using `pub use nade::base::*;` or `pub use nade::base::nade_helper;`.

    Also you can customize the path of `nade_helper`.

    ```rust
    use nade::nade;

    mod custom_nade_helper {
        pub use nade::base::nade_helper;
    }

    #[nade]
    #[nade_path(nade_helper = custom_nade_helper)]
    fn custom_nade_helper_path(a: usize) -> usize {
        a
    }
    ```

- 
    `macro_v` is an attribute macro that makes the visibility of the declarative macro the same as the function. see [macro-v]https://github.com/ZihanType/macro-v for details.

    Its path defaults is `::nade::__internal::macro_v`.

    Also you can customize the path of `macro_v`.

    ```rust
    use nade::nade;

    mod custom_macro_v {
        pub use nade::__internal::macro_v;
    }

    #[nade]
    #[nade_path(macro_v = custom_macro_v)]
    fn custom_macro_v_path(a: usize) -> usize {
        a
    }
    ```

## Limitations

1. When you call the macro `foo`, you must use the `use` statement to bring the macro into scope.

    ```rust
    // Good
    use some_crate::{foo, one};
    foo!(32, d = 1, c = 2);

    // Bad
    use some_crate::one;
    some_crate::foo!(32, d = 1, c = 2);
    ```

    Because the attribute macro `#[nade]` will generate a macro with the same name as the function, and the macro use the function in an unhygienic way, so you must use the `use` statement to bring the macro **and** the function into scope.

2. The default argument expression must be imported into the scope of the macro call.

    ```rust
    // Good
    use some_crate::{foo, one};
    foo!(32, d = 1, c = 2);

    // Bad
    use some_crate::foo;
    foo!(32, d = 1, c = 2);
    ```

    Because the default argument expression is evaluated after the `foo` macro is expanded, so it must be imported into the scope of the macro call.

## How to bypass the limitations

1. You can pass a module path starting with `$crate` for the `#[nade]` attribute macro on the function.

    ```rust
    #[nade(module_path = $crate::module)] // <--- here
    pub fn foo(
        #[nade(42)]
        a: u32,

        #[nade(one())]
        b: u32,

        #[nade]
        c: u32,

        d: u32
    ) -> u32 {
        a + b + c + d
    }
    ```

    it will be expanded to:

    ```rust
    pub fn foo(a: u32, b: u32, c: u32, d: u32) -> u32 {
        a + b + c + d
    }

    #[::nade::__internal::macro_v(pub)]
    macro_rules! foo {
        ($($arguments:tt)*) => {
            $crate::nade_helper!(
                ($($arguments)*)
                (a: u32 = 42, b: u32 = one(), c: u32 = Default::default(), d: u32)
                ($crate::module::foo) // <--- here
            )
        };
    }
    ```

    Then, you can not use the `use` statement to bring the macro and the function into scope, like this:

    ```rust
    use some_crate::one;
    some_crate::foo!(32, d = 1, c = 2);
    ```

2. In the `#[nade]` attribute macro on the parameter, you can specify the default argument expression using the full path, either `$crate::a::expr`, or `::a::b::expr`. In fact, when you use `#[nade]` on an parameter, you are using `#[nade(::core::default::Default::default())]`.

    ```rust
    pub fn one() -> u32 {
        1
    }

    pub static PATH: &str = "a";

    #[nade]
    pub fn foo<T1, T2, T3, T4>(
        #[nade($crate::module::one())]
        a: T1,

        #[nade(::std::path::Path::new("a"))]
        b: T2,

        #[nade($crate::module::PATH)]
        c: T3,

        #[nade("Hello")]
        d: T4
    ) {
        let _ = (a, b, c, d);
    }
    ```

    it will be expanded to:

    ```rust
    pub fn foo<T1, T2, T3, T4>(a: T1, b: T2, c: T3, d: T4) {
        let _ = (a, b, c, d);
    }

    #[::nade::__internal::macro_v(pub)]
    macro_rules! foo {
        ($($arguments:tt)*) => {
            $crate::nade_helper!(
                ($($arguments)*)
                (
                    a: T1 = $crate::module::one(),
                    b: T2 = ::std::path::Path::new("a"),
                    c: T3 = $crate::module::PATH,
                    d: T4 = "Hello",
                )
                (foo)
            )
        };
    }
    ```

    Then, you can not use the `use` statement to bring default argument expressions into scope, like this:

    ```rust
    use some_crate::foo;
    foo!();
    ```

## Credits

This crate is inspired by these crates:

- [default-args]https://github.com/buttercrab/default-args.rs
- [duang]https://github.com/xiaoniu-578fa6bff964d005/duang
- [leptos]https://github.com/leptos-rs/leptos
- [typed-builder]https://github.com/idanarye/rust-typed-builder