Support macro type in enum variant

This commit is contained in:
Paul Nguyen 2022-04-06 15:50:07 +02:00
parent aa15be435a
commit fe77b329a0
2 changed files with 39 additions and 13 deletions

View File

@ -60,9 +60,14 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
}
};
if let Type::Path(p) = &ty {
let mut ty = ty;
while let Type::Group(group) = ty {
ty = &*group.elem;
}
if matches!(ty, Type::Path(_) | Type::Macro(_)) {
// This validates that the field type wasn't already used
if !enum_items.insert(p) {
if !enum_items.insert(ty) {
return Err(
Error::new_spanned(&ty, "This type already used in another variant").into(),
);
@ -70,16 +75,16 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
enum_names.push(enum_name);
let mut assert_ty = p.clone();
RemoveLifetime.visit_type_path_mut(&mut assert_ty);
let mut assert_ty = ty.clone();
RemoveLifetime.visit_type_mut(&mut assert_ty);
if !variant.flatten {
type_into_impls.push(quote! {
#crate_name::static_assertions::assert_impl_one!(#assert_ty: #crate_name::ObjectType);
#[allow(clippy::all, clippy::pedantic)]
impl #impl_generics ::std::convert::From<#p> for #ident #ty_generics #where_clause {
fn from(obj: #p) -> Self {
impl #impl_generics ::std::convert::From<#ty> for #ident #ty_generics #where_clause {
fn from(obj: #ty) -> Self {
#ident::#enum_name(obj)
}
}
@ -89,8 +94,8 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
#crate_name::static_assertions::assert_impl_one!(#assert_ty: #crate_name::UnionType);
#[allow(clippy::all, clippy::pedantic)]
impl #impl_generics ::std::convert::From<#p> for #ident #ty_generics #where_clause {
fn from(obj: #p) -> Self {
impl #impl_generics ::std::convert::From<#ty> for #ident #ty_generics #where_clause {
fn from(obj: #ty) -> Self {
#ident::#enum_name(obj)
}
}
@ -99,15 +104,15 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
if !variant.flatten {
registry_types.push(quote! {
<#p as #crate_name::OutputType>::create_type_info(registry);
<#ty as #crate_name::OutputType>::create_type_info(registry);
});
possible_types.push(quote! {
possible_types.insert(<#p as #crate_name::OutputType>::type_name().into_owned());
possible_types.insert(<#ty as #crate_name::OutputType>::type_name().into_owned());
});
} else {
possible_types.push(quote! {
if let #crate_name::registry::MetaType::Union { possible_types: possible_types2, .. } =
registry.create_fake_output_type::<#p>() {
registry.create_fake_output_type::<#ty>() {
possible_types.extend(possible_types2);
}
});
@ -115,11 +120,11 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
if !variant.flatten {
get_introspection_typename.push(quote! {
#ident::#enum_name(obj) => <#p as #crate_name::OutputType>::type_name()
#ident::#enum_name(obj) => <#ty as #crate_name::OutputType>::type_name()
});
} else {
get_introspection_typename.push(quote! {
#ident::#enum_name(obj) => <#p as #crate_name::OutputType>::introspection_type_name(obj)
#ident::#enum_name(obj) => <#ty as #crate_name::OutputType>::introspection_type_name(obj)
});
}

View File

@ -419,3 +419,24 @@ pub async fn test_trait_object_in_union() {
})
);
}
macro_rules! generate_union {
($name:ident, $variant_ty:ty) => {
#[derive(Union)]
pub enum $name {
Val($variant_ty),
}
};
}
#[test]
pub fn test_macro_generated_union() {
#[derive(SimpleObject)]
pub struct IntObj {
pub val: i32,
}
generate_union!(MyEnum, IntObj);
let _ = MyEnum::Val(IntObj { val: 1 });
}