Rebase async_await onto master (#454)

* feat: Raw identifier support in object macro

This commit implements raw identifier (`r#name`) support
for field names (methods) and arguments in the `object` proc macro.

Eg:

```rust
impl T {
  fn r#type(r#trait: String) -> bool {}
}
```

* Rebase onto master

* Fix merge [skip ci]
This commit is contained in:
nWacky 2019-11-08 12:46:48 +03:00 committed by theduke
parent b133a0f3c2
commit 237e69c036
7 changed files with 136 additions and 7 deletions

View file

@ -0,0 +1,105 @@
#[cfg(test)]
use fnv::FnvHashMap;
#[cfg(test)]
use juniper::Object;
#[cfg(test)]
use juniper::{
self, execute, graphql_value, DefaultScalarValue, EmptyMutation, GraphQLInputObject,
GraphQLType, RootNode, Value, Variables,
};
pub struct Query;
#[juniper::object]
impl Query {
fn r#type(r#fn: MyInputType) -> Vec<String> {
unimplemented!()
}
}
#[derive(GraphQLInputObject, Debug, PartialEq)]
struct MyInputType {
r#trait: String,
}
#[test]
fn supports_raw_idents_in_types_and_args() {
let doc = r#"
{
__type(name: "Query") {
fields {
name
args {
name
}
}
}
}
"#;
let value = run_type_info_query(&doc);
assert_eq!(
value,
graphql_value!(
{
"__type": {
"fields": [
{
"name": "type",
"args": [
{
"name": "fn"
}
]
}
]
}
}
),
);
}
#[test]
fn supports_raw_idents_in_fields_of_input_types() {
let doc = r#"
{
__type(name: "MyInputType") {
inputFields {
name
}
}
}
"#;
let value = run_type_info_query(&doc);
assert_eq!(
value,
graphql_value!(
{
"__type": {
"inputFields": [
{
"name": "trait",
}
]
}
}
),
);
}
#[cfg(test)]
fn run_type_info_query(doc: &str) -> Value {
let schema = RootNode::new(Query, EmptyMutation::<()>::new());
let (result, errs) =
execute(doc, None, &schema, &Variables::new(), &()).expect("Execution failed");
assert_eq!(errs, []);
println!("Result: {:#?}", result);
result
}

View file

@ -3,5 +3,6 @@ mod util;
mod derive_enum;
mod derive_input_object;
mod derive_object;
mod derive_object_with_raw_idents;
mod scalar_value_transparent;
mod unions;

View file

@ -1,6 +1,6 @@
# master
- No changes yet
- Correctly handle raw identifiers in field and argument names.
# [[0.14.1] 2019-10-24](https://github.com/graphql-rust/juniper/releases/tag/juniper-0.14.1)

View file

@ -99,12 +99,12 @@ where
use futures::future::{ready, FutureExt};
match field_name {
"__schema" | "__type" => {
let v = self.resolve_field(info, field_name, arguments, executor);
Box::pin(ready(v))
self.resolve_field(info, field_name, arguments, executor)
}
_ => self
.query_type
.resolve_field_async(info, field_name, arguments, executor),
.resolve_field_async(info, field_name, arguments, executor)
.await
}
}
}

View file

@ -170,7 +170,7 @@ pub fn impl_input_object(ast: &syn::DeriveInput, is_internal: bool) -> TokenStre
}
None => {
// Note: auto camel casing when no custom name specified.
crate::util::to_camel_case(&field_ident.to_string())
crate::util::to_camel_case(&unraw(&field_ident.to_string()))
}
};
let field_description = match field_attrs.description {

View file

@ -354,6 +354,24 @@ impl Query {
}
```
## Raw identifiers
You can use [raw identifiers](https://doc.rust-lang.org/stable/edition-guide/rust-2018/module-system/raw-identifiers.html)
if you want a GrahpQL field that happens to be a Rust keyword:
```
struct User {
r#type: String,
}
#[juniper::object]
impl User {
fn r#type(&self) -> &str {
&self.r#type
}
}
```
*/
#[proc_macro_attribute]
pub fn object(args: TokenStream, input: TokenStream) -> TokenStream {

View file

@ -631,6 +631,11 @@ pub struct GraphQLTypeDefinitionField {
pub is_async: bool,
}
pub fn unraw(s: &str) -> String {
use syn::ext::IdentExt;
quote::format_ident!("{}", s).unraw().to_string()
}
/// Definition of a graphql type based on information extracted
/// by various macros.
/// The definition can be rendered to Rust code.
@ -679,7 +684,7 @@ impl GraphQLTypeDefiniton {
let field_definitions = self.fields.iter().map(|field| {
let args = field.args.iter().map(|arg| {
let arg_type = &arg._type;
let arg_name = &arg.name;
let arg_name = unraw(&arg.name);
let description = match arg.description.as_ref() {
Some(value) => quote!( .description( #value ) ),
@ -719,7 +724,7 @@ impl GraphQLTypeDefiniton {
None => quote!(),
};
let field_name = &field.name;
let field_name = unraw(&field.name);
let _type = &field._type;
quote! {