Add support for generic InputObject
. #387
This commit is contained in:
parent
94bd37c540
commit
74657c6242
|
@ -2,7 +2,9 @@ use darling::ast::{Data, Fields};
|
|||
use darling::util::Ignored;
|
||||
use darling::{FromDeriveInput, FromField, FromMeta, FromVariant};
|
||||
use inflector::Inflector;
|
||||
use syn::{Attribute, Generics, Ident, Lit, LitBool, LitStr, Meta, Type, Visibility};
|
||||
use syn::{
|
||||
Attribute, Generics, Ident, Lit, LitBool, LitStr, Meta, NestedMeta, Path, Type, Visibility,
|
||||
};
|
||||
|
||||
#[derive(FromMeta)]
|
||||
#[darling(default)]
|
||||
|
@ -267,6 +269,28 @@ pub struct InputObjectField {
|
|||
pub visible: Option<Visible>,
|
||||
}
|
||||
|
||||
pub struct PathList(pub Vec<Path>);
|
||||
|
||||
impl FromMeta for PathList {
|
||||
fn from_list(items: &[NestedMeta]) -> darling::Result<Self> {
|
||||
let mut res = Vec::new();
|
||||
for item in items {
|
||||
if let NestedMeta::Meta(Meta::Path(p)) = item {
|
||||
res.push(p.clone());
|
||||
} else {
|
||||
return Err(darling::Error::custom("Invalid path list"));
|
||||
}
|
||||
}
|
||||
Ok(PathList(res))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(FromMeta)]
|
||||
pub struct InputObjectConcrete {
|
||||
pub name: String,
|
||||
pub params: PathList,
|
||||
}
|
||||
|
||||
#[derive(FromDeriveInput)]
|
||||
#[darling(attributes(graphql), forward_attrs(doc))]
|
||||
pub struct InputObject {
|
||||
|
@ -283,6 +307,8 @@ pub struct InputObject {
|
|||
pub rename_fields: Option<RenameRule>,
|
||||
#[darling(default)]
|
||||
pub visible: Option<Visible>,
|
||||
#[darling(default, multiple, rename = "concrete")]
|
||||
pub concretes: Vec<InputObjectConcrete>,
|
||||
}
|
||||
|
||||
#[derive(FromMeta)]
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::utils::{
|
|||
|
||||
pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream> {
|
||||
let crate_name = get_crate_name(object_args.internal);
|
||||
let (impl_generics, ty_generics, where_clause) = object_args.generics.split_for_impl();
|
||||
let ident = &object_args.ident;
|
||||
let s = match &object_args.data {
|
||||
Data::Struct(s) => s,
|
||||
|
@ -170,46 +171,118 @@ pub fn generate(object_args: &args::InputObject) -> GeneratorResult<TokenStream>
|
|||
}
|
||||
|
||||
let visible = visible_fn(&object_args.visible);
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #ident {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::InputObject {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
input_fields: {
|
||||
let mut fields = #crate_name::indexmap::IndexMap::new();
|
||||
#(#schema_fields)*
|
||||
fields
|
||||
},
|
||||
visible: #visible,
|
||||
})
|
||||
}
|
||||
}
|
||||
let expanded = if object_args.concretes.is_empty() {
|
||||
quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #ident {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::InputType for #ident {
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
if let ::std::option::Option::Some(#crate_name::Value::Object(obj)) = value {
|
||||
#(#get_fields)*
|
||||
::std::result::Result::Ok(Self { #(#fields),* })
|
||||
} else {
|
||||
::std::result::Result::Err(#crate_name::InputValueError::expected_type(value.unwrap_or_default()))
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::InputObject {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
input_fields: {
|
||||
let mut fields = #crate_name::indexmap::IndexMap::new();
|
||||
#(#schema_fields)*
|
||||
fields
|
||||
},
|
||||
visible: #visible,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn to_value(&self) -> #crate_name::Value {
|
||||
let mut map = ::std::collections::BTreeMap::new();
|
||||
#(#put_fields)*
|
||||
#crate_name::Value::Object(map)
|
||||
}
|
||||
}
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::InputType for #ident {
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
if let ::std::option::Option::Some(#crate_name::Value::Object(obj)) = value {
|
||||
#(#get_fields)*
|
||||
::std::result::Result::Ok(Self { #(#fields),* })
|
||||
} else {
|
||||
::std::result::Result::Err(#crate_name::InputValueError::expected_type(value.unwrap_or_default()))
|
||||
}
|
||||
}
|
||||
|
||||
impl #crate_name::InputObjectType for #ident {}
|
||||
fn to_value(&self) -> #crate_name::Value {
|
||||
let mut map = ::std::collections::BTreeMap::new();
|
||||
#(#put_fields)*
|
||||
#crate_name::Value::Object(map)
|
||||
}
|
||||
}
|
||||
|
||||
impl #crate_name::InputObjectType for #ident {}
|
||||
}
|
||||
} else {
|
||||
let mut code = Vec::new();
|
||||
|
||||
code.push(quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
fn __internal_create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String where Self: #crate_name::InputType {
|
||||
registry.create_type::<Self, _>(|registry| #crate_name::registry::MetaType::InputObject {
|
||||
name: ::std::borrow::ToOwned::to_owned(#gql_typename),
|
||||
description: #desc,
|
||||
input_fields: {
|
||||
let mut fields = #crate_name::indexmap::IndexMap::new();
|
||||
#(#schema_fields)*
|
||||
fields
|
||||
},
|
||||
visible: #visible,
|
||||
})
|
||||
}
|
||||
|
||||
fn __internal_parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> where Self: #crate_name::InputType {
|
||||
if let ::std::option::Option::Some(#crate_name::Value::Object(obj)) = value {
|
||||
#(#get_fields)*
|
||||
::std::result::Result::Ok(Self { #(#fields),* })
|
||||
} else {
|
||||
::std::result::Result::Err(#crate_name::InputValueError::expected_type(value.unwrap_or_default()))
|
||||
}
|
||||
}
|
||||
|
||||
fn __internal_to_value(&self) -> #crate_name::Value where Self: #crate_name::InputType {
|
||||
let mut map = ::std::collections::BTreeMap::new();
|
||||
#(#put_fields)*
|
||||
#crate_name::Value::Object(map)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for concrete in &object_args.concretes {
|
||||
let gql_typename = &concrete.name;
|
||||
let params = &concrete.params.0;
|
||||
let concrete_type = quote! { #ident<#(#params),*> };
|
||||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::Type for #concrete_type {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> ::std::string::String {
|
||||
Self::__internal_create_type_info(registry)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #crate_name::InputType for #concrete_type {
|
||||
fn parse(value: ::std::option::Option<#crate_name::Value>) -> #crate_name::InputValueResult<Self> {
|
||||
Self::__internal_parse(value)
|
||||
}
|
||||
|
||||
fn to_value(&self) -> #crate_name::Value {
|
||||
self.__internal_to_value()
|
||||
}
|
||||
}
|
||||
|
||||
impl #crate_name::InputObjectType for #concrete_type {}
|
||||
};
|
||||
code.push(expanded);
|
||||
}
|
||||
quote!(#(#code)*)
|
||||
};
|
||||
Ok(expanded.into())
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::utils::{generate_default, get_crate_name, get_rustdoc, visible_fn, Ge
|
|||
pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream> {
|
||||
let crate_name = get_crate_name(interface_args.internal);
|
||||
let ident = &interface_args.ident;
|
||||
let generics = &interface_args.generics;
|
||||
let (impl_generics, ty_generics, where_clause) = interface_args.generics.split_for_impl();
|
||||
let s = match &interface_args.data {
|
||||
Data::Enum(s) => s,
|
||||
_ => {
|
||||
|
@ -89,7 +89,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
#crate_name::static_assertions::assert_impl_any!(#assert_ty: #crate_name::ObjectType, #crate_name::InterfaceType);
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics ::std::convert::From<#p> for #ident #generics {
|
||||
impl #impl_generics ::std::convert::From<#p> for #ident #ty_generics #where_clause {
|
||||
fn from(obj: #p) -> Self {
|
||||
#ident::#enum_name(obj)
|
||||
}
|
||||
|
@ -313,12 +313,12 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
#(#type_into_impls)*
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #ident #generics {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
#(#methods)*
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #crate_name::Type for #ident #generics {
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generics #crate_name::resolver_utils::ContainerType for #ident #generics {
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#(#resolvers)*
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
|
@ -369,13 +369,13 @@ pub fn generate(interface_args: &args::Interface) -> GeneratorResult<TokenStream
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generics #crate_name::OutputType for #ident #generics {
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
}
|
||||
}
|
||||
|
||||
impl #generics #crate_name::InterfaceType for #ident #generics {}
|
||||
impl #impl_generics #crate_name::InterfaceType for #ident #ty_generics #where_clause {}
|
||||
};
|
||||
Ok(expanded.into())
|
||||
}
|
||||
|
|
|
@ -10,9 +10,8 @@ use crate::utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult};
|
|||
pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream> {
|
||||
let crate_name = get_crate_name(object_args.internal);
|
||||
let ident = &object_args.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = object_args.generics.split_for_impl();
|
||||
let extends = object_args.extends;
|
||||
let generics = &object_args.generics;
|
||||
let where_clause = &generics.where_clause;
|
||||
let gql_typename = object_args
|
||||
.name
|
||||
.clone()
|
||||
|
@ -58,7 +57,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
let visible = visible_fn(&object_args.visible);
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #crate_name::Type for #ident #generics #where_clause {
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -92,7 +91,7 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generics #crate_name::resolver_utils::ContainerType for #ident #generics #where_clause {
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#create_merged_obj.resolve_field(ctx).await
|
||||
}
|
||||
|
@ -104,13 +103,13 @@ pub fn generate(object_args: &args::MergedObject) -> GeneratorResult<TokenStream
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generics #crate_name::OutputType for #ident #generics #where_clause {
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
}
|
||||
}
|
||||
|
||||
impl #generics #crate_name::ObjectType for #ident #generics #where_clause {}
|
||||
impl #impl_generics #crate_name::ObjectType for #ident #ty_generics #where_clause {}
|
||||
};
|
||||
Ok(expanded.into())
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@ use crate::utils::{generate_guards, get_crate_name, get_rustdoc, visible_fn, Gen
|
|||
pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream> {
|
||||
let crate_name = get_crate_name(object_args.internal);
|
||||
let ident = &object_args.ident;
|
||||
let generics = &object_args.generics;
|
||||
let where_clause = &generics.where_clause;
|
||||
let (impl_generics, ty_generics, where_clause) = object_args.generics.split_for_impl();
|
||||
let extends = object_args.extends;
|
||||
let gql_typename = object_args
|
||||
.name
|
||||
|
@ -156,12 +155,12 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
|
||||
let expanded = quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #ident #generics #where_clause {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
#(#getters)*
|
||||
}
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #crate_name::Type for #ident #generics #where_clause {
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -186,7 +185,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
|
||||
impl #generics #crate_name::resolver_utils::ContainerType for #ident #generics #where_clause {
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
#(#resolvers)*
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
|
@ -195,13 +194,13 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generics #crate_name::OutputType for #ident #generics #where_clause {
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
}
|
||||
}
|
||||
|
||||
impl #generics #crate_name::ObjectType for #ident #generics #where_clause {}
|
||||
impl #impl_generics #crate_name::ObjectType for #ident #ty_generics #where_clause {}
|
||||
};
|
||||
Ok(expanded.into())
|
||||
}
|
||||
|
|
|
@ -20,8 +20,6 @@ pub fn generate(
|
|||
) -> GeneratorResult<TokenStream> {
|
||||
let crate_name = get_crate_name(subscription_args.internal);
|
||||
let (self_ty, self_name) = get_type_path_and_name(item_impl.self_ty.as_ref())?;
|
||||
let generics = &item_impl.generics;
|
||||
let where_clause = &generics.where_clause;
|
||||
|
||||
let gql_typename = subscription_args
|
||||
.name
|
||||
|
@ -427,7 +425,7 @@ pub fn generate(
|
|||
#item_impl
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #crate_name::Type for #self_ty #where_clause {
|
||||
impl #crate_name::Type for #self_ty {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -452,7 +450,7 @@ pub fn generate(
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[allow(unused_braces, unused_variables)]
|
||||
impl #crate_name::SubscriptionType for #self_ty #where_clause {
|
||||
impl #crate_name::SubscriptionType for #self_ty {
|
||||
fn create_field_stream<'__life>(
|
||||
&'__life self,
|
||||
ctx: &'__life #crate_name::Context<'__life>,
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::utils::{get_crate_name, get_rustdoc, visible_fn, GeneratorResult};
|
|||
pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
||||
let crate_name = get_crate_name(union_args.internal);
|
||||
let ident = &union_args.ident;
|
||||
let generics = &union_args.generics;
|
||||
let (impl_generics, ty_generics, where_clause) = union_args.generics.split_for_impl();
|
||||
let s = match &union_args.data {
|
||||
Data::Enum(s) => s,
|
||||
_ => {
|
||||
|
@ -87,7 +87,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
#crate_name::static_assertions::assert_impl_one!(#assert_ty: #crate_name::ObjectType);
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics ::std::convert::From<#p> for #ident #generics {
|
||||
impl #impl_generics ::std::convert::From<#p> for #ident #ty_generics #where_clause {
|
||||
fn from(obj: #p) -> Self {
|
||||
#ident::#enum_name(obj)
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ 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 #generics ::std::convert::From<#p> for #ident #generics {
|
||||
impl #impl_generics ::std::convert::From<#p> for #ident #ty_generics #where_clause {
|
||||
fn from(obj: #p) -> Self {
|
||||
#ident::#enum_name(obj)
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
#(#type_into_impls)*
|
||||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
impl #generics #crate_name::Type for #ident #generics {
|
||||
impl #impl_generics #crate_name::Type for #ident #ty_generics #where_clause {
|
||||
fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
|
||||
::std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
|
||||
impl #generics #crate_name::resolver_utils::ContainerType for #ident #generics {
|
||||
impl #impl_generics #crate_name::resolver_utils::ContainerType for #ident #ty_generics #where_clause {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::ServerResult<::std::option::Option<#crate_name::Value>> {
|
||||
::std::result::Result::Ok(::std::option::Option::None)
|
||||
}
|
||||
|
@ -199,13 +199,13 @@ pub fn generate(union_args: &args::Union) -> GeneratorResult<TokenStream> {
|
|||
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
#[#crate_name::async_trait::async_trait]
|
||||
impl #generics #crate_name::OutputType for #ident #generics {
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
}
|
||||
}
|
||||
|
||||
impl #generics #crate_name::UnionType for #ident #generics {}
|
||||
impl #impl_generics #crate_name::UnionType for #ident #ty_generics #where_clause {}
|
||||
};
|
||||
Ok(expanded.into())
|
||||
}
|
||||
|
|
|
@ -349,3 +349,42 @@ pub async fn test_box_input_object() {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
pub async fn test_input_object_generic() {
|
||||
#[derive(InputObject)]
|
||||
#[graphql(
|
||||
concrete(name = "IntEqualityFilter", params(i32)),
|
||||
concrete(name = "StringEqualityFilter", params(String))
|
||||
)]
|
||||
struct EqualityFilter<T: InputType> {
|
||||
equals: Option<T>,
|
||||
not_equals: Option<T>,
|
||||
}
|
||||
|
||||
assert_eq!(EqualityFilter::<i32>::type_name(), "IntEqualityFilter");
|
||||
assert_eq!(
|
||||
EqualityFilter::<String>::type_name(),
|
||||
"StringEqualityFilter"
|
||||
);
|
||||
|
||||
struct Root;
|
||||
|
||||
#[Object]
|
||||
impl Root {
|
||||
async fn q(&self, input: EqualityFilter<i32>) -> i32 {
|
||||
input.equals.unwrap_or_default() + input.not_equals.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
let schema = Schema::new(Root, EmptyMutation, EmptySubscription);
|
||||
let query = r#"{
|
||||
q(input: { equals: 7, notEquals: 8 } )
|
||||
}"#;
|
||||
assert_eq!(
|
||||
schema.execute(query).await.into_result().unwrap().data,
|
||||
value!({
|
||||
"q": 15
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user