11 releases

0.5.0 Mar 1, 2024
0.4.5 Sep 15, 2023
0.4.4 Apr 20, 2023
0.4.3 Feb 1, 2023
0.1.0 Nov 29, 2021

#62 in Procedural macros

Download history 326/week @ 2023-12-18 274/week @ 2023-12-25 289/week @ 2024-01-01 317/week @ 2024-01-08 237/week @ 2024-01-15 94/week @ 2024-01-22 69/week @ 2024-01-29 81/week @ 2024-02-05 110/week @ 2024-02-12 76/week @ 2024-02-19 296/week @ 2024-02-26 127/week @ 2024-03-04 169/week @ 2024-03-11 123/week @ 2024-03-18 212/week @ 2024-03-25 426/week @ 2024-04-01

954 downloads per month
Used in 20 crates (7 directly)

MIT license

47KB
1K SLoC

Syn-Helpers

crates.io badge docs.rs badge

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 crates.

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 is a work in progress

Dependencies

~345–800KB
~19K SLoC