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

#85 in Procedural macros

Download history 57/week @ 2024-06-30 112/week @ 2024-07-07 150/week @ 2024-07-14 101/week @ 2024-07-21 130/week @ 2024-07-28 196/week @ 2024-08-04 220/week @ 2024-08-11 109/week @ 2024-08-18 153/week @ 2024-08-25 268/week @ 2024-09-01 85/week @ 2024-09-08 83/week @ 2024-09-15 113/week @ 2024-09-22 136/week @ 2024-09-29 61/week @ 2024-10-06 228/week @ 2024-10-13

555 downloads per month
Used in 22 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

~2MB
~43K SLoC