Skip to content

Commit

Permalink
feat(macros): improve macros and add tests (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
fu050409 authored Sep 24, 2024
1 parent 17f7257 commit 974dd5f
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions crates/aionbot-core/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ impl Router for String {
}
}

#[derive(Default)]
pub struct AnyRouter;

impl Router for AnyRouter {
fn matches(&self, _event: &Event) -> bool {
true
}
}

pub struct ExactMatchRouter {
pattern: String,
ignore_spaces: bool,
Expand Down
3 changes: 3 additions & 0 deletions crates/aionbot-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ proc-macro2 = "1.0.86"
quote = "1.0.37"
syn = { version = "2.0.77", features = ["full"] }

[dev-dependencies]
aionbot-core = { path = "../aionbot-core" }

[lib]
proc-macro = true
37 changes: 26 additions & 11 deletions crates/aionbot-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,27 @@ impl HandlerArgs {
}
}

fn get_router(handler_args: &HandlerArgs) -> syn::Expr {
if let Some(router) = &handler_args.router {
router.clone()
} else {
syn::parse(quote! { "AnyRouter::default()" }.into()).unwrap()
}
}

fn get_hash_id(ident: &syn::Ident) -> String {
let mut hasher = DefaultHasher::new();
ident.hash(&mut hasher);
hasher.finish().to_string()
}

fn extract_fn_name_ident(item: &syn::Ident, hash_id: &str) -> syn::Ident {
let mut fn_name = String::from("__");
fn_name.push_str(&item.to_string());
fn_name.extend("_".chars().chain(hash_id.chars()));
syn::Ident::new(&fn_name, item.span())
}

#[proc_macro_attribute]
pub fn register(attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as syn::ItemFn);
Expand All @@ -61,20 +82,14 @@ pub fn register(attr: TokenStream, item: TokenStream) -> TokenStream {
}

let origin_ident = &input.sig.ident;
let mut fn_name = input.sig.ident.to_string();
let mut hasher = DefaultHasher::new();
fn_name.hash(&mut hasher);
let hash_id = hasher.finish().to_string();
fn_name.extend("_".chars().chain(hash_id.chars()));

let fn_name_ident = syn::Ident::new(&fn_name, input.sig.ident.span());
let hash_id = get_hash_id(origin_ident);
let fn_name_ident = extract_fn_name_ident(origin_ident, &hash_id);

let fn_args = &input.sig.inputs;
let fn_body = &input.block;

let default_router = quote! { "default" }.into();
let default_router = parse_macro_input!(default_router as syn::Expr);
let router = attrs.router.as_ref().unwrap_or(&default_router);
let router = get_router(&attrs);
let priority = &attrs.priority;

if attrs.is_empty() {
return TokenStream::from(
Expand All @@ -94,7 +109,7 @@ pub fn register(attr: TokenStream, item: TokenStream) -> TokenStream {
pub fn #origin_ident() -> Entry {
Entry {
id: #hash_id,
priority: 0,
priority: #priority,
router: Arc::new(Box::new(#router)),
callback: Arc::new(#fn_name_ident),
}
Expand Down
54 changes: 54 additions & 0 deletions crates/aionbot-macros/tests/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use aionbot_core::event::{Message, MessageSegment};
use aionbot_macros::register;

#[register(router = "test_router")]
pub fn test_register_fn(_event: Arc<Event>) -> Result<()> {
Ok(())
}

#[register(router = "test_router", priority = 1)]
pub fn test_register_fn_priority(_event: Arc<Event>) -> Result<()> {
Ok(())
}

#[test]
fn test_register_router() {
let event = Event {
plain_data: Message {
entity: Some("test".to_string()),
segments: vec![MessageSegment {
text: "test_router".to_string(),
type_: "text".to_string(),
}],
},
user_id: "test".to_string(),
channel_id: "test".to_string(),
timestamp: "test".to_string(),
event_type: "text".to_string(),
variables: Default::default(),
};
let entry = test_register_fn();
assert!(entry.priority == 0);
assert!(entry.router.matches(&event));
}

#[test]
fn test_register_router_priority() {
let event = Event {
plain_data: Message {
entity: Some("test".to_string()),
segments: vec![MessageSegment {
text: "test_router".to_string(),
type_: "text".to_string(),
}],
},
user_id: "test".to_string(),
channel_id: "test".to_string(),
timestamp: "test".to_string(),
event_type: "text".to_string(),
variables: Default::default(),
};
let entry = test_register_fn_priority();
assert!(entry.priority == 1);
assert!(entry.router.matches(&event));
}

0 comments on commit 974dd5f

Please sign in to comment.