
# Objective - Currently, the error span for `get_struct_field` when encountering an enum or union points to the macro invocation, rather than the `enum` or `union` token. It also doesn't mention which macro reported the error. ## Solution - Report the correct error span - Add parameter for passing in the name of the macro invocation ## Testing Bevy compiles fine with this change ## Migration Guide ```rs // before let fields = get_struct_fields(&ast.data); // after let fields = get_struct_fields(&ast.data, "derive(Bundle)"); ``` --------- Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
30 lines
1.1 KiB
Rust
30 lines
1.1 KiB
Rust
use syn::{
|
|
punctuated::Punctuated, spanned::Spanned, token::Comma, Data, DataEnum, DataUnion, Error,
|
|
Field, Fields,
|
|
};
|
|
|
|
/// Get the fields of a data structure if that structure is a struct with named fields;
|
|
/// otherwise, return a compile error that points to the site of the macro invocation.
|
|
///
|
|
/// `meta` should be the name of the macro calling this function.
|
|
pub fn get_struct_fields<'a>(
|
|
data: &'a Data,
|
|
meta: &str,
|
|
) -> syn::Result<&'a Punctuated<Field, Comma>> {
|
|
match data {
|
|
Data::Struct(data_struct) => match &data_struct.fields {
|
|
Fields::Named(fields_named) => Ok(&fields_named.named),
|
|
Fields::Unnamed(fields_unnamed) => Ok(&fields_unnamed.unnamed),
|
|
Fields::Unit => Ok(const { &Punctuated::new() }),
|
|
},
|
|
Data::Enum(DataEnum { enum_token, .. }) => Err(Error::new(
|
|
enum_token.span(),
|
|
format!("#[{meta}] only supports structs, not enums"),
|
|
)),
|
|
Data::Union(DataUnion { union_token, .. }) => Err(Error::new(
|
|
union_token.span(),
|
|
format!("#[{meta}] only supports structs, not unions"),
|
|
)),
|
|
}
|
|
}
|