Simplify actions macro.

This commit is contained in:
Nathan Sobo 2023-11-07 21:48:47 -07:00
parent fdc9ea7f9b
commit 2a55b0dbfb
3 changed files with 45 additions and 25 deletions

View file

@ -137,7 +137,8 @@ pub fn all_action_names() -> MappedRwLockReadGuard<'static, [SharedString]> {
})
}
// actions defines structs that can be used as actions.
/// Defines unit structs that can be used as actions.
/// To use more complex data types as actions, annotate your type with the #[action] macro.
#[macro_export]
macro_rules! actions {
() => {};
@ -148,21 +149,10 @@ macro_rules! actions {
pub struct $name;
};
( $name:ident { $($token:tt)* } ) => {
#[gpui::register_action]
#[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug, ::std::cmp::PartialEq, $crate::serde::Deserialize)]
pub struct $name { $($token)* }
};
( $name:ident, $($rest:tt)* ) => {
actions!($name);
actions!($($rest)*);
};
( $name:ident { $($token:tt)* }, $($rest:tt)* ) => {
actions!($name { $($token)* });
actions!($($rest)*);
};
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
@ -408,17 +398,17 @@ mod tests {
#[test]
fn test_actions_definition() {
{
actions!(A, B { field: i32 }, C, D, E, F {}, G);
actions!(A, B, C, D, E, F, G);
}
{
actions!(
A,
B { field: i32 },
B,
C,
D,
E,
F {},
F,
G, // Don't wrap, test the trailing comma
);
}

View file

@ -1,13 +1,17 @@
// Input:
//
// #[action]
// struct Foo {}
// struct Foo {
// bar: String,
// }
// Output:
//
// #[gpui::register_action]
// #[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::default::Default, std::fmt::Debug)]
// struct Foo {}
// struct Foo {
// bar: String,
// }
use proc_macro::TokenStream;
use quote::quote;
@ -16,15 +20,35 @@ use syn::{parse_macro_input, DeriveInput};
pub fn action(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
let name = &input.ident;
let data = &input.data;
let attrs = input
.attrs
.into_iter()
.filter(|attr| !attr.path.is_ident("action"))
.collect::<Vec<_>>();
let data_tokens = quote! { #data }.into();
let expanded = quote! {
let attributes = quote! {
#[gpui::register_action]
#[derive(gpui::serde::Deserialize, std::cmp::PartialEq, std::clone::Clone, std::default::Default, std::fmt::Debug)]
struct #name { #data }
#(#attrs)*
};
TokenStream::from(expanded)
let output = match input.data {
syn::Data::Struct(ref struct_data) => {
let fields = &struct_data.fields;
quote! {
#attributes
struct #name { #fields }
}
}
syn::Data::Enum(ref enum_data) => {
let variants = &enum_data.variants;
quote! {
#attributes
enum #name { #variants }
}
}
_ => panic!("Expected a struct or an enum."),
};
TokenStream::from(output)
}

View file

@ -1,15 +1,21 @@
use proc_macro::TokenStream;
mod action;
mod derive_component;
mod register_action;
mod style_helpers;
mod test;
use proc_macro::TokenStream;
#[proc_macro]
pub fn style_helpers(args: TokenStream) -> TokenStream {
style_helpers::style_helpers(args)
}
#[proc_macro_attribute]
pub fn action(attr: TokenStream, item: TokenStream) -> TokenStream {
action::action(attr, item)
}
#[proc_macro_attribute]
pub fn register_action(attr: TokenStream, item: TokenStream) -> TokenStream {
register_action::register_action(attr, item)