proc_macro_roids 0.2.0

Traits and functions to make writing proc macros more ergonomic.
Documentation
[![Crates.io](https://img.shields.io/crates/v/proc_macro_roids.svg)](https://crates.io/crates/proc_macro_roids)
[![Build Status](https://ci.appveyor.com/api/projects/status/github/azriel91/proc_macro_roids?branch=master&svg=true)](https://ci.appveyor.com/project/azriel91/proc_macro_roids/branch/master)
[![Build Status](https://travis-ci.org/azriel91/proc_macro_roids.svg?branch=master)](https://travis-ci.org/azriel91/proc_macro_roids)
[![Coverage Status](https://codecov.io/gh/azriel91/proc_macro_roids/branch/master/graph/badge.svg)](https://codecov.io/gh/azriel91/proc_macro_roids)

# Proc Macro Roids

Traits and functions to make writing proc macros more ergonomic.

The *roids* name is chosen because, although these functions make it easy to perform certain
operation, they may not necessarily be a good idea =D!

## Examples

1. Append additional `#[derive(..)]`s.

   This works for function-like or attribute proc macros.

    ```rust,ignore
    extern crate proc_macro;

    use proc_macro::TokenStream;
    use proc_macro_roids::DeriveInputDeriveExt;
    use quote::quote;
    use syn::{parse_macro_input, parse_quote, DeriveInput};

    #[proc_macro_attribute]
    pub fn copy(_args: TokenStream, item: TokenStream) -> TokenStream {
        // Example input:
        //
        // #[derive(Debug)]
        // struct Struct;
        let mut ast = parse_macro_input!(item as DeriveInput);

        // Append the derives.
        let derives = parse_quote!(Clone, Copy);
        ast.append_derives(derives);

        // Example output:
        //
        // #[derive(Debug, Clone, Copy)]
        // struct Struct;
        TokenStream::from(quote! { #ast })
    }
    ```

2. Append named fields.

    This works for structs with named fields or unit structs.

    ```rust,ignore
    extern crate proc_macro;

    use proc_macro::TokenStream;
    use proc_macro_roids::FieldsNamedAppend;
    use quote::quote;
    use syn::{parse_macro_input, parse_quote, DeriveInput, FieldsNamed};

    /// Example usage:
    ///
    /// ```rust
    /// use macro_crate::append_cd;
    ///
    /// #[append_cd]
    /// struct StructNamed { a: u32, b: i32 }
    /// ```
    #[proc_macro_attribute]
    pub fn append_cd(_args: TokenStream, item: TokenStream) -> TokenStream {
        // Example input:
        //
        // struct StructNamed { a: u32, b: i32 }
        let mut ast = parse_macro_input!(item as DeriveInput);

        // Append the fields.
        let fields_additional: FieldsNamed = parse_quote!({ c: i64, d: usize });
        ast.append_named(fields_additional);

        // Example output:
        //
        // struct StructNamed { a: u32, b: i32, c: i64, d: usize }
        TokenStream::from(quote! { #ast })
    }
    ```

3. Append unnamed fields (tuples).

    This works for structs with unnamed fields or unit structs.

    ```rust,ignore
    extern crate proc_macro;

    use proc_macro::TokenStream;
    use proc_macro_roids::FieldsUnnamedAppend;
    use quote::quote;
    use syn::{parse_macro_input, parse_quote, DeriveInput, FieldsUnnamed};

    /// Example usage:
    ///
    /// ```rust
    /// use macro_crate::append_i64_usize;
    ///
    /// #[append_i64_usize]
    /// struct StructUnit;
    /// ```
    #[proc_macro_attribute]
    pub fn append_i64_usize(_args: TokenStream, item: TokenStream) -> TokenStream {
        // Example input:
        //
        // struct StructUnit;
        let mut ast = parse_macro_input!(item as DeriveInput);

        // Append the fields.
        let fields_additional: FieldsUnnamed = parse_quote!((i64, usize));
        ast.append_unnamed(fields_additional);

        // Example output:
        //
        // struct StructUnit(i64, usize);
        TokenStream::from(quote! { #ast })
    }
    ```

4. Get newtype inner `Field`.

    This works for structs with unnamed fields or unit structs.

    ```rust,ignore
    extern crate proc_macro;

    use proc_macro::TokenStream;
    use proc_macro_roids::DeriveInputNewtypeExt;
    use quote::quote;
    use syn::{parse_macro_input, parse_quote, DeriveInput, Type};

    #[proc_macro_derive(Deref)]
    pub fn derive_deref(item: TokenStream) -> TokenStream {
        // Example input:
        //
        // #[derive(Deref)]
        // struct Newtype(u32);
        let mut ast = parse_macro_input!(item as DeriveInput);

        // Get the inner field.
        let inner_field = ast.inner_type();

        // Implement `Deref`
        let type_name = &ast.ident;
        let token_stream_2 = quote! {
            #ast

            impl std::ops::Deref for #type_name {
                type Target = #inner_type;
                fn deref(&self) -> &Self::Target {
                    &self.0
                }
            }
        }
        TokenStream::from(token_stream_2)
    }
    ```

## License

Licensed under either of

* Apache License, Version 2.0, ([LICENSE-APACHE]LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT]LICENSE-MIT or https://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally
submitted for inclusion in the work by you, as defined in the Apache-2.0
license, shall be dual licensed as above, without any additional terms or
conditions.