 8e1f660e1d
			
		
	
	
		8e1f660e1d
		
	
	
	
	
		
			
			# Objective Emitting compile errors produces cleaner messages than panicking in a proc-macro. ## Solution - Replace match-with-panic code with call to new `bevy_macro_utils::get_named_struct_fields` function - Replace one use of match-with-panic for enums with inline match _Aside:_ I'm also the maintainer of [`darling`](https://docs.rs/darling), a crate which provides a serde-like API for parsing macro inputs. I avoided using it here because it seemed like overkill, but if there are plans to add lots more attributes/macros then that might be a good way of offloading macro error handling.
		
			
				
	
	
		
			44 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			44 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use bevy_macro_utils::BevyManifest;
 | |
| use proc_macro::{Span, TokenStream};
 | |
| use quote::quote;
 | |
| use syn::{parse_macro_input, Data, DeriveInput};
 | |
| 
 | |
| pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
 | |
|     let ast = parse_macro_input!(input as DeriveInput);
 | |
|     let variants = match &ast.data {
 | |
|         Data::Enum(v) => &v.variants,
 | |
|         _ => {
 | |
|             return syn::Error::new(Span::call_site().into(), "Only enums are supported")
 | |
|                 .into_compile_error()
 | |
|                 .into()
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     let bevy_util_path = BevyManifest::default().get_path(crate::modules::BEVY_UTILS);
 | |
| 
 | |
|     let generics = ast.generics;
 | |
|     let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
 | |
| 
 | |
|     let struct_name = &ast.ident;
 | |
|     let idents = variants.iter().map(|v| &v.ident);
 | |
|     let names = variants.iter().map(|v| v.ident.to_string());
 | |
|     let indices = 0..names.len();
 | |
| 
 | |
|     TokenStream::from(quote! {
 | |
|         impl #impl_generics #bevy_util_path::EnumVariantMeta for #struct_name #ty_generics #where_clause {
 | |
|             fn enum_variant_index(&self) -> usize {
 | |
|                 match self {
 | |
|                     #(#struct_name::#idents {..} => #indices,)*
 | |
|                 }
 | |
|             }
 | |
|             fn enum_variant_name(&self) -> &'static str {
 | |
|                 static variants: &[&str] = &[
 | |
|                     #(#names,)*
 | |
|                 ];
 | |
|                 let index = self.enum_variant_index();
 | |
|                 variants[index]
 | |
|             }
 | |
|         }
 | |
|     })
 | |
| }
 |