diff --git a/juniper/src/macros/tests/input_object.rs b/juniper/src/executor_tests/introspection/input_object.rs similarity index 86% rename from juniper/src/macros/tests/input_object.rs rename to juniper/src/executor_tests/introspection/input_object.rs index a4219be6..c4e15758 100644 --- a/juniper/src/macros/tests/input_object.rs +++ b/juniper/src/executor_tests/introspection/input_object.rs @@ -8,82 +8,81 @@ use types::scalars::EmptyMutation; struct Root; -graphql_input_object!( - struct DefaultName { - field_one: String, - field_two: String, - } -); +#[derive(GraphQLInputObject)] +#[graphql(_internal)] +struct DefaultName { + field_one: String, + field_two: String, +} -graphql_input_object!( - struct NoTrailingComma { - field_one: String, - field_two: String - } -); +#[derive(GraphQLInputObject)] +#[graphql(_internal)] +struct NoTrailingComma { + field_one: String, + field_two: String +} -graphql_input_object!( - #[derive(Debug)] - struct Derive { - field_one: String, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +struct Derive { + field_one: String, +} -graphql_input_object!( - struct Named as "ANamedInputObject" { - field_one: String, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(name = "ANamedInputObject", _internal)] +struct Named { + field_one: String, +} -graphql_input_object!( - description: "Description for the input object" +#[derive(GraphQLInputObject, Debug)] +#[graphql(description = "Description for the input object", _internal)] +struct Description { + field_one: String, +} - struct Description { - field_one: String, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +pub struct Public { + field_one: String, +} -graphql_input_object!( - pub struct Public { - field_one: String, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(description = "Description for the input object", _internal)] +pub struct PublicWithDescription { + field_one: String, +} -graphql_input_object!( - description: "Description for the input object" +#[derive(GraphQLInputObject, Debug)] +#[graphql(name = "APublicNamedInputObjectWithDescription", + description = "Description for the input object", + _internal)] +pub struct NamedPublicWithDescription { + field_one: String, +} - pub struct PublicWithDescription { - field_one: String, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(name = "APublicNamedInputObject", _internal)] +pub struct NamedPublic { + field_one: String, +} -graphql_input_object!( - description: "Description for the input object" +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +struct FieldDescription { + #[graphql(description = "The first field")] + field_one: String, + #[graphql(description = "The second field")] + field_two: String, +} - pub struct NamedPublicWithDescription as "APublicNamedInputObjectWithDescription" { - field_one: String, - } -); - -graphql_input_object!( - pub struct NamedPublic as "APublicNamedInputObject" { - field_one: String, - } -); - -graphql_input_object!( - struct FieldDescription { - field_one: String as "The first field", - field_two: String as "The second field", - } -); - -graphql_input_object!( - struct FieldWithDefaults { - field_one = 123: i32, - field_two = 456: i32 as "The second field", - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +struct FieldWithDefaults { + #[graphql(default = "123")] + field_one: i32, + #[graphql(default = "456", description = "The second field")] + field_two: i32, +} graphql_object!(Root: () |&self| { field test_field( diff --git a/juniper/src/executor_tests/introspection.rs b/juniper/src/executor_tests/introspection/mod.rs similarity index 98% rename from juniper/src/executor_tests/introspection.rs rename to juniper/src/executor_tests/introspection/mod.rs index 1480ca17..2471b0b7 100644 --- a/juniper/src/executor_tests/introspection.rs +++ b/juniper/src/executor_tests/introspection/mod.rs @@ -1,8 +1,16 @@ +mod input_object; + +// This asserts that the input objects defined public actually became public +#[allow(unused_imports)] +use self::input_object::{NamedPublic, NamedPublicWithDescription}; + use executor::Variables; use value::Value; use schema::model::RootNode; use types::scalars::EmptyMutation; + + #[derive(GraphQLEnum)] #[graphql(name = "SampleEnum", _internal)] enum Sample { diff --git a/juniper/src/executor_tests/variables.rs b/juniper/src/executor_tests/variables.rs index 900d9eda..bbbad525 100644 --- a/juniper/src/executor_tests/variables.rs +++ b/juniper/src/executor_tests/variables.rs @@ -30,39 +30,35 @@ graphql_scalar!(TestComplexScalar { } }); +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +struct TestInputObject { + a: Option, + b: Option>>, + c: String, + d: Option, +} -graphql_input_object!( - #[derive(Debug)] - struct TestInputObject { - a: Option, - b: Option>>, - c: String, - d: Option, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +struct TestNestedInputObject { + na: TestInputObject, + nb: String, +} -graphql_input_object!( - #[derive(Debug)] - struct TestNestedInputObject { - na: TestInputObject, - nb: String, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +struct ExampleInputObject { + a: Option, + b: i32, +} -graphql_input_object!( - #[derive(Debug)] - struct ExampleInputObject { - a: Option, - b: i32, - } -); - -graphql_input_object!( - #[derive(Debug)] - struct InputWithDefaults { - a = 123: i32, - } -); +#[derive(GraphQLInputObject, Debug)] +#[graphql(_internal)] +struct InputWithDefaults { + #[graphql(default = "123")] + a: i32, +} graphql_object!(TestType: () |&self| { field field_with_object_input(input: Option) -> String { diff --git a/juniper/src/macros/input_object.rs b/juniper/src/macros/input_object.rs deleted file mode 100644 index adf43669..00000000 --- a/juniper/src/macros/input_object.rs +++ /dev/null @@ -1,283 +0,0 @@ -/** -Create an input object - -Input objects are used as data carriers for complex input values to -fields and mutations. Unlike the other helper macros, -`graphql_input_object!` actually *creates* the struct you define. It -does not add anything to the struct definition itself - what you type -is what will be generated: - -```rust -# #[macro_use] extern crate juniper; -# -graphql_input_object!( - description: "Coordinates for the user" - - struct Coordinates { - longitude: f64 as "The X coordinate, from -180 to +180", - latitude: f64 as "The Y coordinate, from -90 to +90", - } -); - -# fn main() { } -``` - -This macro creates the struct as specified and implements -`FromInputValue` to automatically parse values provided from variables -and arguments. - -If you want to expose the struct under a different name than the Rust -type, you can write `struct Coordinates as "MyCoordinates" { ...`. - -You can specify *default values* for input object fields; the syntax -is similar to argument default values: - -```rust -# #[macro_use] extern crate juniper; -# -graphql_input_object!( - struct SampleObject { - foo = 123: i32 as "A sample field, defaults to 123 if omitted" - } -); - -# fn main() { } -``` - -*/ -#[macro_export] -macro_rules! graphql_input_object { - // Calls $val.$func($arg) if $arg is not None - ( @maybe_apply, None, $func:ident, $val:expr ) => { $val }; - ( @maybe_apply, $arg:tt, $func:ident, $val:expr ) => { $val.$func($arg) }; - - // Calls $val.description($descr) when $descr is not empty - ( @apply_description, , $val:expr ) => { $val }; - ( @apply_description, $descr:tt , $val:expr ) => { $val.description($descr) }; - - // Generate the FromInputValue::from method body, provided a - // HashMap<&str, &InputValue> in $var - ( - @generate_from_input_value, - $name:tt, $var:tt, - ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* ) - ) => { - Some($name { - $( $field_name: { - let n = $crate::to_camel_case(stringify!($field_name)); - let v: Option<&&$crate::InputValue> = $var.get(&n[..]); - - match v { - $( Some(&&$crate::InputValue::Null) | None if true => $default, )* - Some(v) => $crate::FromInputValue::from_input_value(v).unwrap(), - _ => $crate::FromInputValue::from_input_value(&$crate::InputValue::null()).unwrap() - } - } ),* - }) - }; - - // Generate the ToInputValue::To method body, provided self in $self - ( - @generate_to_input_value, - $name:tt, $selfvar:tt, - ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* ) - ) => { - $crate::InputValue::object(vec![ - $( - ($crate::to_camel_case(stringify!($field_name)), $selfvar.$field_name.to_input_value()) - ),* - ].into_iter().collect()) - }; - - // Generate the struct declaration, including (Rust) meta attributes - ( - @generate_struct_fields, - ( $($meta:tt)* ), ( $($pubmod:tt)* ), $name:tt, - ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* ) - ) => { - $($meta)* $($pubmod)* struct $name { - $( $field_name: $field_type, )* - } - }; - - // Generate single field meta for field with default value - ( - @generate_single_meta_field, - $reg:tt, - ( $field_name:ident = $default:tt : $field_type:ty $(as $descr:tt)* ) - ) => { - graphql_input_object!( - @apply_description, - $($descr)*, - $reg.arg_with_default::<$field_type>( - &$crate::to_camel_case(stringify!($field_name)), - &$default, &())) - }; - - // Generate single field meta for field without default value - ( - @generate_single_meta_field, - $reg:tt, - ( $field_name:ident : $field_type:ty $(as $descr:tt)* ) - ) => { - graphql_input_object!( - @apply_description, - $($descr)*, - $reg.arg::<$field_type>( - &$crate::to_camel_case(stringify!($field_name)), &())) - }; - - // Generate the input field meta list, i.e. &[Argument] for - ( - @generate_meta_fields, - $reg:tt, - ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* ) - ) => { - &[ - $( - graphql_input_object!( - @generate_single_meta_field, - $reg, - ( $field_name $(= $default)* : $field_type $(as $descr)* ) - ) - ),* - ] - }; - - // #[...] struct $name { ... } - // struct $name { ... } - ( - @parse, - ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ), - $(#[$meta:meta])* struct $name:ident { $($fields:tt)* } $($rest:tt)* - ) => { - graphql_input_object!( - @parse, - ( ( $(#[$meta])* ), ( ), $name, (stringify!($name)), ($($fields)*), $descr ), - $($rest)* - ); - }; - - // #[...] pub struct $name { ... } - // pub struct $name { ... } - ( - @parse, - ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ), - $(#[$meta:meta])* pub struct $name:ident { $($fields:tt)* } $($rest:tt)* - ) => { - graphql_input_object!( - @parse, - ( ( $(#[$meta])* ), ( pub ), $name, (stringify!($name)), ($($fields)*), $descr ), - $($rest)* - ); - }; - - // #[...] struct $name as "GraphQLName" { ... } - // struct $name as "GraphQLName" { ... } - ( - @parse, - ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ), - $(#[$meta:meta])* struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)* - ) => { - graphql_input_object!( - @parse, - ( ( $($meta)* ), ( ), $name, $outname, ($($fields)*), $descr ), - $($rest)* - ); - }; - - // #[...] pub struct $name as "GraphQLName" { ... } - // pub struct $name as "GraphQLName" { ... } - ( - @parse, - ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ), - $(#[$meta:meta])* pub struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)* - ) => { - graphql_input_object!( - @parse, - ( ( $($meta)* ), ( pub ), $name, $outname, ($($fields)*), $descr ), - $($rest)* - ); - }; - - // description: - ( - @parse, - ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $_ignore:tt ), - description: $descr:tt $($rest:tt)* - ) => { - graphql_input_object!( - @parse, - ( $meta, $pubmod, $name, $outname, $fields, $descr ), - $($rest)* - ); - }; - - // No more data to parse, generate the struct and impls - ( - @parse, - ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $descr:tt ), - ) => { - graphql_input_object!(@generate_struct_fields, $meta, $pubmod, $name, $fields); - - impl $crate::FromInputValue for $name { - fn from_input_value(value: &$crate::InputValue) -> Option<$name> { - if let Some(obj) = value.to_object_value() { - graphql_input_object!(@generate_from_input_value, $name, obj, $fields) - } - else { - None - } - } - } - - impl $crate::ToInputValue for $name { - fn to_input_value(&self) -> $crate::InputValue { - graphql_input_object!(@generate_to_input_value, $name, self, $fields) - } - } - - impl $crate::GraphQLType for $name { - type Context = (); - type TypeInfo = (); - - fn name(_: &()) -> Option<&str> { - Some($outname) - } - - fn meta<'r>(_: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { - let fields = graphql_input_object!(@generate_meta_fields, registry, $fields); - graphql_input_object!( - @maybe_apply, $descr, description, - registry.build_input_object_type::<$name>(&(), fields)).into_meta() - } - } - }; - - // Entry point: parse calls starting with a struct declaration - ( $(#[$meta:meta])* struct $($items:tt)* ) => { - graphql_input_object!( - @parse, - ( ( ), ( ), None, None, None, None ), - $(#[$meta])* struct $($items)* - ); - }; - - // Entry point: parse calls starting with a public struct declaration - ( $(#[$meta:meta])* pub struct $($items:tt)* ) => { - graphql_input_object!( - @parse, - ( ( ), ( ), None, None, None, None ), - $(#[$meta])* pub struct $($items)* - ); - }; - - // Entry point: parse calls starting with the description - ( description: $($items:tt)* ) => { - graphql_input_object!( - @parse, - ( ( ), ( ), None, None, None, None ), - description: $($items)* - ); - }; -} diff --git a/juniper/src/macros/mod.rs b/juniper/src/macros/mod.rs index c41f6be2..fa97f3ee 100644 --- a/juniper/src/macros/mod.rs +++ b/juniper/src/macros/mod.rs @@ -9,8 +9,6 @@ mod args; #[macro_use] mod field; #[macro_use] -mod input_object; -#[macro_use] mod union; #[cfg(test)] diff --git a/juniper/src/macros/tests/args.rs b/juniper/src/macros/tests/args.rs index 007233fc..6d51632a 100644 --- a/juniper/src/macros/tests/args.rs +++ b/juniper/src/macros/tests/args.rs @@ -19,12 +19,11 @@ Syntax to validate: */ -graphql_input_object!( - #[derive(Debug)] - struct Point { - x: i32, - } -); +#[derive(GraphQLInputObject)] +#[graphql(_internal)] +struct Point { + x: i32, +} graphql_object!(Root: () |&self| { field simple() -> i32 { 0 } diff --git a/juniper/src/macros/tests/mod.rs b/juniper/src/macros/tests/mod.rs index 5b458865..1738b128 100644 --- a/juniper/src/macros/tests/mod.rs +++ b/juniper/src/macros/tests/mod.rs @@ -1,6 +1,4 @@ mod scalar; -#[allow(dead_code)] -mod input_object; mod args; mod field; mod object; @@ -9,6 +7,4 @@ mod union; mod enums; -// This asserts that the input objects defined public actually became public -#[allow(unused_imports)] -use self::input_object::{NamedPublic, NamedPublicWithDescription}; +