use proc_macro::TokenStream;
use syn::{DeriveInput, parse_macro_input};
mod aggregate;
mod case;
#[cfg(feature = "children")]
mod children;
#[cfg(feature = "config")]
mod config;
mod constraints;
#[cfg(feature = "contracts")]
mod contracts;
mod crate_path;
mod enumeration;
mod event;
mod every;
#[cfg(feature = "factories")]
mod factory;
#[cfg(feature = "fixtures")]
mod fixture;
mod input;
#[cfg(feature = "joins")]
mod joins;
#[cfg(feature = "retention")]
mod pruned;
mod read_model;
#[cfg(feature = "remote-contracts")]
mod remote;
mod sensitive;
mod serialize;
mod shape;
#[cfg(feature = "span")]
mod span;
#[cfg(feature = "tasks")]
mod task;
mod value;
#[proc_macro_derive(
Aggregate,
attributes(
sofie, owner, aggregate, min, max, length, range, required, unique, expose, mirror,
sensitive
)
)]
pub fn derive_aggregate(item: TokenStream) -> TokenStream {
expand(item, aggregate::derive)
}
#[cfg(feature = "children")]
#[proc_macro_derive(Child, attributes(sofie, min, max, length, range, required))]
pub fn derive_child(item: TokenStream) -> TokenStream {
expand(item, children::derive)
}
#[proc_macro_derive(Value, attributes(sofie, sensitive))]
pub fn derive_value(item: TokenStream) -> TokenStream {
expand(item, value::derive)
}
#[cfg(feature = "config")]
#[proc_macro_derive(Config, attributes(sofie))]
pub fn derive_config(item: TokenStream) -> TokenStream {
expand(item, config::derive)
}
#[proc_macro_derive(Enum, attributes(sofie, to, tone))]
pub fn derive_enum(item: TokenStream) -> TokenStream {
expand(item, enumeration::derive)
}
#[proc_macro_derive(ReadModel, attributes(sofie, read, sensitive))]
pub fn derive_read_model(item: TokenStream) -> TokenStream {
expand(item, read_model::derive)
}
#[proc_macro_derive(Event, attributes(sofie))]
pub fn derive_event(item: TokenStream) -> TokenStream {
expand(item, event::derive)
}
#[proc_macro_derive(
Input,
attributes(sofie, input, min, max, length, range, required, unique, unconstrained)
)]
pub fn derive_input(item: TokenStream) -> TokenStream {
expand(item, input::derive)
}
#[proc_macro_attribute]
pub fn on(arguments: TokenStream, item: TokenStream) -> TokenStream {
if arguments.is_empty() {
return item;
}
let error = syn::Error::new_spanned(
proc_macro2::TokenStream::from(arguments),
"write a bare `#[on]`: the listener's first argument's type is the event",
);
[error.into_compile_error().into(), item]
.into_iter()
.collect()
}
#[cfg(feature = "span")]
#[proc_macro_attribute]
pub fn span(arguments: TokenStream, item: TokenStream) -> TokenStream {
span::attribute(&arguments.into(), item.into()).into()
}
#[proc_macro_attribute]
pub fn job(_arguments: TokenStream, item: TokenStream) -> TokenStream {
item
}
#[cfg(feature = "tasks")]
#[proc_macro_attribute]
pub fn task(arguments: TokenStream, item: TokenStream) -> TokenStream {
task::attribute(&arguments.into(), item.into()).into()
}
#[cfg(feature = "contracts")]
#[proc_macro_attribute]
pub fn contract(_arguments: TokenStream, item: TokenStream) -> TokenStream {
contracts::attribute(item.into(), contracts::Boundary::Contract).into()
}
#[cfg(feature = "gateways")]
#[proc_macro_attribute]
pub fn gateway(_arguments: TokenStream, item: TokenStream) -> TokenStream {
contracts::attribute(item.into(), contracts::Boundary::Gateway).into()
}
#[proc_macro_attribute]
pub fn every(arguments: TokenStream, item: TokenStream) -> TokenStream {
every::attribute(arguments.into(), item.into()).into()
}
#[proc_macro_attribute]
pub fn feature(_arguments: TokenStream, item: TokenStream) -> TokenStream {
item
}
#[cfg(feature = "fixtures")]
#[proc_macro_attribute]
pub fn test_app(arguments: TokenStream, item: TokenStream) -> TokenStream {
let function = parse_macro_input!(item as syn::ItemFn);
fixture::test_app(arguments.into(), &function)
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}
fn expand(
item: TokenStream,
derive: fn(&DeriveInput) -> syn::Result<proc_macro2::TokenStream>,
) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
derive(&input)
.and_then(|expanded| crate_path::with_crate_path(&input, expanded))
.unwrap_or_else(syn::Error::into_compile_error)
.into()
}