action.rs

 1// Input:
 2//
 3// #[action]
 4// struct Foo {
 5//   bar: String,
 6// }
 7
 8// Output:
 9//
10// #[gpui::register_action]
11// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::default::Default, std::fmt::Debug)]
12// struct Foo {
13//   bar: String,
14// }
15
16use proc_macro::TokenStream;
17use quote::quote;
18use syn::{parse_macro_input, DeriveInput};
19
20pub fn action(_attr: TokenStream, item: TokenStream) -> TokenStream {
21    let input = parse_macro_input!(item as DeriveInput);
22    let name = &input.ident;
23    let attrs = input
24        .attrs
25        .into_iter()
26        .filter(|attr| !attr.path.is_ident("action"))
27        .collect::<Vec<_>>();
28
29    let attributes = quote! {
30        #[gpui::register_action]
31        #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::default::Default, std::fmt::Debug)]
32        #(#attrs)*
33    };
34    let visibility = input.vis;
35
36    let output = match input.data {
37        syn::Data::Struct(ref struct_data) => match &struct_data.fields {
38            syn::Fields::Named(_) | syn::Fields::Unnamed(_) => {
39                let fields = &struct_data.fields;
40                quote! {
41                    #attributes
42                    #visibility struct #name #fields
43                }
44            }
45            syn::Fields::Unit => {
46                quote! {
47                    #attributes
48                    #visibility struct #name;
49                }
50            }
51        },
52        syn::Data::Enum(ref enum_data) => {
53            let variants = &enum_data.variants;
54            quote! {
55                #attributes
56                #visibility enum #name { #variants }
57            }
58        }
59        _ => panic!("Expected a struct or an enum."),
60    };
61
62    TokenStream::from(output)
63}