Codegen: implement description for custom derives + improve tests

Description attribute was available, but not actually used for derive
Object, InputObject and enum and the fields on input object.

Description is now properly set in each of those cases.

Also, tests for all three derives now properly verify the meta
information (name and description) for the derived GraphQLType.
This commit is contained in:
theduke 2017-08-03 04:18:11 +02:00 committed by theduke
parent 6c45fba9bd
commit 81ce7780fa
6 changed files with 55 additions and 15 deletions

View file

@ -84,6 +84,11 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
let attrs = EnumAttrs::from_input(ast); let attrs = EnumAttrs::from_input(ast);
let name = attrs.name.unwrap_or(ast.ident.to_string()); let name = attrs.name.unwrap_or(ast.ident.to_string());
let meta_description = match attrs.description {
Some(descr) => quote!{ let meta = meta.description(#descr); },
None => quote!{ let meta = meta; },
};
let mut values = Vec::<Tokens>::new(); let mut values = Vec::<Tokens>::new();
let mut resolves = Vec::<Tokens>::new(); let mut resolves = Vec::<Tokens>::new();
let mut from_inputs = Vec::<Tokens>::new(); let mut from_inputs = Vec::<Tokens>::new();
@ -146,10 +151,11 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
} }
fn meta<'r>(registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { fn meta<'r>(registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> {
registry.build_enum_type::<#ident>(&[ let meta = registry.build_enum_type::<#ident>(&[
#(#values)* #(#values)*
]) ]);
.into_meta() #meta_description
meta.into_meta()
} }
fn resolve(&self, _: Option<&[::juniper::Selection]>, _: &::juniper::Executor<Self::Context>) -> ::juniper::Value { fn resolve(&self, _: Option<&[::juniper::Selection]>, _: &::juniper::Executor<Self::Context>) -> ::juniper::Value {

View file

@ -90,6 +90,11 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
let attrs = ObjAttrs::from_input(ast); let attrs = ObjAttrs::from_input(ast);
let name = attrs.name.unwrap_or(ast.ident.to_string()); let name = attrs.name.unwrap_or(ast.ident.to_string());
let meta_description = match attrs.description {
Some(descr) => quote!{ let meta = meta.description(#descr); },
None => quote!{ let meta = meta; },
};
let mut meta_fields = Vec::<Tokens>::new(); let mut meta_fields = Vec::<Tokens>::new();
let mut from_inputs = Vec::<Tokens>::new(); let mut from_inputs = Vec::<Tokens>::new();
let mut to_inputs = Vec::<Tokens>::new(); let mut to_inputs = Vec::<Tokens>::new();
@ -110,9 +115,9 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
::util::to_camel_case(field_ident.as_ref()) ::util::to_camel_case(field_ident.as_ref())
}, },
}; };
let descr = match field_attrs.description { let field_description = match field_attrs.description {
Some(s) => quote!{ Some(#s.to_string()) }, Some(s) => quote!{ let field = field.description(#s); },
None => quote!{ None }, None => quote!{ let field = field; },
}; };
let default = match field_attrs.default { let default = match field_attrs.default {
@ -127,18 +132,25 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
None => None, None => None,
}; };
let meta_field = match default { let create_meta_field = match default {
Some(ref def) => { Some(ref def) => {
quote!{ quote!{
registry.arg_with_default::<#field_ty>( #name, &#def), let field = registry.arg_with_default::<#field_ty>( #name, &#def);
} }
}, },
None => { None => {
quote!{ quote!{
registry.arg::<#field_ty>(#name), let field = registry.arg::<#field_ty>(#name);
} }
} }
}; };
let meta_field = quote!{
{
#create_meta_field
#field_description
field
},
};
meta_fields.push(meta_field); meta_fields.push(meta_field);
// Buil from_input clause. // Buil from_input clause.
@ -183,7 +195,9 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
let fields = &[ let fields = &[
#(#meta_fields)* #(#meta_fields)*
]; ];
registry.build_input_object_type::<#ident>(fields).into_meta() let meta = registry.build_input_object_type::<#ident>(fields);
#meta_description
meta.into_meta()
} }
} }

View file

@ -101,7 +101,6 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens {
let field_ty = &field.ty; let field_ty = &field.ty;
let field_attrs = ObjFieldAttrs::from_input(field); let field_attrs = ObjFieldAttrs::from_input(field);
let field_ident = field.ident.as_ref().unwrap(); let field_ident = field.ident.as_ref().unwrap();
let field_ident_name = field_ident.to_string();
// Build value. // Build value.
let name = match field_attrs.name { let name = match field_attrs.name {

View file

@ -24,6 +24,9 @@ fn test_derived_enum() {
let mut registry = juniper::Registry::new(HashMap::new()); let mut registry = juniper::Registry::new(HashMap::new());
let meta = SomeEnum::meta(&mut registry); let meta = SomeEnum::meta(&mut registry);
assert_eq!(meta.name(), Some("Some"));
assert_eq!(meta.description(), Some(&"enum descr".to_string()));
// Test Regular variant. // Test Regular variant.
assert_eq!( assert_eq!(
SomeEnum::Regular.to(), SomeEnum::Regular.to(),

View file

@ -1,10 +1,12 @@
use juniper::{ToInputValue, GraphQLType, FromInputValue}; use std::collections::HashMap;
use juniper::{self, ToInputValue, GraphQLType, FromInputValue};
#[derive(GraphQLInputObject, Debug, PartialEq)] #[derive(GraphQLInputObject, Debug, PartialEq)]
#[graphql(name="MyInput")] #[graphql(name="MyInput", description="input descr")]
struct Input { struct Input {
regular_field: String, regular_field: String,
#[graphql(name="haha", default="33")] #[graphql(name="haha", default="33", description="haha descr")]
c: i32, c: i32,
} }
@ -12,6 +14,12 @@ struct Input {
fn test_derived_input_object() { fn test_derived_input_object() {
assert_eq!(Input::name(), Some("MyInput")); assert_eq!(Input::name(), Some("MyInput"));
// Validate meta info.
let mut registry = juniper::Registry::new(HashMap::new());
let meta = Input::meta(&mut registry);
assert_eq!(meta.name(), Some("MyInput"));
assert_eq!(meta.description(), Some(&"input descr".to_string()));
let obj = Input { let obj = Input {
regular_field: "a".to_string(), regular_field: "a".to_string(),
c: 33, c: 33,

View file

@ -1,4 +1,6 @@
use juniper::{execute, GraphQLType, Value, Variables, EmptyMutation, RootNode}; use std::collections::HashMap;
use juniper::{self, execute, GraphQLType, Value, Variables, EmptyMutation, RootNode};
#[derive(GraphQLObject, Debug, PartialEq)] #[derive(GraphQLObject, Debug, PartialEq)]
#[graphql(name="MyObj", description="obj descr")] #[graphql(name="MyObj", description="obj descr")]
@ -22,6 +24,14 @@ graphql_object!(Query: () |&self| {
#[test] #[test]
fn test_derived_object() { fn test_derived_object() {
assert_eq!(Obj::name(), Some("MyObj")); assert_eq!(Obj::name(), Some("MyObj"));
// Verify meta info.
let mut registry = juniper::Registry::new(HashMap::new());
let meta = Obj::meta(&mut registry);
assert_eq!(meta.name(), Some("MyObj"));
assert_eq!(meta.description(), Some(&"obj descr".to_string()));
let doc = r#" let doc = r#"
{ {
obj { obj {