# 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.
49 lines
1.6 KiB
Rust
49 lines
1.6 KiB
Rust
use bevy_macro_utils::get_named_struct_fields;
|
|
use proc_macro2::{Literal, TokenStream};
|
|
use quote::quote;
|
|
use syn::{parse_quote, DeriveInput, Path};
|
|
|
|
pub fn emit(input: DeriveInput) -> TokenStream {
|
|
let bevy_crevice_path = crate::bevy_crevice_path();
|
|
|
|
let fields = match get_named_struct_fields(&input.data) {
|
|
Ok(fields) => fields,
|
|
Err(e) => return e.into_compile_error(),
|
|
};
|
|
|
|
let base_trait_path: Path = parse_quote!(#bevy_crevice_path::glsl::Glsl);
|
|
let struct_trait_path: Path = parse_quote!(#bevy_crevice_path::glsl::GlslStruct);
|
|
|
|
let name = input.ident;
|
|
let name_str = Literal::string(&name.to_string());
|
|
|
|
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
|
|
|
|
let glsl_fields = fields.named.iter().map(|field| {
|
|
let field_ty = &field.ty;
|
|
let field_name_str = Literal::string(&field.ident.as_ref().unwrap().to_string());
|
|
let field_as = quote! {<#field_ty as #bevy_crevice_path::glsl::GlslArray>};
|
|
|
|
quote! {
|
|
s.push_str("\t");
|
|
s.push_str(#field_as::NAME);
|
|
s.push_str(" ");
|
|
s.push_str(#field_name_str);
|
|
<#field_as::ArraySize as #bevy_crevice_path::glsl::DimensionList>::push_to_string(s);
|
|
s.push_str(";\n");
|
|
}
|
|
});
|
|
|
|
quote! {
|
|
unsafe impl #impl_generics #base_trait_path for #name #ty_generics #where_clause {
|
|
const NAME: &'static str = #name_str;
|
|
}
|
|
|
|
unsafe impl #impl_generics #struct_trait_path for #name #ty_generics #where_clause {
|
|
fn enumerate_fields(s: &mut String) {
|
|
#( #glsl_fields )*
|
|
}
|
|
}
|
|
}
|
|
}
|