7 unstable releases (3 breaking)

new 0.4.2 Jan 30, 2023
0.4.1 Jan 27, 2023
0.3.0 Dec 9, 2022
0.2.1 Jan 3, 2022
0.1.0 Nov 29, 2021

#100 in Procedural macros

Download history 12/week @ 2022-10-10 10/week @ 2022-10-17 19/week @ 2022-10-24 23/week @ 2022-10-31 31/week @ 2022-11-07 27/week @ 2022-11-14 17/week @ 2022-11-21 9/week @ 2022-11-28 47/week @ 2022-12-05 26/week @ 2022-12-12 25/week @ 2022-12-19 24/week @ 2022-12-26 8/week @ 2023-01-02 41/week @ 2023-01-09 26/week @ 2023-01-16 124/week @ 2023-01-23

199 downloads per month
Used in 5 crates (3 directly)

MIT license

42KB
1K SLoC

Syn-Helpers

Framework for building derive proc macros over structures (struct and enum).

Handles:

  • Getting expressions referencing fields
  • Building patterns for enums
  • Using the same logic for deriving over a enum or struct
  • Error handling and generating compile_error output
  • Generics on trait and structure (including conflict rectification)

This crate extends (and re-exports) the excellent syn and quote

Example

Evaluate do_thing function on every field (expect those with the #[ignore] attribute)

use syn_helpers::{
    syn::{parse_quote, DeriveInput, GenericParam, Ident, Stmt}, proc_macro2::Span, quote,
    derive_trait, FieldMut, HasAttributes, Trait, TraitItem, TypeOfSelf, Constructable,
};

let my_trait = Trait {
    name: parse_quote!(::my_crate::MyTrait),
    generic_parameters: None,
    items: vec![TraitItem::new_method(
        Ident::new("method_one", Span::call_site()),
        None,
        TypeOfSelf::Reference,
        Vec::default(),
        None,
        |mut item| {
            item.map_constructable(|mut constructable| {
                Ok(constructable
                    .get_fields_mut()
                    .fields_iterator_mut()
                    .flat_map(|mut field| -> Option<Stmt> {
                        if field
                            .get_attributes()
                            .iter()
                            .any(|attr| attr.path.is_ident("ignore"))
                        {
                            None
                        } else {
                            let reference = field.get_reference();
                            Some(parse_quote!(do_thing(#reference);))
                        }
                    })
                    .collect())
            })
        },
    )],
};

let r#struct: DeriveInput = parse_quote! {
    struct X {
        a: String,
        b: i32
    }
};

let stream = derive_trait(r#struct, my_trait);

assert_eq!(
    stream.to_string(),
    quote! {
        #[automatically_derived]
        impl ::my_crate::MyTrait for X {
            fn method_one(&self) {
                let X { a: ref _0, b: ref _1 } = self;
                do_thing(_0);
                do_thing(_1);
            }
        }
    }.to_string()
)

Used in:

Design work in progress

Dependencies

~215–610KB
~15K SLoC