Simplify actions macro.

Nathan Sobo created

Change summary

crates/gpui2/src/action.rs              | 20 +++----------
crates/gpui2_macros/src/action.rs       | 40 +++++++++++++++++++++-----
crates/gpui2_macros/src/gpui2_macros.rs | 10 +++++-
3 files changed, 45 insertions(+), 25 deletions(-)

Detailed changes

crates/gpui2/src/action.rs 🔗

@@ -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
             );
         }

crates/gpui2_macros/src/action.rs 🔗

@@ -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)*
+    };
+
+    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(expanded)
+    TokenStream::from(output)
 }

crates/gpui2_macros/src/gpui2_macros.rs 🔗

@@ -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)