pub mod declaration;
pub mod expand;
pub mod schedule_spec;
pub mod validate;
pub use declaration::ModuleDeclaration;
use proc_macro2::TokenStream;
use crate::diagnostic::{MacroError, MacroErrorCode, MacroResult};
pub fn module(input: TokenStream) -> MacroResult {
let declaration: ModuleDeclaration =
syn::parse2(input).map_err(|e| MacroError::from_syn(MacroErrorCode::ArcM001, e))?;
validate::validate(&declaration)?;
Ok(expand::expand(&declaration))
}
#[cfg(test)]
mod tests {
use super::*;
use quote::quote;
#[test]
fn expands_a_full_module_declaration() {
let s = module(quote! {
pub Accounts {
imports: [Notifications],
exports: [AuthenticationService],
controllers: [SessionsController],
services: [AuthenticationService],
policies: [UserPolicy],
routes: ACCOUNTS_ROUTES,
listeners: [UserRegistered => send_welcome],
jobs: [send_email v2 => handle_send_email],
commands: ["users:prune" => prune_users],
schedules: [cleanup_sessions every "5m"],
pages: [pages::SignInPage],
}
})
.unwrap()
.to_string();
assert!(s.contains("ACCOUNTS_MODULE"), "got: {s}");
assert!(s.contains("fn accounts_module ()"), "got: {s}");
assert!(s.contains("ACCOUNTS_ROUTES"), "got: {s}");
assert!(s.contains("\"users:prune\""), "got: {s}");
assert!(
s.contains("pages :: SignInPage :: PAGE_CONTRACT_ENTRY"),
"got: {s}"
);
}
#[test]
fn reports_a_page_listed_twice_as_arc_m002() {
let err = module(quote! { A { pages: [P, pages::P] } }).unwrap_err();
assert_eq!(err.code(), MacroErrorCode::ArcM002);
}
#[test]
fn reports_a_syntax_error_as_arc_m001() {
let err = module(quote! { pub Accounts { unknown: [A] } }).unwrap_err();
assert_eq!(err.code(), MacroErrorCode::ArcM001);
}
#[test]
fn reports_a_duplicate_entry_as_arc_m002() {
let err = module(quote! { pub Accounts { imports: [A, A] } }).unwrap_err();
assert_eq!(err.code(), MacroErrorCode::ArcM002);
}
}