Browse Source

Macro attribute so we can control impl of `xtra::Message`

Co-authored-by: Mariusz Klochowicz <mariusz@klochowicz.com>
contact-taker-before-changing-cfd-state
Daniel Karzel 3 years ago
committed by Mariusz Klochowicz
parent
commit
cd8d559867
No known key found for this signature in database GPG Key ID: 470C865699C8D4D
  1. 34
      xtra_productivity/src/lib.rs
  2. 20
      xtra_productivity/tests/pass/can_handle_message.rs

34
xtra_productivity/src/lib.rs

@ -1,10 +1,26 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{FnArg, GenericParam, ImplItem, ItemImpl, ReturnType};
use syn::{FnArg, GenericParam, ImplItem, ItemImpl, MetaNameValue, ReturnType};
#[proc_macro_attribute]
pub fn xtra_productivity(_attribute: TokenStream, item: TokenStream) -> TokenStream {
pub fn xtra_productivity(attribute: TokenStream, item: TokenStream) -> TokenStream {
let block = syn::parse::<ItemImpl>(item).unwrap();
let want_message_impl = if attribute.is_empty() {
true
} else {
let attribute = syn::parse::<MetaNameValue>(attribute).unwrap();
if !attribute.path.is_ident("message_impl") {
panic!(
"Unexpected attribute {:?}",
attribute.path.get_ident().unwrap()
)
}
matches!(
attribute.lit,
syn::Lit::Bool(syn::LitBool { value: true, .. })
)
};
let actor = block.self_ty;
@ -60,10 +76,18 @@ pub fn xtra_productivity(_attribute: TokenStream, item: TokenStream) -> TokenStr
ReturnType::Type(_, ref t) => quote! { #t }
};
quote! {
impl xtra::Message for #message_type {
type Result = #result_type;
let message_impl = if want_message_impl {
quote! {
impl xtra::Message for #message_type {
type Result = #result_type;
}
}
} else {
quote! {}
};
quote! {
#message_impl
#[async_trait::async_trait]
impl<#generic_params> xtra::Handler<#message_type> for #actor

20
xtra_productivity/tests/pass/can_handle_message.rs

@ -30,6 +30,21 @@ impl DummyActor {
fn is_i32(_: i32) {}
struct DummyMessageWithoutMessageImpl;
#[xtra_productivity(message_impl = false)]
impl DummyActor {
pub fn handle_dummy_message_without_message_impl(
&mut self,
_message: DummyMessageWithoutMessageImpl,
) {
}
}
impl xtra::Message for DummyMessageWithoutMessageImpl {
type Result = ();
}
#[tokio::main]
async fn main() {
// Create dummy actor
@ -39,4 +54,9 @@ async fn main() {
let i32 = dummy_actor.send(DummyMessage).await.unwrap();
is_i32(i32);
dummy_actor.send(DummyMessageWithContext).await.unwrap();
dummy_actor
.send(DummyMessageWithoutMessageImpl)
.await
.unwrap();
}

Loading…
Cancel
Save