46 lines
1.7 KiB
Rust
46 lines
1.7 KiB
Rust
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::{parse_macro_input, DeriveInput, Error, Expr, LitStr, Result};
|
|
#[proc_macro_derive(Command, attributes(command))]
|
|
pub fn derive_command(input: TokenStream) -> TokenStream {
|
|
let input = parse_macro_input!(input as DeriveInput);
|
|
expand(&input)
|
|
.unwrap_or_else(Error::into_compile_error)
|
|
.into()
|
|
}
|
|
fn expand(input: &DeriveInput) -> Result<proc_macro2::TokenStream> {
|
|
let attr = input
|
|
.attrs
|
|
.iter()
|
|
.find(|attr| attr.path().is_ident("command"))
|
|
.ok_or_else(|| {
|
|
Error::new_spanned(&input.ident, "missing #[command(id = ...)] attribute")
|
|
})?;
|
|
let mut id: Option<proc_macro2::TokenStream> = None;
|
|
let mut name: Option<String> = None;
|
|
attr.parse_nested_meta(|meta| {
|
|
if meta.path.is_ident("id") {
|
|
let value: Expr = meta.value()?.parse()?;
|
|
id = Some(quote!(#value));
|
|
return Ok(());
|
|
}
|
|
if meta.path.is_ident("name") {
|
|
let value: LitStr = meta.value()?.parse()?;
|
|
name = Some(value.value());
|
|
return Ok(());
|
|
}
|
|
Err(meta.error("unsupported #[command(...)] key"))
|
|
})?;
|
|
let id = id.ok_or_else(|| Error::new_spanned(attr, "#[command(...)] requires `id`"))?;
|
|
let ident = &input.ident;
|
|
let name = name.unwrap_or_else(|| ident.to_string());
|
|
Ok(quote! {
|
|
impl ::logic::commands::CommandMeta for #ident {
|
|
const COMMAND_TYPE: i32 = #id;
|
|
const NAME: &'static str = #name;
|
|
}
|
|
::titan::inventory::submit! {
|
|
::logic::commands::CommandRegistryEntry::of::<#ident>()
|
|
}
|
|
})
|
|
}
|