@ -63,7 +63,11 @@ fn expand(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
let Data ::Enum ( data ) = & input . data else {
let Data ::Enum ( data ) = & input . data else {
return Err ( syn ::Error ::new (
return Err ( syn ::Error ::new (
input . ident . span ( ) ,
input . ident . span ( ) ,
"`GameAction` can only be derived for enums" ,
format! (
" ` GameAction ` can only be derived for enums , but ` { } ` is not one . \ n \
An action set is a fixed list of variants , e . g . ` enum { } { { #[ action_kind(instant) ] Jump } } ` . " ,
input . ident , input . ident
) ,
) ) ;
) ) ;
} ;
} ;
@ -78,7 +82,11 @@ fn expand(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
if ! matches! ( variant . fields , Fields ::Unit ) {
if ! matches! ( variant . fields , Fields ::Unit ) {
return Err ( syn ::Error ::new (
return Err ( syn ::Error ::new (
variant . fields . span ( ) ,
variant . fields . span ( ) ,
"`GameAction` variants must be fieldless (unit variants)" ,
format! (
" action variant ` { 0 } ` must be a unit variant ( no fields ) . \ n \
Actions are plain identifiers used as map keys — write ` { 0 } ` , not ` { 0 } ( .. ) ` or ` { 0 } { { .. } } ` . " ,
variant . ident
) ,
) ) ;
) ) ;
}
}
let variant_ident = & variant . ident ;
let variant_ident = & variant . ident ;
@ -166,13 +174,20 @@ fn parse_kind(variant: &syn::Variant) -> syn::Result<Kind> {
if kind . is_some ( ) {
if kind . is_some ( ) {
return Err ( syn ::Error ::new (
return Err ( syn ::Error ::new (
attr . span ( ) ,
attr . span ( ) ,
"duplicate `#[action_kind(...)]` attribute" ,
format! (
"action variant `{}` has more than one `#[action_kind(..)]`; each variant declares exactly one kind" ,
variant . ident
) ,
) ) ;
) ) ;
}
}
let name : Ident = attr . parse_args ( ) . map_err ( | _ | {
let name : Ident = attr . parse_args ( ) . map_err ( | _ | {
syn ::Error ::new (
syn ::Error ::new (
attr . span ( ) ,
attr . span ( ) ,
"expected `#[action_kind(instant|toggle|axis|scalar)]`" ,
format! (
" malformed ` #[ action_kind(..) ] ` on ` { } ` : expected a single kind — one of \
` instant ` , ` toggle ` , ` axis ` , or ` scalar ` , e . g . ` #[ action_kind(instant) ] ` " ,
variant . ident
) ,
)
)
} ) ? ;
} ) ? ;
kind = Some ( match name . to_string ( ) . as_str ( ) {
kind = Some ( match name . to_string ( ) . as_str ( ) {
@ -184,7 +199,8 @@ fn parse_kind(variant: &syn::Variant) -> syn::Result<Kind> {
return Err ( syn ::Error ::new (
return Err ( syn ::Error ::new (
name . span ( ) ,
name . span ( ) ,
format! (
format! (
"unknown action kind `{other}`, expected `instant`, `toggle`, `axis`, or `scalar`"
"unknown action kind `{other}` on `{}`; expected `instant`, `toggle`, `axis`, or `scalar`" ,
variant . ident
) ,
) ,
) )
) )
}
}
@ -195,7 +211,8 @@ fn parse_kind(variant: &syn::Variant) -> syn::Result<Kind> {
syn ::Error ::new (
syn ::Error ::new (
variant . ident . span ( ) ,
variant . ident . span ( ) ,
format! (
format! (
"variant `{}` needs `#[action_kind(instant|toggle|axis|scalar)]`" ,
" action variant ` { 0 } ` is missing its kind ; add one of \
` #[ action_kind(instant|toggle|axis|scalar) ] ` , e . g . ` #[ action_kind(instant) ] { 0 } ` " ,
variant . ident
variant . ident
) ,
) ,
)
)
@ -212,7 +229,11 @@ fn parse_handlers(variant: &syn::Variant) -> syn::Result<Vec<Path>> {
let path : Path = attr . parse_args ( ) . map_err ( | _ | {
let path : Path = attr . parse_args ( ) . map_err ( | _ | {
syn ::Error ::new (
syn ::Error ::new (
attr . span ( ) ,
attr . span ( ) ,
"expected `#[action_handler(path::to::system)]`" ,
format! (
" malformed ` #[ action_handler(..) ] ` on ` { } ` : expected a path to a system \
function , e . g . ` #[ action_handler(jump) ] ` or ` #[ action_handler(sim::step) ] ` " ,
variant . ident
) ,
)
)
} ) ? ;
} ) ? ;
handlers . push ( path ) ;
handlers . push ( path ) ;