gh_workflow_macros/
lib.rs1use heck::ToSnakeCase;
2use proc_macro::TokenStream;
3use quote::quote;
4use syn::{parse_macro_input, Data, DeriveInput, Fields};
5
6#[proc_macro_derive(Context)]
7pub fn derive_expr(input: TokenStream) -> TokenStream {
8 let input = parse_macro_input!(input as DeriveInput);
9 let struct_name = input.ident;
10 let ctor_name = struct_name.to_string().to_snake_case();
11 let ctor_id = syn::Ident::new(&ctor_name, struct_name.span());
12
13 let fields = if let Data::Struct(data_struct) = input.data {
15 if let Fields::Named(fields) = data_struct.fields {
16 fields
17 } else {
18 panic!("#[derive(Context)] only supports structs with named fields")
19 }
20 } else {
21 panic!("#[derive(Context)] can only be used with structs");
22 };
23
24 let methods = fields.named.iter().map(|field| {
26 let field_name = &field.ident;
27 let field_type = &field.ty;
28 let field_name_str = field_name.as_ref().unwrap().to_string();
29 quote! {
30 pub fn #field_name(&self) -> Context<#field_type> {
31 self.select::<#field_type>(#field_name_str)
32 }
33 }
34 });
35
36 let expanded = quote! {
38 impl Context<#struct_name> {
39 #(#methods)*
40
41 pub fn #ctor_id() -> Self {
42 Context::<Github>::new().select(stringify!(#ctor_name))
43 }
44 }
45 };
46
47 TokenStream::from(expanded)
50}