Add support for extending an entity with computed fields (advanced) #180

This commit is contained in:
Sunli 2020-06-19 12:37:52 +08:00
parent 96ca4ade82
commit 362ba90e7d
3 changed files with 46 additions and 16 deletions

View File

@ -130,6 +130,7 @@ pub struct Argument {
pub desc: Option<String>, pub desc: Option<String>,
pub default: Option<TokenStream>, pub default: Option<TokenStream>,
pub validator: TokenStream, pub validator: TokenStream,
pub key: bool, // for entity
} }
impl Argument { impl Argument {
@ -138,6 +139,7 @@ impl Argument {
let mut desc = None; let mut desc = None;
let mut default = None; let mut default = None;
let mut validator = quote! { None }; let mut validator = quote! { None };
let mut key = false;
for attr in attrs { for attr in attrs {
match attr.parse_meta()? { match attr.parse_meta()? {
@ -146,6 +148,8 @@ impl Argument {
if let NestedMeta::Meta(Meta::Path(p)) = meta { if let NestedMeta::Meta(Meta::Path(p)) = meta {
if p.is_ident("default") { if p.is_ident("default") {
default = Some(quote! { Default::default() }); default = Some(quote! { Default::default() });
} else if p.is_ident("key") {
key = true;
} }
} else if let NestedMeta::Meta(Meta::NameValue(nv)) = meta { } else if let NestedMeta::Meta(Meta::NameValue(nv)) = meta {
if nv.path.is_ident("name") { if nv.path.is_ident("name") {
@ -185,6 +189,7 @@ impl Argument {
desc, desc,
default, default,
validator, validator,
key,
}) })
} }
} }

View File

@ -113,29 +113,51 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
let mut use_keys = Vec::new(); let mut use_keys = Vec::new();
let mut keys = Vec::new(); let mut keys = Vec::new();
let mut keys_str = String::new(); let mut keys_str = String::new();
let mut requires_getter = Vec::new();
let mut one_key = false;
for (ident, ty, args::Argument { name, .. }) in &args { if args.is_empty() {
return Err(Error::new_spanned(
method,
"Entity need to have at least one key.",
));
} else if args.len() == 1 {
one_key = true;
}
for (ident, ty, args::Argument { name, key, .. }) in &args {
let is_key = one_key || *key;
let name = name let name = name
.clone() .clone()
.unwrap_or_else(|| ident.ident.to_string().to_camel_case()); .unwrap_or_else(|| ident.ident.to_string().to_camel_case());
if !keys_str.is_empty() { if is_key {
keys_str.push(' '); if !keys_str.is_empty() {
} keys_str.push(' ');
keys_str.push_str(&name); }
keys_str.push_str(&name);
key_pat.push(quote! { key_pat.push(quote! {
Some(#ident) Some(#ident)
}); });
key_getter.push(quote! { key_getter.push(quote! {
params.get(#name).and_then(|value| { params.get(#name).and_then(|value| {
let value: Option<#ty> = #crate_name::InputValueType::parse(Some(value.clone())).ok(); let value: Option<#ty> = #crate_name::InputValueType::parse(Some(value.clone())).ok();
value value
}) })
}); });
keys.push(name); keys.push(name);
use_keys.push(ident); use_keys.push(ident);
} else {
// requires
requires_getter.push(quote! {
let #ident: #ty = #crate_name::InputValueType::parse(params.get(#name).cloned()).
map_err(|err| err.into_error(ctx.position(), <#ty as #crate_name::Type>::qualified_type_name()))?;
});
use_keys.push(ident);
}
} }
add_keys.push(quote! { registry.add_keys(&<#entity_type as #crate_name::Type>::type_name(), #keys_str); }); add_keys.push(quote! { registry.add_keys(&<#entity_type as #crate_name::Type>::type_name(), #keys_str); });
create_entity_types.push( create_entity_types.push(
quote! { <#entity_type as #crate_name::Type>::create_type_info(registry); }, quote! { <#entity_type as #crate_name::Type>::create_type_info(registry); },
@ -163,6 +185,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
quote! { quote! {
if typename == &<#entity_type as #crate_name::Type>::type_name() { if typename == &<#entity_type as #crate_name::Type>::type_name() {
if let (#(#key_pat),*) = (#(#key_getter),*) { if let (#(#key_pat),*) = (#(#key_getter),*) {
#(#requires_getter)*
let ctx_obj = ctx.with_selection_set(&ctx.selection_set); let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
return #crate_name::OutputValueType::resolve(&#do_find, &ctx_obj, ctx.item).await; return #crate_name::OutputValueType::resolve(&#do_find, &ctx_obj, ctx.item).await;
} }
@ -290,6 +313,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
desc, desc,
default, default,
validator, validator,
..
}, },
) in args ) in args
{ {

View File

@ -143,6 +143,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
desc, desc,
default, default,
validator, validator,
..
}, },
) in args ) in args
{ {