From 049ba0c9dcbacc7e51ab29258b117366239d031b Mon Sep 17 00:00:00 2001 From: Christoph Herzog Date: Mon, 22 Jul 2019 21:46:55 +0200 Subject: [PATCH] (codegen) Respect mut modifier on arguments in object proc macro This commit forwards `mut` declaration of arguments in a #[juniper::object] macro invocation to the generated code. Closes #399 --- juniper/CHANGELOG.md | 2 ++ juniper/src/macros/tests/impl_object.rs | 22 ++++++++++++++++++++++ juniper_codegen/src/impl_object.rs | 13 +++++++++---- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/juniper/CHANGELOG.md b/juniper/CHANGELOG.md index 894f5ea3..70a3752c 100644 --- a/juniper/CHANGELOG.md +++ b/juniper/CHANGELOG.md @@ -2,6 +2,8 @@ - No changes yet +- Allow `mut` arguments for resolver functions in `#[object]` macros [#402](https://github.com/graphql-rust/juniper/pull/402) + # [[0.13.0] 2019-07-19](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.13.0) ### newtype ScalarValue derive diff --git a/juniper/src/macros/tests/impl_object.rs b/juniper/src/macros/tests/impl_object.rs index 81427cd7..bbcfdb18 100644 --- a/juniper/src/macros/tests/impl_object.rs +++ b/juniper/src/macros/tests/impl_object.rs @@ -101,6 +101,13 @@ impl<'a> Query { fn with_lifetime_child(&self) -> WithLifetime<'a> { WithLifetime { value: "blub" } } + + fn with_mut_arg(mut arg: bool) -> bool { + if arg { + arg = !arg; + } + arg + } } #[derive(Default)] @@ -216,6 +223,19 @@ fn object_introspect() { "description": None, "args": [], }, + { + "name": "withMutArg", + "description": None, + "args": [ + { + "name": "arg", + "description": None, + "type": { + "name": None, + }, + } + ], + }, ] }) ); @@ -241,6 +261,7 @@ fn object_query() { withLifetimeChild { value } + withMutArg(arg: true) } "#; let schema = RootNode::new(Query { b: true }, EmptyMutation::::new()); @@ -264,6 +285,7 @@ fn object_query() { "argWithDescription": true, "withContextChild": { "ctx": true }, "withLifetimeChild": { "value": "blub" }, + "withMutArg": false, }) ); } diff --git a/juniper_codegen/src/impl_object.rs b/juniper_codegen/src/impl_object.rs index 3fe7af3f..01fb7450 100644 --- a/juniper_codegen/src/impl_object.rs +++ b/juniper_codegen/src/impl_object.rs @@ -129,8 +129,10 @@ pub fn build_object(args: TokenStream, body: TokenStream, is_internal: bool) -> ); } syn::FnArg::Captured(ref captured) => { - let arg_ident = match &captured.pat { - syn::Pat::Ident(ref pat_ident) => &pat_ident.ident, + let (arg_ident, is_mut) = match &captured.pat { + syn::Pat::Ident(ref pat_ident) => { + (&pat_ident.ident, pat_ident.mutability.is_some()) + } _ => { panic!("Invalid token for function argument"); } @@ -147,7 +149,7 @@ pub fn build_object(args: TokenStream, body: TokenStream, is_internal: bool) -> else if util::type_is_identifier(&captured.ty, "Executor") { panic!("Invalid executor argument: to access the Executor, you need to specify the type as a reference.\nDid you mean &Executor?"); } - // Check for executor arg. + // Check for context arg. else if context_type .clone() .map(|ctx| util::type_is_ref_of(&captured.ty, ctx)) @@ -167,12 +169,15 @@ pub fn build_object(args: TokenStream, body: TokenStream, is_internal: bool) -> quote!(captured.ty), ); } else { + // Regular argument. + let ty = &captured.ty; // TODO: respect graphql attribute overwrite. let final_name = util::to_camel_case(&arg_name); let expect_text = format!("Internal error: missing argument {} - validation must have failed", &final_name); + let mut_modifier = if is_mut { quote!(mut) } else { quote!() }; resolve_parts.push(quote!( - let #arg_ident = args + let #mut_modifier #arg_ident = args .get::<#ty>(#final_name) .expect(#expect_text); ));