From d280a13b708260ce39ba573264ff33e2bbd96f27 Mon Sep 17 00:00:00 2001 From: Sunli Date: Mon, 10 Aug 2020 14:11:46 +0800 Subject: [PATCH] Add derive macro GQLMergeObject. #231 --- async-graphql-derive/src/lib.rs | 18 ++++++++++-- async-graphql-derive/src/merged_object.rs | 36 +++++------------------ src/base.rs | 7 +++++ src/lib.rs | 5 +++- tests/merged_object.rs | 30 ++++++++++++++++++- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/async-graphql-derive/src/lib.rs b/async-graphql-derive/src/lib.rs index a8c4e550..3f808b59 100644 --- a/async-graphql-derive/src/lib.rs +++ b/async-graphql-derive/src/lib.rs @@ -19,7 +19,7 @@ mod utils; use crate::utils::{add_container_attrs, parse_derive}; use proc_macro::TokenStream; use quote::quote; -use syn::{parse_macro_input, DeriveInput}; +use syn::parse_macro_input; use syn::{AttributeArgs, ItemImpl}; #[proc_macro_attribute] @@ -207,11 +207,25 @@ pub fn Scalar(args: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro_attribute] #[allow(non_snake_case)] pub fn MergedObject(args: TokenStream, input: TokenStream) -> TokenStream { + add_container_attrs( + quote!(GQLMergedObject), + parse_macro_input!(args as AttributeArgs), + input.into(), + ) + .unwrap_or_else(|err| err.to_compile_error()) + .into() +} + +#[proc_macro_derive(GQLMergedObject, attributes(item, graphql))] +pub fn derive_merged_object(input: TokenStream) -> TokenStream { + let (args, input) = match parse_derive(input.into()) { + Ok(r) => r, + Err(err) => return err.to_compile_error().into(), + }; let object_args = match args::Object::parse(parse_macro_input!(args as AttributeArgs)) { Ok(object_args) => object_args, Err(err) => return err.to_compile_error().into(), }; - let input = parse_macro_input!(input as DeriveInput); match merged_object::generate(&object_args, &input) { Ok(expanded) => expanded, Err(err) => err.to_compile_error().into(), diff --git a/async-graphql-derive/src/merged_object.rs b/async-graphql-derive/src/merged_object.rs index ed16ca9e..3dfb8c0c 100644 --- a/async-graphql-derive/src/merged_object.rs +++ b/async-graphql-derive/src/merged_object.rs @@ -1,9 +1,9 @@ use crate::args; use crate::utils::{get_crate_name, get_rustdoc}; use proc_macro::TokenStream; +use proc_macro2::Span; use quote::quote; -use syn::spanned::Spanned; -use syn::{Data, DeriveInput, Error, Ident, Result}; +use syn::{Data, DeriveInput, Error, LitInt, Result}; pub fn generate(object_args: &args::Object, input: &DeriveInput) -> Result { let crate_name = get_crate_name(object_args.internal); @@ -13,8 +13,6 @@ pub fn generate(object_args: &args::Object, input: &DeriveInput) -> Result Result Result Self { - #new_func - } - } - #[allow(clippy::all, clippy::pedantic)] impl #crate_name::Type for #ident { fn type_name() -> ::std::borrow::Cow<'static, str> { @@ -109,7 +89,7 @@ pub fn generate(object_args: &args::Object, input: &DeriveInput) -> Result) -> #crate_name::Result<#crate_name::serde_json::Value> { - self.0.resolve_field(ctx).await + #create_merged_obj.resolve_field(ctx).await } } diff --git a/src/base.rs b/src/base.rs index 7c3690d7..72062d07 100644 --- a/src/base.rs +++ b/src/base.rs @@ -166,6 +166,13 @@ impl OutputValueType for &T { } } +#[async_trait::async_trait] +impl ObjectType for &T { + async fn resolve_field(&self, ctx: &Context<'_>) -> Result { + T::resolve_field(*self, ctx).await + } +} + impl Type for Box { fn type_name() -> Cow<'static, str> { T::type_name() diff --git a/src/lib.rs b/src/lib.rs index 90fc433b..63218238 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -786,6 +786,9 @@ pub use async_graphql_derive::Scalar; /// #[MergedObject] /// struct MyObj(Object1, Object2, Object3); /// -/// let obj = MyObj::new(Object1 { a: 10 }, Object2 { b: 20 }, Object3 { c: 30 }); +/// let obj = MyObj(Object1 { a: 10 }, Object2 { b: 20 }, Object3 { c: 30 }); /// ``` pub use async_graphql_derive::MergedObject; + +/// Derive a GraphQL Merged object +pub use async_graphql_derive::GQLMergedObject; diff --git a/tests/merged_object.rs b/tests/merged_object.rs index da73f7ff..c855c022 100644 --- a/tests/merged_object.rs +++ b/tests/merged_object.rs @@ -64,7 +64,35 @@ pub async fn test_merged_object_macro() { #[Object] impl Query { async fn obj(&self) -> MyObj { - MyObj::new(Object1 { a: 10 }, Object2 { b: 20 }, Object3 { c: 30 }) + MyObj(Object1 { a: 10 }, Object2 { b: 20 }, Object3 { c: 30 }) + } + } + + let schema = Schema::new(Query, EmptyMutation, EmptySubscription); + let query = "{ obj { a b c } }"; + assert_eq!( + schema.execute(&query).await.unwrap().data, + serde_json::json!({ + "obj": { + "a": 10, + "b": 20, + "c": 30, + } + }) + ); +} + +#[async_std::test] +pub async fn test_merged_object_derive() { + #[derive(GQLMergedObject)] + struct MyObj(Object1, Object2, Object3); + + struct Query; + + #[Object] + impl Query { + async fn obj(&self) -> MyObj { + MyObj(Object1 { a: 10 }, Object2 { b: 20 }, Object3 { c: 30 }) } }