Add remote
attribute for Enum macro. #276
This commit is contained in:
parent
0d6771a199
commit
a725594cd1
|
@ -326,6 +326,7 @@ pub struct Enum {
|
|||
pub internal: bool,
|
||||
pub name: Option<String>,
|
||||
pub desc: Option<String>,
|
||||
pub remote: Option<String>,
|
||||
}
|
||||
|
||||
impl Enum {
|
||||
|
@ -333,6 +334,7 @@ impl Enum {
|
|||
let mut internal = false;
|
||||
let mut name = None;
|
||||
let mut desc = None;
|
||||
let mut remote = None;
|
||||
|
||||
for arg in args {
|
||||
match arg {
|
||||
|
@ -358,6 +360,15 @@ impl Enum {
|
|||
"Attribute 'desc' should be a string.",
|
||||
));
|
||||
}
|
||||
} else if nv.path.is_ident("remote") {
|
||||
if let syn::Lit::Str(lit) = nv.lit {
|
||||
remote = Some(lit.value());
|
||||
} else {
|
||||
return Err(Error::new_spanned(
|
||||
&nv.lit,
|
||||
"Attribute 'remote' should be a string.",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -368,6 +379,7 @@ impl Enum {
|
|||
internal,
|
||||
name,
|
||||
desc,
|
||||
remote,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::args;
|
||||
use crate::utils::{get_crate_name, get_rustdoc};
|
||||
use crate::utils::{get_cfg_attrs, get_crate_name, get_rustdoc};
|
||||
use inflector::Inflector;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
|
@ -39,11 +39,6 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
|||
}
|
||||
|
||||
let item_ident = &variant.ident;
|
||||
let item_attrs = variant
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|attr| !attr.path.is_ident("item"))
|
||||
.collect::<Vec<_>>();
|
||||
let mut item_args = args::EnumItem::parse(&variant.attrs)?;
|
||||
let gql_item_name = item_args
|
||||
.name
|
||||
|
@ -59,7 +54,7 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
|||
.as_ref()
|
||||
.map(|s| quote! { Some(#s) })
|
||||
.unwrap_or_else(|| quote! {None});
|
||||
enum_items.push(quote! { #(#item_attrs)* #item_ident});
|
||||
enum_items.push((get_cfg_attrs(&variant.attrs), item_ident));
|
||||
items.push(quote! {
|
||||
#crate_name::resolver_utils::EnumItem {
|
||||
name: #gql_item_name,
|
||||
|
@ -75,6 +70,49 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
|||
});
|
||||
}
|
||||
|
||||
let remote_conversion = if let Some(remote) = &enum_args.remote {
|
||||
let remote_ty = if let Ok(ty) = syn::parse_str::<syn::Type>(remote) {
|
||||
ty
|
||||
} else {
|
||||
return Err(Error::new_spanned(
|
||||
remote,
|
||||
format!("Invalid remote type: '{}'", remote),
|
||||
));
|
||||
};
|
||||
|
||||
let local_to_remote_items = enum_items.iter().map(|(cfg_attrs, item)| {
|
||||
quote! {
|
||||
#(#cfg_attrs)*
|
||||
#ident::#item => #remote_ty::#item,
|
||||
}
|
||||
});
|
||||
let remote_to_local_items = enum_items.iter().map(|(cfg_attrs, item)| {
|
||||
quote! {
|
||||
#(#cfg_attrs)*
|
||||
#remote_ty::#item => #ident::#item,
|
||||
}
|
||||
});
|
||||
Some(quote! {
|
||||
impl ::std::convert::From<#ident> for #remote_ty {
|
||||
fn from(value: #ident) -> Self {
|
||||
match value {
|
||||
#(#local_to_remote_items)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::convert::From<#remote_ty> for #ident {
|
||||
fn from(value: #remote_ty) -> Self {
|
||||
match value {
|
||||
#(#remote_to_local_items)*
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::resolver_utils::EnumType for #ident {
|
||||
|
@ -122,6 +160,8 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
|||
}
|
||||
}
|
||||
|
||||
#remote_conversion
|
||||
|
||||
impl #crate_name::type_mark::TypeMarkEnum for #ident {}
|
||||
};
|
||||
Ok(expanded.into())
|
||||
|
|
|
@ -70,3 +70,25 @@ pub async fn test_enum_derive_and_item_attributes() {
|
|||
TestStruct { value: Test::Real }
|
||||
);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
pub async fn test_remote_enum() {
|
||||
#[derive(Enum, Copy, Clone, Eq, PartialEq)]
|
||||
#[graphql(remote = "remote::RemoteEnum")]
|
||||
enum LocalEnum {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
|
||||
mod remote {
|
||||
pub enum RemoteEnum {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
||||
}
|
||||
|
||||
let _: remote::RemoteEnum = LocalEnum::A.into();
|
||||
let _: LocalEnum = remote::RemoteEnum::A.into();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user