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 internal: bool,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub desc: Option<String>,
|
pub desc: Option<String>,
|
||||||
|
pub remote: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Enum {
|
impl Enum {
|
||||||
|
@ -333,6 +334,7 @@ impl Enum {
|
||||||
let mut internal = false;
|
let mut internal = false;
|
||||||
let mut name = None;
|
let mut name = None;
|
||||||
let mut desc = None;
|
let mut desc = None;
|
||||||
|
let mut remote = None;
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg {
|
match arg {
|
||||||
|
@ -358,6 +360,15 @@ impl Enum {
|
||||||
"Attribute 'desc' should be a string.",
|
"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,
|
internal,
|
||||||
name,
|
name,
|
||||||
desc,
|
desc,
|
||||||
|
remote,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::args;
|
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 inflector::Inflector;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
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_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 mut item_args = args::EnumItem::parse(&variant.attrs)?;
|
||||||
let gql_item_name = item_args
|
let gql_item_name = item_args
|
||||||
.name
|
.name
|
||||||
|
@ -59,7 +54,7 @@ pub fn generate(enum_args: &args::Enum, input: &DeriveInput) -> Result<TokenStre
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| quote! { Some(#s) })
|
.map(|s| quote! { Some(#s) })
|
||||||
.unwrap_or_else(|| quote! {None});
|
.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! {
|
items.push(quote! {
|
||||||
#crate_name::resolver_utils::EnumItem {
|
#crate_name::resolver_utils::EnumItem {
|
||||||
name: #gql_item_name,
|
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! {
|
let expanded = quote! {
|
||||||
#[allow(clippy::all, clippy::pedantic)]
|
#[allow(clippy::all, clippy::pedantic)]
|
||||||
impl #crate_name::resolver_utils::EnumType for #ident {
|
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 {}
|
impl #crate_name::type_mark::TypeMarkEnum for #ident {}
|
||||||
};
|
};
|
||||||
Ok(expanded.into())
|
Ok(expanded.into())
|
||||||
|
|
|
@ -70,3 +70,25 @@ pub async fn test_enum_derive_and_item_attributes() {
|
||||||
TestStruct { value: Test::Real }
|
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