(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
This commit is contained in:
Christoph Herzog 2019-07-22 21:46:55 +02:00 committed by theduke
parent 9e849fe512
commit 049ba0c9dc
3 changed files with 33 additions and 4 deletions

View file

@ -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

View file

@ -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::<Context>::new());
@ -264,6 +285,7 @@ fn object_query() {
"argWithDescription": true,
"withContextChild": { "ctx": true },
"withLifetimeChild": { "value": "blub" },
"withMutArg": false,
})
);
}

View file

@ -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);
));