diff --git a/juniper/src/ast.rs b/juniper/src/ast.rs index c63186b5a..d95cbde0d 100644 --- a/juniper/src/ast.rs +++ b/juniper/src/ast.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::borrow::Cow; use std::collections::HashMap; use std::hash::Hash; use std::vec; @@ -14,13 +15,13 @@ use parser::Spanning; #[derive(Clone, Eq, PartialEq, Debug)] pub enum Type<'a> { /// A nullable named type, e.g. `String` - Named(&'a str), + Named(Cow<'a, str>), /// A nullable list type, e.g. `[String]` /// /// The list itself is what's nullable, the containing type might be non-null. List(Box>), /// A non-null named type, e.g. `String!` - NonNullNamed(&'a str), + NonNullNamed(Cow<'a, str>), /// A non-null list type, e.g. `[String]!`. /// /// The list itself is what's non-null, the containing type might be null. @@ -168,7 +169,7 @@ impl<'a> Type<'a> { /// Only applies to named types; lists will return `None`. pub fn name(&self) -> Option<&str> { match *self { - Type::Named(n) | Type::NonNullNamed(n) => Some(n), + Type::Named(ref n) | Type::NonNullNamed(ref n) => Some(n), _ => None, } } @@ -178,7 +179,7 @@ impl<'a> Type<'a> { /// All type literals contain exactly one named type. pub fn innermost_name(&self) -> &str { match *self { - Type::Named(n) | Type::NonNullNamed(n) => n, + Type::Named(ref n) | Type::NonNullNamed(ref n) => n, Type::List(ref l) | Type::NonNullList(ref l) => l.innermost_name(), } } @@ -195,8 +196,8 @@ impl<'a> Type<'a> { impl<'a> fmt::Display for Type<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Type::Named(n) => write!(f, "{}", n), - Type::NonNullNamed(n) => write!(f, "{}!", n), + Type::Named(ref n) => write!(f, "{}", n), + Type::NonNullNamed(ref n) => write!(f, "{}!", n), Type::List(ref t) => write!(f, "[{}]", t), Type::NonNullList(ref t) => write!(f, "[{}]!", t), } diff --git a/juniper/src/executor.rs b/juniper/src/executor.rs index fd6e8e71a..56c57e146 100644 --- a/juniper/src/executor.rs +++ b/juniper/src/executor.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::HashMap; use std::sync::RwLock; @@ -156,25 +157,34 @@ impl<'a, CtxT> Executor<'a, CtxT> { /// Resolve a single arbitrary value, mapping the context to a new type pub fn resolve_with_ctx>( &self, + info: &T::TypeInfo, value: &T, ) -> ExecutionResult where NewCtxT: FromContext, { self.replaced_context(>::from(self.context)) - .resolve(value) + .resolve(info, value) } /// Resolve a single arbitrary value into an `ExecutionResult` - pub fn resolve>(&self, value: &T) -> ExecutionResult { - Ok(value.resolve(self.current_selection_set, self)) + pub fn resolve>( + &self, + info: &T::TypeInfo, + value: &T, + ) -> ExecutionResult { + Ok(value.resolve(info, self.current_selection_set, self)) } /// Resolve a single arbitrary value into a return value /// /// If the field fails to resolve, `null` will be returned. - pub fn resolve_into_value>(&self, value: &T) -> Value { - match self.resolve(value) { + pub fn resolve_into_value>( + &self, + info: &T::TypeInfo, + value: &T, + ) -> Value { + match self.resolve(info, value) { Ok(v) => v, Err(e) => { let position = self.field_path.location().clone(); @@ -383,8 +393,10 @@ where }; value = match op.item.operation_type { - OperationType::Query => executor.resolve_into_value(&root_node), - OperationType::Mutation => executor.resolve_into_value(&root_node.mutation_type), + OperationType::Query => executor.resolve_into_value(&root_node.query_info, &root_node), + OperationType::Mutation => { + executor.resolve_into_value(&root_node.mutation_info, &root_node.mutation_type) + } }; } @@ -404,24 +416,24 @@ impl<'r> Registry<'r> { /// /// If the registry hasn't seen a type with this name before, it will /// construct its metadata and store it. - pub fn get_type(&mut self) -> Type<'r> + pub fn get_type(&mut self, info: &T::TypeInfo) -> Type<'r> where T: GraphQLType, { - if let Some(name) = T::name() { - if !self.types.contains_key(name) { - self.insert_placeholder(name, Type::NonNullNamed(name)); - let meta = T::meta(self); - self.types.insert(name.to_owned(), meta); + if let Some(name) = T::name(info) { + if !self.types.contains_key(&name.to_string()) { + self.insert_placeholder(&name, Type::NonNullNamed(Cow::Owned(name.to_string()))); + let meta = T::meta(info, self); + self.types.insert(name.to_string(), meta); } - self.types[name].as_type() + self.types[&name.to_string()].as_type() } else { - T::meta(self).as_type() + T::meta(info, self).as_type() } } /// Create a field with the provided name - pub fn field(&mut self, name: &str) -> Field<'r> + pub fn field(&mut self, name: &str, info: &T::TypeInfo) -> Field<'r> where T: GraphQLType, { @@ -429,13 +441,17 @@ impl<'r> Registry<'r> { name: name.to_owned(), description: None, arguments: None, - field_type: self.get_type::(), + field_type: self.get_type::(info), deprecation_reason: None, } } #[doc(hidden)] - pub fn field_convert<'a, T: IntoResolvable<'a, I, C>, I, C>(&mut self, name: &str) -> Field<'r> + pub fn field_convert<'a, T: IntoResolvable<'a, I, C>, I, C>( + &mut self, + name: &str, + info: &I::TypeInfo, + ) -> Field<'r> where I: GraphQLType, { @@ -443,28 +459,28 @@ impl<'r> Registry<'r> { name: name.to_owned(), description: None, arguments: None, - field_type: self.get_type::(), + field_type: self.get_type::(info), deprecation_reason: None, } } /// Create an argument with the provided name - pub fn arg(&mut self, name: &str) -> Argument<'r> + pub fn arg(&mut self, name: &str, info: &T::TypeInfo) -> Argument<'r> where T: GraphQLType + FromInputValue, { - Argument::new(name, self.get_type::()) + Argument::new(name, self.get_type::(info)) } /// Create an argument with a default value /// /// When called with type `T`, the actual argument will be given the type /// `Option`. - pub fn arg_with_default(&mut self, name: &str, value: &T) -> Argument<'r> + pub fn arg_with_default(&mut self, name: &str, value: &T, info: &T::TypeInfo) -> Argument<'r> where T: GraphQLType + ToInputValue + FromInputValue, { - Argument::new(name, self.get_type::>()).default_value(value.to()) + Argument::new(name, self.get_type::>(info)).default_value(value.to()) } fn insert_placeholder(&mut self, name: &str, of_type: Type<'r>) { @@ -479,23 +495,23 @@ impl<'r> Registry<'r> { /// Create a scalar meta type /// /// This expects the type to implement `FromInputValue`. - pub fn build_scalar_type(&mut self) -> ScalarMeta<'r> + pub fn build_scalar_type(&mut self, info: &T::TypeInfo) -> ScalarMeta<'r> where T: FromInputValue + GraphQLType, { - let name = T::name().expect("Scalar types must be named. Implement name()"); - ScalarMeta::new::(name) + let name = T::name(info).expect("Scalar types must be named. Implement name()"); + ScalarMeta::new::(Cow::Owned(name.to_string())) } /// Create a list meta type - pub fn build_list_type(&mut self) -> ListMeta<'r> { - let of_type = self.get_type::(); + pub fn build_list_type(&mut self, info: &T::TypeInfo) -> ListMeta<'r> { + let of_type = self.get_type::(info); ListMeta::new(of_type) } /// Create a nullable meta type - pub fn build_nullable_type(&mut self) -> NullableMeta<'r> { - let of_type = self.get_type::(); + pub fn build_nullable_type(&mut self, info: &T::TypeInfo) -> NullableMeta<'r> { + let of_type = self.get_type::(info); NullableMeta::new(of_type) } @@ -503,56 +519,69 @@ impl<'r> Registry<'r> { /// /// To prevent infinite recursion by enforcing ordering, this returns a /// function that needs to be called with the list of fields on the object. - pub fn build_object_type(&mut self, fields: &[Field<'r>]) -> ObjectMeta<'r> + pub fn build_object_type( + &mut self, + info: &T::TypeInfo, + fields: &[Field<'r>], + ) -> ObjectMeta<'r> where T: GraphQLType, { - let name = T::name().expect("Object types must be named. Implement name()"); + let name = T::name(info).expect("Object types must be named. Implement name()"); let mut v = fields.to_vec(); - v.push(self.field::("__typename")); - ObjectMeta::new(name, &v) + v.push(self.field::("__typename", &())); + ObjectMeta::new(Cow::Owned(name.to_string()), &v) } /// Create an enum meta type - pub fn build_enum_type(&mut self, values: &[EnumValue]) -> EnumMeta<'r> + pub fn build_enum_type(&mut self, info: &T::TypeInfo, values: &[EnumValue]) -> EnumMeta<'r> where T: FromInputValue + GraphQLType, { - let name = T::name().expect("Enum types must be named. Implement name()"); + let name = T::name(info).expect("Enum types must be named. Implement name()"); - EnumMeta::new::(name, values) + EnumMeta::new::(Cow::Owned(name.to_string()), values) } - /// Create an interface meta type builder - pub fn build_interface_type(&mut self, fields: &[Field<'r>]) -> InterfaceMeta<'r> + /// Create an interface meta type builder, + /// by providing a type info object. + pub fn build_interface_type( + &mut self, + info: &T::TypeInfo, + fields: &[Field<'r>], + ) -> InterfaceMeta<'r> where T: GraphQLType, { - let name = T::name().expect("Interface types must be named. Implement name()"); + let name = T::name(info).expect("Interface types must be named. Implement name()"); let mut v = fields.to_vec(); - v.push(self.field::("__typename")); - InterfaceMeta::new(name, &v) + v.push(self.field::("__typename", &())); + InterfaceMeta::new(Cow::Owned(name.to_string()), &v) } /// Create a union meta type builder - pub fn build_union_type(&mut self, types: &[Type<'r>]) -> UnionMeta<'r> + pub fn build_union_type(&mut self, info: &T::TypeInfo, types: &[Type<'r>]) -> UnionMeta<'r> where T: GraphQLType, { - let name = T::name().expect("Union types must be named. Implement name()"); + let name = T::name(info).expect("Union types must be named. Implement name()"); - UnionMeta::new(name, types) + UnionMeta::new(Cow::Owned(name.to_string()), types) } /// Create an input object meta type builder - pub fn build_input_object_type(&mut self, args: &[Argument<'r>]) -> InputObjectMeta<'r> + pub fn build_input_object_type( + &mut self, + info: &T::TypeInfo, + args: &[Argument<'r>], + ) -> InputObjectMeta<'r> where T: FromInputValue + GraphQLType, { - let name = T::name().expect("Input object types must be named. Implement name()"); + let name = T::name(info).expect("Input object types must be named. Implement name()"); - InputObjectMeta::new::(name, args) + InputObjectMeta::new::(Cow::Owned(name.to_string()), args) } } diff --git a/juniper/src/macros/args.rs b/juniper/src/macros/args.rs index 7c32119c6..62c0cc34e 100644 --- a/juniper/src/macros/args.rs +++ b/juniper/src/macros/args.rs @@ -42,57 +42,60 @@ macro_rules! __graphql__args { .expect("Argument missing - validation must have failed"); }; - ( @apply_args, $reg:expr, $base:expr, ( ) ) => { + ( @apply_args, $reg:expr, $base:expr, $info:expr, ( ) ) => { $base }; ( @apply_args, - $reg:expr, $base:expr, ( , $( $rest:tt )* ) + $reg:expr, $base:expr, $info:expr, ( , $( $rest:tt )* ) ) => { __graphql__args!( @apply_args, $reg, $base, + $info, ( $($rest)* )) }; ( @apply_args, - $reg:expr, $base:expr, ( &executor $( $rest:tt )* ) + $reg:expr, $base:expr, $info:expr, ( &executor $( $rest:tt )* ) ) => { __graphql__args!( @apply_args, $reg, $base, + $info, ( $($rest)* )) }; ( @apply_args, - $reg:expr, $base:expr, ( $name:ident = $default:tt : $t:ty ) + $reg:expr, $base:expr, $info:expr, ( $name:ident = $default:tt : $t:ty ) ) => { $base.argument($reg.arg_with_default::<$t>( &$crate::to_camel_case(stringify!($name)), - &__graphql__args!(@as_expr, $default))) + &__graphql__args!(@as_expr, $default), $info)) }; ( @apply_args, - $reg:expr, $base:expr, ( $name:ident = $default:tt : $t:ty , $( $rest:tt )* ) + $reg:expr, $base:expr, $info:expr, ( $name:ident = $default:tt : $t:ty , $( $rest:tt )* ) ) => { __graphql__args!( @apply_args, $reg, $base.argument($reg.arg_with_default::<$t>( &$crate::to_camel_case(stringify!($name)), - &__graphql__args!(@as_expr, $default))), + &__graphql__args!(@as_expr, $default), $info)), + $info, ( $($rest)* )) }; ( @apply_args, - $reg:expr, $base:expr, + $reg:expr, $base:expr, $info:expr, ( $name:ident = $default:tt : $t:ty as $desc:tt $( $rest:tt )* ) ) => { __graphql__args!( @@ -100,42 +103,45 @@ macro_rules! __graphql__args { $reg, $base.argument($reg.arg_with_default::<$t>( &$crate::to_camel_case(stringify!($name)), - &__graphql__args!(@as_expr, $default)) + &__graphql__args!(@as_expr, $default), $info) .description($desc)), + $info, ( $($rest)* )) }; ( @apply_args, - $reg:expr, $base:expr, ( $name:ident : $t:ty ) + $reg:expr, $base:expr, $info:expr, ( $name:ident : $t:ty ) ) => { $base.argument($reg.arg::<$t>( - &$crate::to_camel_case(stringify!($name)))) + &$crate::to_camel_case(stringify!($name)), $info)) }; ( @apply_args, - $reg:expr, $base:expr, ( $name:ident : $t:ty , $( $rest:tt )* ) + $reg:expr, $base:expr, $info:expr, ( $name:ident : $t:ty , $( $rest:tt )* ) ) => { __graphql__args!( @apply_args, $reg, $base.argument($reg.arg::<$t>( - &$crate::to_camel_case(stringify!($name)))), + &$crate::to_camel_case(stringify!($name)), $info)), + $info, ( $($rest)* )) }; ( @apply_args, - $reg:expr, $base:expr, ( $name:ident : $t:ty as $desc:tt $( $rest:tt )* ) + $reg:expr, $base:expr, $info:expr, ( $name:ident : $t:ty as $desc:tt $( $rest:tt )* ) ) => { __graphql__args!( @apply_args, $reg, $base.argument( $reg.arg::<$t>( - &$crate::to_camel_case(stringify!($name))) + &$crate::to_camel_case(stringify!($name)), $info) .description($desc)), + $info, ( $($rest)* )) }; } diff --git a/juniper/src/macros/enums.rs b/juniper/src/macros/enums.rs index 1c27b4695..191de8529 100644 --- a/juniper/src/macros/enums.rs +++ b/juniper/src/macros/enums.rs @@ -61,15 +61,16 @@ macro_rules! graphql_enum { ) => { impl $crate::GraphQLType for $name { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some(graphql_enum!(@as_expr, $outname)) } - fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { + fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { graphql_enum!( @maybe_apply, $descr, description, - registry.build_enum_type::<$name>(&[ + registry.build_enum_type::<$name>(info, &[ $( graphql_enum!( @maybe_apply, @@ -83,7 +84,7 @@ macro_rules! graphql_enum { .into_meta() } - fn resolve(&self, _: Option<&[$crate::Selection]>, _: &$crate::Executor) -> $crate::Value { + fn resolve(&self, _: &(), _: Option<&[$crate::Selection]>, _: &$crate::Executor) -> $crate::Value { match *self { $( graphql_enum!(@as_pattern, $eval) => diff --git a/juniper/src/macros/field.rs b/juniper/src/macros/field.rs index 79b8ebc95..707677bdb 100644 --- a/juniper/src/macros/field.rs +++ b/juniper/src/macros/field.rs @@ -79,7 +79,7 @@ macro_rules! __graphql__build_field_matches { return ($crate::IntoResolvable::into(result, $executorvar.context())).and_then( |res| match res { - Some((ctx, r)) => $executorvar.replaced_context(ctx).resolve_with_ctx(&r), + Some((ctx, r)) => $executorvar.replaced_context(ctx).resolve_with_ctx(&(), &r), None => Ok($crate::Value::null()), }) } diff --git a/juniper/src/macros/input_object.rs b/juniper/src/macros/input_object.rs index 265750ee1..4e89196d5 100644 --- a/juniper/src/macros/input_object.rs +++ b/juniper/src/macros/input_object.rs @@ -111,7 +111,7 @@ macro_rules! graphql_input_object { $($descr)*, $reg.arg_with_default::<$field_type>( &$crate::to_camel_case(stringify!($field_name)), - &$default)) + &$default, &())) }; // Generate single field meta for field without default value @@ -124,7 +124,7 @@ macro_rules! graphql_input_object { @apply_description, $($descr)*, $reg.arg::<$field_type>( - &$crate::to_camel_case(stringify!($field_name)))) + &$crate::to_camel_case(stringify!($field_name)), &())) }; // Generate the input field meta list, i.e. &[Argument] for @@ -239,16 +239,17 @@ macro_rules! graphql_input_object { impl $crate::GraphQLType for $name { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some($outname) } - fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { + 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() + registry.build_input_object_type::<$name>(&(), fields)).into_meta() } } }; diff --git a/juniper/src/macros/interface.rs b/juniper/src/macros/interface.rs index b52f5d5e7..61c9bda63 100644 --- a/juniper/src/macros/interface.rs +++ b/juniper/src/macros/interface.rs @@ -93,93 +93,97 @@ macro_rules! graphql_interface { // field deprecated (...) -> as { ... } ( @ gather_meta, - ($reg:expr, $acc:expr, $descr:expr), + ($reg:expr, $acc:expr, $info:expr, $descr:expr), field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))) + &$crate::to_camel_case(stringify!($name)), $info) .description($desc) .deprecated($reason), + $info, $args)); - graphql_interface!(@ gather_meta, ($reg, $acc, $descr), $( $rest )*); + graphql_interface!(@ gather_meta, ($reg, $acc, $info, $descr), $( $rest )*); }; // field deprecated (...) -> { ... } ( @ gather_meta, - ($reg:expr, $acc:expr, $descr:expr), + ($reg:expr, $acc:expr, $info:expr, $descr:expr), field deprecated $reason:tt $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))) + &$crate::to_camel_case(stringify!($name)), $info) .deprecated($reason), + $info, $args)); - graphql_interface!(@ gather_meta, ($reg, $acc, $descr), $( $rest )*); + graphql_interface!(@ gather_meta, ($reg, $acc, $info, $descr), $( $rest )*); }; // field (...) -> as { ... } ( @gather_meta, - ($reg:expr, $acc:expr, $descr:expr), + ($reg:expr, $acc:expr, $info:expr, $descr:expr), field $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))) + &$crate::to_camel_case(stringify!($name)), $info) .description($desc), + $info, $args)); - graphql_interface!(@ gather_meta, ($reg, $acc, $descr), $( $rest )*); + graphql_interface!(@ gather_meta, ($reg, $acc, $info, $descr), $( $rest )*); }; // field (...) -> { ... } ( @ gather_meta, - ($reg:expr, $acc:expr, $descr:expr), + ($reg:expr, $acc:expr, $info:expr, $descr:expr), field $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))), + &$crate::to_camel_case(stringify!($name)), $info), + $info, $args)); - graphql_interface!(@ gather_meta, ($reg, $acc, $descr), $( $rest )*); + graphql_interface!(@ gather_meta, ($reg, $acc, $info, $descr), $( $rest )*); }; // description: ( @ gather_meta, - ($reg:expr, $acc:expr, $descr:expr), + ($reg:expr, $acc:expr, $info:expr, $descr:expr), description : $value:tt $( $rest:tt )* ) => { $descr = Some(graphql_interface!(@as_expr, $value)); - graphql_interface!(@gather_meta, ($reg, $acc, $descr), $( $rest )*) + graphql_interface!(@gather_meta, ($reg, $acc, $info, $descr), $( $rest )*) }; // instance_resolvers: | | [...] ( @ gather_meta, - ($reg:expr, $acc:expr, $descr:expr), + ($reg:expr, $acc:expr, $info:expr, $descr:expr), instance_resolvers : | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )* ) => { $( - let _ = $reg.get_type::<$srctype>(); + let _ = $reg.get_type::<$srctype>(&()); )* - graphql_interface!(@gather_meta, ($reg, $acc, $descr), $( $rest )*) + graphql_interface!(@gather_meta, ($reg, $acc, $info, $descr), $( $rest )*) }; // instance_resolvers: | | [...] @@ -192,7 +196,7 @@ macro_rules! graphql_interface { $( if ($resolver as Option<$srctype>).is_some() { - return (<$srctype as $crate::GraphQLType>::name()).unwrap().to_owned(); + return (<$srctype as $crate::GraphQLType>::name(&())).unwrap().to_owned(); } )* @@ -208,8 +212,8 @@ macro_rules! graphql_interface { let $ctxtvar = &$execarg.context(); $( - if $typenamearg == (<$srctype as $crate::GraphQLType>::name()).unwrap() { - return $execarg.resolve(&$resolver); + if $typenamearg == (<$srctype as $crate::GraphQLType>::name(&())).unwrap() { + return $execarg.resolve(&(), &$resolver); } )* @@ -229,18 +233,19 @@ macro_rules! graphql_interface { ) => { graphql_interface!(@as_item, impl<$($lifetime)*> $crate::GraphQLType for $name { type Context = $ctxt; + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some($outname) } #[allow(unused_assignments)] #[allow(unused_mut)] - fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { + fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { let mut fields = Vec::new(); let mut description = None; - graphql_interface!(@ gather_meta, (registry, fields, description), $($items)*); - let mut mt = registry.build_interface_type::<$name>(&fields); + graphql_interface!(@ gather_meta, (registry, fields, info, description), $($items)*); + let mut mt = registry.build_interface_type::<$name>(&(), &fields); if let Some(description) = description { mt = mt.description(description); @@ -251,7 +256,7 @@ macro_rules! graphql_interface { #[allow(unused_variables)] #[allow(unused_mut)] - fn resolve_field(&$mainself, field: &str, args: &$crate::Arguments, mut executor: &$crate::Executor) -> $crate::ExecutionResult { + fn resolve_field(&$mainself, info: &(), field: &str, args: &$crate::Arguments, mut executor: &$crate::Executor) -> $crate::ExecutionResult { __graphql__build_field_matches!( ($outname, $mainself, field, args, executor), (), @@ -267,6 +272,7 @@ macro_rules! graphql_interface { fn resolve_into_type( &$mainself, + _: &(), type_name: &str, _: Option<&[$crate::Selection]>, executor: &$crate::Executor, diff --git a/juniper/src/macros/object.rs b/juniper/src/macros/object.rs index c3555cbd4..3cd0be332 100644 --- a/juniper/src/macros/object.rs +++ b/juniper/src/macros/object.rs @@ -239,116 +239,120 @@ macro_rules! graphql_object { // field deprecated (...) -> as { ... } ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))) + &$crate::to_camel_case(stringify!($name)), $info) .description($desc) .deprecated($reason), + $info, $args)); - graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*); + graphql_object!(@gather_object_meta, $reg, $acc, $info, $descr, $ifaces, $( $rest )*); }; // field deprecated (...) -> { ... } ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, field deprecated $reason:tt $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))) + &$crate::to_camel_case(stringify!($name)), $info) .deprecated($reason), + $info, $args)); - graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*); + graphql_object!(@gather_object_meta, $reg, $acc, $info, $descr, $ifaces, $( $rest )*); }; // field (...) -> as { ... } ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, field $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))) + &$crate::to_camel_case(stringify!($name)), $info) .description($desc), + $info, $args)); - graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*); + graphql_object!(@gather_object_meta, $reg, $acc, $info, $descr, $ifaces, $( $rest )*); }; // field (...) -> { ... } ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, field $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )* ) => { $acc.push(__graphql__args!( @apply_args, $reg, $reg.field_convert::<$t, _, Self::Context>( - &$crate::to_camel_case(stringify!($name))), + &$crate::to_camel_case(stringify!($name)), $info), + $info, $args)); - graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*); + graphql_object!(@gather_object_meta, $reg, $acc, $info, $descr, $ifaces, $( $rest )*); }; // description: ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, description : $value:tt $( $rest:tt )* ) => { $descr = Some(graphql_object!(@as_expr, $value)); - graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*) + graphql_object!(@gather_object_meta, $reg, $acc, $info, $descr, $ifaces, $( $rest )*) }; // interfaces: [...] ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, interfaces : $value:tt $( $rest:tt )* ) => { graphql_object!(@assign_interfaces, $reg, $ifaces, $value); - graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*) + graphql_object!(@gather_object_meta, $reg, $acc, $info, $descr, $ifaces, $( $rest )*) }; // eat commas ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, , $( $rest:tt )* + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, , $( $rest:tt )* ) => { - graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*) + graphql_object!(@gather_object_meta, $reg, $acc, $info, $descr, $ifaces, $( $rest )*) }; // base case ( @gather_object_meta, - $reg:expr, $acc:expr, $descr:expr, $ifaces:expr, + $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, ) => {}; ( @assign_interfaces, $reg:expr, $tgt:expr, [ $($t:ty,)* ] ) => { $tgt = Some(vec![ - $($reg.get_type::<$t>()),* + $($reg.get_type::<$t>(&())),* ]); }; ( @assign_interfaces, $reg:expr, $tgt:expr, [ $($t:ty),* ] ) => { $tgt = Some(vec![ - $($reg.get_type::<$t>()),* + $($reg.get_type::<$t>(&())),* ]); }; @@ -358,22 +362,23 @@ macro_rules! graphql_object { ) => { graphql_object!(@as_item, impl<$($lifetime)*> $crate::GraphQLType for $name { type Context = $ctxt; + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some($outname) } #[allow(unused_assignments)] #[allow(unused_mut)] - fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { + fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { let mut fields = Vec::new(); let mut description = None; let mut interfaces: Option> = None; graphql_object!( @gather_object_meta, - registry, fields, description, interfaces, $($items)* + registry, fields, info, description, interfaces, $($items)* ); - let mut mt = registry.build_object_type::<$name>(&fields); + let mut mt = registry.build_object_type::<$name>(info, &fields); if let Some(description) = description { mt = mt.description(description); @@ -394,6 +399,7 @@ macro_rules! graphql_object { #[allow(unused_mut)] fn resolve_field( &$mainself, + info: &(), field: &str, args: &$crate::Arguments, executor: &$crate::Executor diff --git a/juniper/src/macros/scalar.rs b/juniper/src/macros/scalar.rs index cec0cb7ee..0d9280738 100644 --- a/juniper/src/macros/scalar.rs +++ b/juniper/src/macros/scalar.rs @@ -65,20 +65,22 @@ macro_rules! graphql_scalar { ) => { impl $crate::GraphQLType for $name { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some(graphql_scalar!( @as_expr, $outname )) } - fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { + fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { graphql_scalar!( @maybe_apply, $descr, description, - registry.build_scalar_type::()) + registry.build_scalar_type::(info)) .into_meta() } fn resolve( &$resolve_selfvar, + _: &(), _: Option<&[$crate::Selection]>, _: &$crate::Executor) -> $crate::Value { $resolve_body diff --git a/juniper/src/macros/union.rs b/juniper/src/macros/union.rs index d78467faa..012296c5b 100644 --- a/juniper/src/macros/union.rs +++ b/juniper/src/macros/union.rs @@ -44,7 +44,7 @@ macro_rules! graphql_union { ) => { $acc = vec![ $( - $reg.get_type::<$srctype>() + $reg.get_type::<$srctype>(&()) ),* ]; @@ -62,7 +62,7 @@ macro_rules! graphql_union { $( if let Some(_) = $resolver as Option<$srctype> { - return (<$srctype as $crate::GraphQLType>::name()).unwrap().to_owned(); + return (<$srctype as $crate::GraphQLType>::name(&())).unwrap().to_owned(); } )* @@ -79,8 +79,8 @@ macro_rules! graphql_union { let $ctxtvar = &$execarg.context(); $( - if $typenamearg == (<$srctype as $crate::GraphQLType>::name()).unwrap().to_owned() { - return $execarg.resolve(&$resolver); + if $typenamearg == (<$srctype as $crate::GraphQLType>::name(&())).unwrap().to_owned() { + return $execarg.resolve(&(), &$resolver); } )* @@ -107,18 +107,19 @@ macro_rules! graphql_union { ) => { graphql_union!(@as_item, impl<$($lifetime)*> $crate::GraphQLType for $name { type Context = $ctxt; + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some($outname) } #[allow(unused_assignments)] #[allow(unused_mut)] - fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { + fn meta<'r>(_: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { let mut types; let mut description = None; graphql_union!(@ gather_meta, (registry, types, description), $($items)*); - let mut mt = registry.build_union_type::<$name>(&types); + let mut mt = registry.build_union_type::<$name>(&(), &types); if let Some(description) = description { mt = mt.description(description); @@ -136,6 +137,7 @@ macro_rules! graphql_union { fn resolve_into_type( &$mainself, + _: &(), type_name: &str, _: Option<&[$crate::Selection]>, executor: &$crate::Executor, diff --git a/juniper/src/parser/document.rs b/juniper/src/parser/document.rs index 76ebb2afd..74ae11460 100644 --- a/juniper/src/parser/document.rs +++ b/juniper/src/parser/document.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use ast::{Arguments, Definition, Directive, Document, Field, Fragment, FragmentSpread, InlineFragment, InputValue, Operation, OperationType, Selection, Type, VariableDefinition, VariableDefinitions}; @@ -362,7 +364,7 @@ pub fn parse_type<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Type<'a>> { let Spanning { end: end_pos, .. } = try!(parser.expect(&Token::BracketClose)); Spanning::start_end(&start_pos, &end_pos, Type::List(Box::new(inner_type.item))) } else { - try!(parser.expect_name()).map(Type::Named) + try!(parser.expect_name()).map(|s| Type::Named(Cow::Borrowed(s))) }; Ok(match *parser.peek() { diff --git a/juniper/src/schema/meta.rs b/juniper/src/schema/meta.rs index ecd19121f..73626af3c 100644 --- a/juniper/src/schema/meta.rs +++ b/juniper/src/schema/meta.rs @@ -1,6 +1,6 @@ //! Types used to describe a GraphQL schema - +use std::borrow::Cow; use std::fmt; use ast::{FromInputValue, InputValue, Type}; @@ -9,7 +9,7 @@ use types::base::TypeKind; /// Scalar type metadata pub struct ScalarMeta<'a> { #[doc(hidden)] - pub name: &'a str, + pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option, #[doc(hidden)] @@ -34,7 +34,7 @@ pub struct NullableMeta<'a> { #[derive(Debug)] pub struct ObjectMeta<'a> { #[doc(hidden)] - pub name: &'a str, + pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option, #[doc(hidden)] @@ -46,7 +46,7 @@ pub struct ObjectMeta<'a> { /// Enum type metadata pub struct EnumMeta<'a> { #[doc(hidden)] - pub name: &'a str, + pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option, #[doc(hidden)] @@ -59,7 +59,7 @@ pub struct EnumMeta<'a> { #[derive(Debug)] pub struct InterfaceMeta<'a> { #[doc(hidden)] - pub name: &'a str, + pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option, #[doc(hidden)] @@ -70,7 +70,7 @@ pub struct InterfaceMeta<'a> { #[derive(Debug)] pub struct UnionMeta<'a> { #[doc(hidden)] - pub name: &'a str, + pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option, #[doc(hidden)] @@ -80,7 +80,7 @@ pub struct UnionMeta<'a> { /// Input object metadata pub struct InputObjectMeta<'a> { #[doc(hidden)] - pub name: &'a str, + pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option, #[doc(hidden)] @@ -174,12 +174,12 @@ impl<'a> MetaType<'a> { /// Lists, non-null wrappers, and placeholders don't have names. pub fn name(&self) -> Option<&str> { match *self { - MetaType::Scalar(ScalarMeta { name, .. }) | - MetaType::Object(ObjectMeta { name, .. }) | - MetaType::Enum(EnumMeta { name, .. }) | - MetaType::Interface(InterfaceMeta { name, .. }) | - MetaType::Union(UnionMeta { name, .. }) | - MetaType::InputObject(InputObjectMeta { name, .. }) => Some(name), + MetaType::Scalar(ScalarMeta { ref name, .. }) | + MetaType::Object(ObjectMeta { ref name, .. }) | + MetaType::Enum(EnumMeta { ref name, .. }) | + MetaType::Interface(InterfaceMeta { ref name, .. }) | + MetaType::Union(UnionMeta { ref name, .. }) | + MetaType::InputObject(InputObjectMeta { ref name, .. }) => Some(name), _ => None, } } @@ -257,17 +257,19 @@ impl<'a> MetaType<'a> { /// Construct a `Type` literal instance based on the metadata pub fn as_type(&self) -> Type<'a> { match *self { - MetaType::Scalar(ScalarMeta { name, .. }) | - MetaType::Object(ObjectMeta { name, .. }) | - MetaType::Enum(EnumMeta { name, .. }) | - MetaType::Interface(InterfaceMeta { name, .. }) | - MetaType::Union(UnionMeta { name, .. }) | - MetaType::InputObject(InputObjectMeta { name, .. }) => Type::NonNullNamed(name), + MetaType::Scalar(ScalarMeta { ref name, .. }) | + MetaType::Object(ObjectMeta { ref name, .. }) | + MetaType::Enum(EnumMeta { ref name, .. }) | + MetaType::Interface(InterfaceMeta { ref name, .. }) | + MetaType::Union(UnionMeta { ref name, .. }) | + MetaType::InputObject(InputObjectMeta { ref name, .. }) => { + Type::NonNullNamed(name.clone()) + } MetaType::List(ListMeta { ref of_type }) => { Type::NonNullList(Box::new(of_type.clone())) } MetaType::Nullable(NullableMeta { ref of_type }) => match *of_type { - Type::NonNullNamed(inner) => Type::Named(inner), + Type::NonNullNamed(ref inner) => Type::Named(inner.clone()), Type::NonNullList(ref inner) => Type::List(inner.clone()), ref t => t.clone(), }, @@ -339,7 +341,7 @@ impl<'a> MetaType<'a> { impl<'a> ScalarMeta<'a> { /// Build a new scalar type metadata with the specified name - pub fn new(name: &'a str) -> ScalarMeta<'a> { + pub fn new(name: Cow<'a, str>) -> ScalarMeta<'a> { ScalarMeta { name: name, description: None, @@ -387,7 +389,7 @@ impl<'a> NullableMeta<'a> { impl<'a> ObjectMeta<'a> { /// Build a new object type with the specified name and fields - pub fn new(name: &'a str, fields: &[Field<'a>]) -> ObjectMeta<'a> { + pub fn new(name: Cow<'a, str>, fields: &[Field<'a>]) -> ObjectMeta<'a> { ObjectMeta { name: name, description: None, @@ -424,7 +426,7 @@ impl<'a> ObjectMeta<'a> { impl<'a> EnumMeta<'a> { /// Build a new enum type with the specified name and possible values - pub fn new(name: &'a str, values: &[EnumValue]) -> EnumMeta<'a> { + pub fn new(name: Cow<'a, str>, values: &[EnumValue]) -> EnumMeta<'a> { EnumMeta { name: name, description: None, @@ -449,7 +451,7 @@ impl<'a> EnumMeta<'a> { impl<'a> InterfaceMeta<'a> { /// Build a new interface type with the specified name and fields - pub fn new(name: &'a str, fields: &[Field<'a>]) -> InterfaceMeta<'a> { + pub fn new(name: Cow<'a, str>, fields: &[Field<'a>]) -> InterfaceMeta<'a> { InterfaceMeta { name: name, description: None, @@ -473,7 +475,7 @@ impl<'a> InterfaceMeta<'a> { impl<'a> UnionMeta<'a> { /// Build a new union type with the specified name and possible types - pub fn new(name: &'a str, of_types: &[Type]) -> UnionMeta<'a> { + pub fn new(name: Cow<'a, str>, of_types: &[Type]) -> UnionMeta<'a> { UnionMeta { name: name, description: None, @@ -501,7 +503,7 @@ impl<'a> UnionMeta<'a> { impl<'a> InputObjectMeta<'a> { /// Build a new input type with the specified name and input fields pub fn new( - name: &'a str, + name: Cow<'a, str>, input_fields: &[Argument<'a>], ) -> InputObjectMeta<'a> { InputObjectMeta { diff --git a/juniper/src/schema/model.rs b/juniper/src/schema/model.rs index 086b51d90..5bb3bb4fc 100644 --- a/juniper/src/schema/model.rs +++ b/juniper/src/schema/model.rs @@ -10,12 +10,16 @@ use schema::meta::{Argument, InterfaceMeta, MetaType, ObjectMeta, PlaceholderMet /// /// This brings the mutation and query types together, and provides the /// predefined metadata fields. -pub struct RootNode<'a, QueryT, MutationT> { +pub struct RootNode<'a, QueryT: GraphQLType, MutationT: GraphQLType> { #[doc(hidden)] pub query_type: QueryT, #[doc(hidden)] + pub query_info: QueryT::TypeInfo, + #[doc(hidden)] pub mutation_type: MutationT, #[doc(hidden)] + pub mutation_info: MutationT::TypeInfo, + #[doc(hidden)] pub schema: SchemaType<'a>, } @@ -54,24 +58,47 @@ pub enum DirectiveLocation { impl<'a, QueryT, MutationT> RootNode<'a, QueryT, MutationT> where - QueryT: GraphQLType, - MutationT: GraphQLType, + QueryT: GraphQLType, + MutationT: GraphQLType, { /// Construct a new root node from query and mutation nodes /// /// If the schema should not support mutations, use the /// `new` constructor instead. pub fn new(query_obj: QueryT, mutation_obj: MutationT) -> RootNode<'a, QueryT, MutationT> { + RootNode::new_with_info(query_obj, mutation_obj, (), ()) + } +} + +impl<'a, QueryT, MutationT> RootNode<'a, QueryT, MutationT> +where + QueryT: GraphQLType, + MutationT: GraphQLType, +{ + /// Construct a new root node from query and mutation nodes, + /// while also providing type info objects for the query and + /// mutation types. + pub fn new_with_info( + query_obj: QueryT, + mutation_obj: MutationT, + query_info: QueryT::TypeInfo, + mutation_info: MutationT::TypeInfo, + ) -> RootNode<'a, QueryT, MutationT> { RootNode { query_type: query_obj, mutation_type: mutation_obj, - schema: SchemaType::new::(), + schema: SchemaType::new::(&query_info, &mutation_info), + query_info: query_info, + mutation_info: mutation_info, } } } impl<'a> SchemaType<'a> { - pub fn new() -> SchemaType<'a> + pub fn new( + query_info: &QueryT::TypeInfo, + mutation_info: &MutationT::TypeInfo, + ) -> SchemaType<'a> where QueryT: GraphQLType, MutationT: GraphQLType, @@ -81,10 +108,16 @@ impl<'a> SchemaType<'a> { let mutation_type_name: String; let mut registry = Registry::new(HashMap::new()); - query_type_name = registry.get_type::().innermost_name().to_owned(); - mutation_type_name = registry.get_type::().innermost_name().to_owned(); - - registry.get_type::(); + query_type_name = registry + .get_type::(query_info) + .innermost_name() + .to_owned(); + mutation_type_name = registry + .get_type::(mutation_info) + .innermost_name() + .to_owned(); + + registry.get_type::(&()); directives.insert("skip".to_owned(), DirectiveType::new_skip(&mut registry)); directives.insert( "include".to_owned(), @@ -92,10 +125,10 @@ impl<'a> SchemaType<'a> { ); let mut meta_fields = vec![ - registry.field::("__schema"), + registry.field::("__schema", &()), registry - .field::("__type") - .argument(registry.arg::("name")), + .field::("__type", &()) + .argument(registry.arg::("name", &())), ]; if let Some(root_type) = registry.types.get_mut(&query_type_name) { @@ -180,13 +213,13 @@ impl<'a> SchemaType<'a> { pub fn make_type(&self, t: &Type) -> TypeType { match *t { - Type::NonNullNamed(n) => TypeType::NonNull(Box::new( + Type::NonNullNamed(ref n) => TypeType::NonNull(Box::new( self.type_by_name(n).expect("Type not found in schema"), )), Type::NonNullList(ref inner) => { TypeType::NonNull(Box::new(TypeType::List(Box::new(self.make_type(inner))))) } - Type::Named(n) => self.type_by_name(n).expect("Type not found in schema"), + Type::Named(ref n) => self.type_by_name(n).expect("Type not found in schema"), Type::List(ref inner) => TypeType::List(Box::new(self.make_type(inner))), } } @@ -222,7 +255,7 @@ impl<'a> SchemaType<'a> { .iter() .flat_map(|t| self.concrete_type_by_name(t)) .collect(), - MetaType::Interface(InterfaceMeta { name, .. }) => self.concrete_type_list() + MetaType::Interface(InterfaceMeta { ref name, .. }) => self.concrete_type_list() .into_iter() .filter(|t| match **t { MetaType::Object(ObjectMeta { @@ -250,9 +283,9 @@ impl<'a> SchemaType<'a> { } match (super_type, sub_type) { - (&NonNullNamed(super_name), &NonNullNamed(sub_name)) | - (&Named(super_name), &Named(sub_name)) | - (&Named(super_name), &NonNullNamed(sub_name)) => { + (&NonNullNamed(ref super_name), &NonNullNamed(ref sub_name)) | + (&Named(ref super_name), &Named(ref sub_name)) | + (&Named(ref super_name), &NonNullNamed(ref sub_name)) => { self.is_named_subtype(sub_name, super_name) } (&NonNullList(ref super_inner), &NonNullList(ref sub_inner)) | @@ -309,7 +342,7 @@ impl<'a> DirectiveType<'a> { DirectiveLocation::FragmentSpread, DirectiveLocation::InlineFragment, ], - &[registry.arg::("if")], + &[registry.arg::("if", &())], ) } @@ -321,7 +354,7 @@ impl<'a> DirectiveType<'a> { DirectiveLocation::FragmentSpread, DirectiveLocation::InlineFragment, ], - &[registry.arg::("if")], + &[registry.arg::("if", &())], ) } diff --git a/juniper/src/schema/schema.rs b/juniper/src/schema/schema.rs index 97a3ec3e0..2c29dccac 100644 --- a/juniper/src/schema/schema.rs +++ b/juniper/src/schema/schema.rs @@ -11,17 +11,19 @@ where MutationT: GraphQLType, { type Context = CtxT; + type TypeInfo = QueryT::TypeInfo; - fn name() -> Option<&'static str> { - QueryT::name() + fn name(info: &QueryT::TypeInfo) -> Option<&str> { + QueryT::name(info) } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - QueryT::meta(registry) + fn meta<'r>(info: &QueryT::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r> { + QueryT::meta(info, registry) } fn resolve_field( &self, + info: &QueryT::TypeInfo, field: &str, args: &Arguments, executor: &Executor, @@ -29,14 +31,14 @@ where match field { "__schema" => executor .replaced_context(&self.schema) - .resolve(&self.schema), + .resolve(&(), &self.schema), "__type" => { let type_name: String = args.get("name").unwrap(); executor .replaced_context(&self.schema) - .resolve(&self.schema.type_by_name(&type_name)) + .resolve(&(), &self.schema.type_by_name(&type_name)) } - _ => self.query_type.resolve_field(field, args, executor), + _ => self.query_type.resolve_field(info, field, args, executor), } } } @@ -140,12 +142,12 @@ graphql_object!(<'a> TypeType<'a>: SchemaType<'a> as "__Type" |&self| { .filter_map(|tn| schema.type_by_name(tn)) .collect()) } - TypeType::Concrete(&MetaType::Interface(InterfaceMeta { name: iface_name, .. })) => { + TypeType::Concrete(&MetaType::Interface(InterfaceMeta { name: ref iface_name, .. })) => { Some(schema.concrete_type_list() .iter() .filter_map(|&ct| if let MetaType::Object(ObjectMeta { ref name, ref interface_names, .. }) = *ct { - if interface_names.contains(&iface_name.to_owned()) { + if interface_names.contains(&iface_name.to_string()) { schema.type_by_name(name) } else { None } } else { None } diff --git a/juniper/src/tests/mod.rs b/juniper/src/tests/mod.rs index 79b5e798a..97d01a376 100644 --- a/juniper/src/tests/mod.rs +++ b/juniper/src/tests/mod.rs @@ -6,3 +6,5 @@ mod schema; mod query_tests; #[cfg(test)] mod introspection_tests; +#[cfg(test)] +mod type_info_tests; diff --git a/juniper/src/tests/type_info_tests.rs b/juniper/src/tests/type_info_tests.rs new file mode 100644 index 000000000..1ddf69180 --- /dev/null +++ b/juniper/src/tests/type_info_tests.rs @@ -0,0 +1,83 @@ +use std::collections::HashMap; + +use executor::{ExecutionResult, Executor, Registry, Variables}; +use value::Value; +use schema::meta::MetaType; +use schema::model::RootNode; +use types::base::{Arguments, GraphQLType}; +use types::scalars::EmptyMutation; + +pub struct NodeTypeInfo { + name: String, + attribute_names: Vec, +} + +pub struct Node { + attributes: HashMap, +} + +impl GraphQLType for Node { + type Context = (); + type TypeInfo = NodeTypeInfo; + + fn name(info: &Self::TypeInfo) -> Option<&str> { + Some(&info.name) + } + + fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r> { + let fields = info.attribute_names + .iter() + .map(|name| registry.field::(name, &())) + .collect::>(); + + registry + .build_object_type::(info, &fields) + .into_meta() + } + + fn resolve_field( + &self, + _: &Self::TypeInfo, + field_name: &str, + _: &Arguments, + executor: &Executor, + ) -> ExecutionResult { + executor.resolve(&(), &self.attributes.get(field_name).unwrap()) + } +} + +#[test] +fn test_node() { + let doc = r#" + { + foo, + bar, + baz + }"#; + let node_info = NodeTypeInfo { + name: "MyNode".to_string(), + attribute_names: vec!["foo".to_string(), "bar".to_string(), "baz".to_string()], + }; + let mut node = Node { + attributes: HashMap::new(), + }; + node.attributes.insert("foo".to_string(), "1".to_string()); + node.attributes.insert("bar".to_string(), "2".to_string()); + node.attributes.insert("baz".to_string(), "3".to_string()); + let schema = RootNode::new_with_info(node, EmptyMutation::new(), node_info, ()); + + assert_eq!( + ::execute(doc, None, &schema, &Variables::new(), &()), + Ok(( + Value::object( + vec![ + ("foo", Value::string("1")), + ("bar", Value::string("2")), + ("baz", Value::string("3")), + ].into_iter() + .collect() + ), + vec![] + )) + ); +} diff --git a/juniper/src/types/base.rs b/juniper/src/types/base.rs index f9ba29722..415dbfbe6 100644 --- a/juniper/src/types/base.rs +++ b/juniper/src/types/base.rs @@ -152,27 +152,29 @@ impl Context for Database {} impl GraphQLType for User { type Context = Database; + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("User") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(_: &(), registry: &mut Registry<'r>) -> MetaType<'r> { // First, we need to define all fields and their types on this type. // // If we need arguments, want to implement interfaces, or want to add // documentation strings, we can do it here. let fields = &[ - registry.field::<&String>("id"), - registry.field::<&String>("name"), - registry.field::>("friends"), + registry.field::<&String>("id", &()), + registry.field::<&String>("name", &()), + registry.field::>("friends", &()), ]; - registry.build_object_type::(fields).into_meta() + registry.build_object_type::(&(), fields).into_meta() } fn resolve_field( &self, + info: &(), field_name: &str, args: &Arguments, executor: &Executor @@ -188,14 +190,14 @@ impl GraphQLType for User { // Because scalars are defined with another `Context` associated // type, you must use resolve_with_ctx here to make the executor // perform automatic type conversion of its argument. - "id" => executor.resolve_with_ctx(&self.id), - "name" => executor.resolve_with_ctx(&self.name), + "id" => executor.resolve_with_ctx(info, &self.id), + "name" => executor.resolve_with_ctx(info, &self.name), // You pass a vector of User objects to `executor.resolve`, and it // will determine which fields of the sub-objects to actually // resolve based on the query. The executor instance keeps track // of its current position in the query. - "friends" => executor.resolve( + "friends" => executor.resolve(info, &self.friend_ids.iter() .filter_map(|id| database.users.get(id)) .collect::>() @@ -222,15 +224,22 @@ pub trait GraphQLType: Sized { /// request session information. type Context; + /// Type that may carry additional schema information + /// + /// This can be used to implement a schema that is partly dynamic, + /// meaning that it can use information that is not known at compile time, + /// for instance by reading it from a configuration file at start-up. + type TypeInfo; + /// The name of the GraphQL type to expose. /// /// This function will be called multiple times during schema construction. /// It must _not_ perform any calculation and _always_ return the same /// value. - fn name() -> Option<&'static str>; + fn name(info: &Self::TypeInfo) -> Option<&str>; /// The meta type representing this GraphQL type. - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r>; + fn meta<'r>(info: &Self::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r>; /// Resolve the value of a single field on this type. /// @@ -243,6 +252,7 @@ pub trait GraphQLType: Sized { #[allow(unused_variables)] fn resolve_field( &self, + info: &Self::TypeInfo, field_name: &str, arguments: &Arguments, executor: &Executor, @@ -259,12 +269,13 @@ pub trait GraphQLType: Sized { #[allow(unused_variables)] fn resolve_into_type( &self, + info: &Self::TypeInfo, type_name: &str, selection_set: Option<&[Selection]>, executor: &Executor, ) -> ExecutionResult { - if Self::name().unwrap() == type_name { - Ok(self.resolve(selection_set, executor)) + if Self::name(info).unwrap() == type_name { + Ok(self.resolve(info, selection_set, executor)) } else { panic!("resolve_into_type must be implemented by unions and interfaces"); } @@ -290,12 +301,13 @@ pub trait GraphQLType: Sized { /// non-object types, this method panics. fn resolve( &self, + info: &Self::TypeInfo, selection_set: Option<&[Selection]>, executor: &Executor, ) -> Value { if let Some(selection_set) = selection_set { let mut result = HashMap::new(); - resolve_selection_set_into(self, selection_set, executor, &mut result); + resolve_selection_set_into(self, info, selection_set, executor, &mut result); Value::object(result) } else { panic!("resolve() must be implemented by non-object output types"); @@ -305,6 +317,7 @@ pub trait GraphQLType: Sized { fn resolve_selection_set_into( instance: &T, + info: &T::TypeInfo, selection_set: &[Selection], executor: &Executor, result: &mut HashMap, @@ -313,7 +326,11 @@ fn resolve_selection_set_into( { let meta_type = executor .schema() - .concrete_type_by_name(T::name().expect("Resolving named type's selection set")) + .concrete_type_by_name( + T::name(info) + .expect("Resolving named type's selection set") + .as_ref(), + ) .expect("Type not found in schema"); for selection in selection_set { @@ -354,6 +371,7 @@ fn resolve_selection_set_into( ); let field_result = instance.resolve_field( + info, f.name.item, &Arguments::new( f.arguments.as_ref().map(|m| { @@ -388,7 +406,13 @@ fn resolve_selection_set_into( .fragment_by_name(spread.name.item) .expect("Fragment could not be found"); - resolve_selection_set_into(instance, &fragment.selection_set[..], executor, result); + resolve_selection_set_into( + instance, + info, + &fragment.selection_set[..], + executor, + result, + ); } Selection::InlineFragment(Spanning { item: ref fragment, @@ -404,6 +428,7 @@ fn resolve_selection_set_into( if let Some(ref type_condition) = fragment.type_condition { let sub_result = instance.resolve_into_type( + info, type_condition.item, Some(&fragment.selection_set[..]), &sub_exec, @@ -419,6 +444,7 @@ fn resolve_selection_set_into( } else { resolve_selection_set_into( instance, + info, &fragment.selection_set[..], &sub_exec, result, diff --git a/juniper/src/types/containers.rs b/juniper/src/types/containers.rs index becbe0a53..b2e202467 100644 --- a/juniper/src/types/containers.rs +++ b/juniper/src/types/containers.rs @@ -10,18 +10,24 @@ where T: GraphQLType, { type Context = CtxT; + type TypeInfo = T::TypeInfo; - fn name() -> Option<&'static str> { + fn name(_: &T::TypeInfo) -> Option<&str> { None } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - registry.build_nullable_type::().into_meta() + fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r> { + registry.build_nullable_type::(info).into_meta() } - fn resolve(&self, _: Option<&[Selection]>, executor: &Executor) -> Value { + fn resolve( + &self, + info: &T::TypeInfo, + _: Option<&[Selection]>, + executor: &Executor, + ) -> Value { match *self { - Some(ref obj) => executor.resolve_into_value(obj), + Some(ref obj) => executor.resolve_into_value(info, obj), None => Value::null(), } } @@ -59,19 +65,25 @@ where T: GraphQLType, { type Context = CtxT; + type TypeInfo = T::TypeInfo; - fn name() -> Option<&'static str> { + fn name(_: &T::TypeInfo) -> Option<&str> { None } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - registry.build_list_type::().into_meta() + fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r> { + registry.build_list_type::(info).into_meta() } - fn resolve(&self, _: Option<&[Selection]>, executor: &Executor) -> Value { + fn resolve( + &self, + info: &T::TypeInfo, + _: Option<&[Selection]>, + executor: &Executor, + ) -> Value { Value::list( self.iter() - .map(|e| executor.resolve_into_value(e)) + .map(|e| executor.resolve_into_value(info, e)) .collect(), ) } @@ -115,19 +127,25 @@ where T: GraphQLType, { type Context = CtxT; + type TypeInfo = T::TypeInfo; - fn name() -> Option<&'static str> { + fn name(_: &T::TypeInfo) -> Option<&str> { None } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - registry.build_list_type::().into_meta() + fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r> { + registry.build_list_type::(info).into_meta() } - fn resolve(&self, _: Option<&[Selection]>, executor: &Executor) -> Value { + fn resolve( + &self, + info: &T::TypeInfo, + _: Option<&[Selection]>, + executor: &Executor, + ) -> Value { Value::list( self.iter() - .map(|e| executor.resolve_into_value(e)) + .map(|e| executor.resolve_into_value(info, e)) .collect(), ) } diff --git a/juniper/src/types/pointers.rs b/juniper/src/types/pointers.rs index 48f26bce3..043821aca 100644 --- a/juniper/src/types/pointers.rs +++ b/juniper/src/types/pointers.rs @@ -10,35 +10,43 @@ where T: GraphQLType, { type Context = CtxT; + type TypeInfo = T::TypeInfo; - fn name() -> Option<&'static str> { - T::name() + fn name(info: &T::TypeInfo) -> Option<&str> { + T::name(info) } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - T::meta(registry) + fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r> { + T::meta(info, registry) } fn resolve_into_type( &self, + info: &T::TypeInfo, name: &str, selection_set: Option<&[Selection]>, executor: &Executor, ) -> ExecutionResult { - (**self).resolve_into_type(name, selection_set, executor) + (**self).resolve_into_type(info, name, selection_set, executor) } fn resolve_field( &self, + info: &T::TypeInfo, field: &str, args: &Arguments, executor: &Executor, ) -> ExecutionResult { - (**self).resolve_field(field, args, executor) + (**self).resolve_field(info, field, args, executor) } - fn resolve(&self, selection_set: Option<&[Selection]>, executor: &Executor) -> Value { - (**self).resolve(selection_set, executor) + fn resolve( + &self, + info: &T::TypeInfo, + selection_set: Option<&[Selection]>, + executor: &Executor, + ) -> Value { + (**self).resolve(info, selection_set, executor) } } @@ -68,35 +76,43 @@ where T: GraphQLType, { type Context = CtxT; + type TypeInfo = T::TypeInfo; - fn name() -> Option<&'static str> { - T::name() + fn name(info: &T::TypeInfo) -> Option<&str> { + T::name(info) } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - T::meta(registry) + fn meta<'r>(info: &T::TypeInfo, registry: &mut Registry<'r>) -> MetaType<'r> { + T::meta(info, registry) } fn resolve_into_type( &self, + info: &T::TypeInfo, name: &str, selection_set: Option<&[Selection]>, executor: &Executor, ) -> ExecutionResult { - (**self).resolve_into_type(name, selection_set, executor) + (**self).resolve_into_type(info, name, selection_set, executor) } fn resolve_field( &self, + info: &T::TypeInfo, field: &str, args: &Arguments, executor: &Executor, ) -> ExecutionResult { - (**self).resolve_field(field, args, executor) + (**self).resolve_field(info, field, args, executor) } - fn resolve(&self, selection_set: Option<&[Selection]>, executor: &Executor) -> Value { - (**self).resolve(selection_set, executor) + fn resolve( + &self, + info: &T::TypeInfo, + selection_set: Option<&[Selection]>, + executor: &Executor, + ) -> Value { + (**self).resolve(info, selection_set, executor) } } diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs index b101b9f6c..9376d7103 100644 --- a/juniper/src/types/scalars.rs +++ b/juniper/src/types/scalars.rs @@ -61,16 +61,17 @@ graphql_scalar!(String as "String" { impl<'a> GraphQLType for &'a str { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some("String") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - registry.build_scalar_type::().into_meta() + fn meta<'r>(_: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + registry.build_scalar_type::(&()).into_meta() } - fn resolve(&self, _: Option<&[Selection]>, _: &Executor) -> Value { + fn resolve(&self, _: &(), _: Option<&[Selection]>, _: &Executor) -> Value { Value::string(self) } } @@ -128,13 +129,14 @@ graphql_scalar!(f64 as "Float" { impl GraphQLType for () { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some("__Unit") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - registry.build_scalar_type::().into_meta() + fn meta<'r>(_: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + registry.build_scalar_type::(&()).into_meta() } } @@ -164,13 +166,14 @@ impl EmptyMutation { impl GraphQLType for EmptyMutation { type Context = T; + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some("_EmptyMutation") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - registry.build_object_type::(&[]).into_meta() + fn meta<'r>(_: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + registry.build_object_type::(&(), &[]).into_meta() } } diff --git a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs index 8d1844711..b3696fa14 100644 --- a/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs +++ b/juniper/src/validation/rules/overlapping_fields_can_be_merged.rs @@ -510,8 +510,8 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> { (&Type::NonNullList(ref inner1), &Type::NonNullList(ref inner2)) => { self.is_type_conflict(ctx, inner1, inner2) } - (&Type::NonNullNamed(n1), &Type::NonNullNamed(n2)) | - (&Type::Named(n1), &Type::Named(n2)) => { + (&Type::NonNullNamed(ref n1), &Type::NonNullNamed(ref n2)) | + (&Type::Named(ref n1), &Type::Named(ref n2)) => { let ct1 = ctx.schema.concrete_type_by_name(n1); let ct2 = ctx.schema.concrete_type_by_name(n2); @@ -1357,102 +1357,107 @@ mod tests { impl GraphQLType for SomeBox { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("SomeBox") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ - registry.field::>("deepBox"), - registry.field::>("unrelatedField"), + registry.field::>("deepBox", i), + registry.field::>("unrelatedField", i), ]; - registry.build_interface_type::(fields).into_meta() + registry.build_interface_type::(i, fields).into_meta() } } impl GraphQLType for StringBox { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("StringBox") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ - registry.field::>("scalar"), - registry.field::>("deepBox"), - registry.field::>("unrelatedField"), - registry.field::>>>("listStringBox"), - registry.field::>("stringBox"), - registry.field::>("intBox"), + registry.field::>("scalar", i), + registry.field::>("deepBox", i), + registry.field::>("unrelatedField", i), + registry.field::>>>("listStringBox", i), + registry.field::>("stringBox", i), + registry.field::>("intBox", i), ]; registry - .build_object_type::(fields) - .interfaces(&[registry.get_type::()]) + .build_object_type::(i, fields) + .interfaces(&[registry.get_type::(i)]) .into_meta() } } impl GraphQLType for IntBox { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("IntBox") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ - registry.field::>("scalar"), - registry.field::>("deepBox"), - registry.field::>("unrelatedField"), - registry.field::>>>("listStringBox"), - registry.field::>("stringBox"), - registry.field::>("intBox"), + registry.field::>("scalar", i), + registry.field::>("deepBox", i), + registry.field::>("unrelatedField", i), + registry.field::>>>("listStringBox", i), + registry.field::>("stringBox", i), + registry.field::>("intBox", i), ]; registry - .build_object_type::(fields) - .interfaces(&[registry.get_type::()]) + .build_object_type::(i, fields) + .interfaces(&[registry.get_type::(i)]) .into_meta() } } impl GraphQLType for NonNullStringBox1 { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("NonNullStringBox1") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let fields = &[registry.field::("scalar")]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let fields = &[registry.field::("scalar", i)]; - registry.build_interface_type::(fields).into_meta() + registry.build_interface_type::(i, fields).into_meta() } } impl GraphQLType for NonNullStringBox1Impl { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("NonNullStringBox1Impl") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ - registry.field::("scalar"), - registry.field::>("deepBox"), - registry.field::>("unrelatedField"), + registry.field::("scalar", i), + registry.field::>("deepBox", i), + registry.field::>("unrelatedField", i), ]; registry - .build_object_type::(fields) + .build_object_type::(i, fields) .interfaces(&[ - registry.get_type::(), - registry.get_type::(), + registry.get_type::(i), + registry.get_type::(i), ]) .into_meta() } @@ -1460,37 +1465,39 @@ mod tests { impl GraphQLType for NonNullStringBox2 { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("NonNullStringBox2") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let fields = &[registry.field::("scalar")]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let fields = &[registry.field::("scalar", i)]; - registry.build_interface_type::(fields).into_meta() + registry.build_interface_type::(i, fields).into_meta() } } impl GraphQLType for NonNullStringBox2Impl { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("NonNullStringBox2Impl") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ - registry.field::("scalar"), - registry.field::>("deepBox"), - registry.field::>("unrelatedField"), + registry.field::("scalar", i), + registry.field::>("deepBox", i), + registry.field::>("unrelatedField", i), ]; registry - .build_object_type::(fields) + .build_object_type::(i, fields) .interfaces(&[ - registry.get_type::(), - registry.get_type::(), + registry.get_type::(i), + registry.get_type::(i), ]) .into_meta() } @@ -1498,67 +1505,71 @@ mod tests { impl GraphQLType for Node { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Node") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ - registry.field::>("id"), - registry.field::>("name"), + registry.field::>("id", i), + registry.field::>("name", i), ]; - registry.build_object_type::(fields).into_meta() + registry.build_object_type::(i, fields).into_meta() } } impl GraphQLType for Edge { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Edge") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let fields = &[registry.field::>("node")]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let fields = &[registry.field::>("node", i)]; - registry.build_object_type::(fields).into_meta() + registry.build_object_type::(i, fields).into_meta() } } impl GraphQLType for Connection { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Connection") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let fields = &[registry.field::>>>("edges")]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let fields = &[registry.field::>>>("edges", i)]; - registry.build_object_type::(fields).into_meta() + registry.build_object_type::(i, fields).into_meta() } } impl GraphQLType for QueryRoot { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("QueryRoot") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - registry.get_type::(); - registry.get_type::(); - registry.get_type::(); - registry.get_type::(); + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + registry.get_type::(i); + registry.get_type::(i); + registry.get_type::(i); + registry.get_type::(i); let fields = &[ - registry.field::>("someBox"), - registry.field::>("connection"), + registry.field::>("someBox", i), + registry.field::>("connection", i), ]; - registry.build_object_type::(fields).into_meta() + registry.build_object_type::(i, fields).into_meta() } } diff --git a/juniper/src/validation/rules/variables_in_allowed_position.rs b/juniper/src/validation/rules/variables_in_allowed_position.rs index a931b732f..73fb5c971 100644 --- a/juniper/src/validation/rules/variables_in_allowed_position.rs +++ b/juniper/src/validation/rules/variables_in_allowed_position.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use ast::{Document, Fragment, FragmentSpread, Operation, Type, VariableDefinition}; @@ -48,7 +49,9 @@ impl<'a> VariableInAllowedPosition<'a> { { let expected_type = match (&var_def.default_value, &var_def.var_type.item) { (&Some(_), &Type::List(ref inner)) => Type::NonNullList(inner.clone()), - (&Some(_), &Type::Named(inner)) => Type::NonNullNamed(inner), + (&Some(_), &Type::Named(ref inner)) => { + Type::NonNullNamed(Cow::Borrowed(inner)) + } (_, t) => t.clone(), }; diff --git a/juniper/src/validation/test_harness.rs b/juniper/src/validation/test_harness.rs index 687f1ef81..f9f9ca65a 100644 --- a/juniper/src/validation/test_harness.rs +++ b/juniper/src/validation/test_harness.rs @@ -53,72 +53,79 @@ struct ComplexInput { impl GraphQLType for Being { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Being") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("name") - .argument(registry.arg::>("surname")), + .field::>("name", i) + .argument(registry.arg::>("surname", i)), ]; - registry.build_interface_type::(fields).into_meta() + registry.build_interface_type::(i, fields).into_meta() } } impl GraphQLType for Pet { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Pet") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("name") - .argument(registry.arg::>("surname")), + .field::>("name", i) + .argument(registry.arg::>("surname", i)), ]; - registry.build_interface_type::(fields).into_meta() + registry.build_interface_type::(i, fields).into_meta() } } impl GraphQLType for Canine { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Canine") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("name") - .argument(registry.arg::>("surname")), + .field::>("name", i) + .argument(registry.arg::>("surname", i)), ]; - registry.build_interface_type::(fields).into_meta() + registry.build_interface_type::(i, fields).into_meta() } } impl GraphQLType for DogCommand { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("DogCommand") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { registry - .build_enum_type::(&[ - EnumValue::new("SIT"), - EnumValue::new("HEEL"), - EnumValue::new("DOWN"), - ]) + .build_enum_type::( + i, + &[ + EnumValue::new("SIT"), + EnumValue::new("HEEL"), + EnumValue::new("DOWN"), + ], + ) .into_meta() } } @@ -136,37 +143,38 @@ impl FromInputValue for DogCommand { impl GraphQLType for Dog { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Dog") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("name") - .argument(registry.arg::>("surname")), - registry.field::>("nickname"), - registry.field::>("barkVolume"), - registry.field::>("barks"), + .field::>("name", i) + .argument(registry.arg::>("surname", i)), + registry.field::>("nickname", i), + registry.field::>("barkVolume", i), + registry.field::>("barks", i), registry - .field::>("doesKnowCommand") - .argument(registry.arg::>("dogCommand")), + .field::>("doesKnowCommand", i) + .argument(registry.arg::>("dogCommand", i)), registry - .field::>("isHousetrained") - .argument(registry.arg_with_default("atOtherHomes", &true)), + .field::>("isHousetrained", i) + .argument(registry.arg_with_default("atOtherHomes", &true, i)), registry - .field::>("isAtLocation") - .argument(registry.arg::>("x")) - .argument(registry.arg::>("y")), + .field::>("isAtLocation", i) + .argument(registry.arg::>("x", i)) + .argument(registry.arg::>("y", i)), ]; registry - .build_object_type::(fields) + .build_object_type::(i, fields) .interfaces(&[ - registry.get_type::(), - registry.get_type::(), - registry.get_type::(), + registry.get_type::(i), + registry.get_type::(i), + registry.get_type::(i), ]) .into_meta() } @@ -174,19 +182,23 @@ impl GraphQLType for Dog { impl GraphQLType for FurColor { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("FurColor") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { registry - .build_enum_type::(&[ - EnumValue::new("BROWN"), - EnumValue::new("BLACK"), - EnumValue::new("TAN"), - EnumValue::new("SPOTTED"), - ]) + .build_enum_type::( + i, + &[ + EnumValue::new("BROWN"), + EnumValue::new("BLACK"), + EnumValue::new("TAN"), + EnumValue::new("SPOTTED"), + ], + ) .into_meta() } } @@ -205,78 +217,85 @@ impl FromInputValue for FurColor { impl GraphQLType for Cat { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Cat") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("name") - .argument(registry.arg::>("surname")), - registry.field::>("nickname"), - registry.field::>("meows"), - registry.field::>("meowVolume"), - registry.field::>("furColor"), + .field::>("name", i) + .argument(registry.arg::>("surname", i)), + registry.field::>("nickname", i), + registry.field::>("meows", i), + registry.field::>("meowVolume", i), + registry.field::>("furColor", i), ]; registry - .build_object_type::(fields) - .interfaces(&[registry.get_type::(), registry.get_type::()]) + .build_object_type::(i, fields) + .interfaces(&[ + registry.get_type::(i), + registry.get_type::(i), + ]) .into_meta() } } impl GraphQLType for CatOrDog { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("CatOrDog") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let types = &[registry.get_type::(), registry.get_type::()]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let types = &[registry.get_type::(i), registry.get_type::(i)]; - registry.build_union_type::(types).into_meta() + registry.build_union_type::(i, types).into_meta() } } impl GraphQLType for Intelligent { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Intelligent") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let fields = &[registry.field::>("iq")]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let fields = &[registry.field::>("iq", i)]; - registry.build_interface_type::(fields).into_meta() + registry.build_interface_type::(i, fields).into_meta() } } impl GraphQLType for Human { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Human") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("name") - .argument(registry.arg::>("surname")), - registry.field::>>>("pets"), - registry.field::>>("relatives"), - registry.field::>("iq"), + .field::>("name", i) + .argument(registry.arg::>("surname", i)), + registry.field::>>>("pets", i), + registry.field::>>("relatives", i), + registry.field::>("iq", i), ]; registry - .build_object_type::(fields) + .build_object_type::(i, fields) .interfaces(&[ - registry.get_type::(), - registry.get_type::(), + registry.get_type::(i), + registry.get_type::(i), ]) .into_meta() } @@ -284,25 +303,26 @@ impl GraphQLType for Human { impl GraphQLType for Alien { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("Alien") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("name") - .argument(registry.arg::>("surname")), - registry.field::>("iq"), - registry.field::>("numEyes"), + .field::>("name", i) + .argument(registry.arg::>("surname", i)), + registry.field::>("iq", i), + registry.field::>("numEyes", i), ]; registry - .build_object_type::(fields) + .build_object_type::(i, fields) .interfaces(&[ - registry.get_type::(), - registry.get_type::(), + registry.get_type::(i), + registry.get_type::(i), ]) .into_meta() } @@ -310,49 +330,54 @@ impl GraphQLType for Alien { impl GraphQLType for DogOrHuman { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("DogOrHuman") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let types = &[registry.get_type::(), registry.get_type::()]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let types = &[registry.get_type::(i), registry.get_type::(i)]; - registry.build_union_type::(types).into_meta() + registry.build_union_type::(i, types).into_meta() } } impl GraphQLType for HumanOrAlien { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("HumanOrAlien") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { - let types = &[registry.get_type::(), registry.get_type::()]; + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { + let types = &[registry.get_type::(i), registry.get_type::(i)]; - registry.build_union_type::(types).into_meta() + registry.build_union_type::(i, types).into_meta() } } impl GraphQLType for ComplexInput { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("ComplexInput") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ - registry.arg::("requiredField"), - registry.arg::>("intField"), - registry.arg::>("stringField"), - registry.arg::>("booleanField"), - registry.arg::>>>("stringListField"), + registry.arg::("requiredField", i), + registry.arg::>("intField", i), + registry.arg::>("stringField", i), + registry.arg::>("booleanField", i), + registry.arg::>>>("stringListField", i), ]; - registry.build_input_object_type::(fields).into_meta() + registry + .build_input_object_type::(i, fields) + .into_meta() } } @@ -378,89 +403,93 @@ impl FromInputValue for ComplexInput { impl GraphQLType for ComplicatedArgs { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("ComplicatedArgs") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("intArgField") - .argument(registry.arg::>("intArg")), + .field::>("intArgField", i) + .argument(registry.arg::>("intArg", i)), registry - .field::>("nonNullIntArgField") - .argument(registry.arg::("nonNullIntArg")), + .field::>("nonNullIntArgField", i) + .argument(registry.arg::("nonNullIntArg", i)), registry - .field::>("stringArgField") - .argument(registry.arg::>("stringArg")), + .field::>("stringArgField", i) + .argument(registry.arg::>("stringArg", i)), registry - .field::>("booleanArgField") - .argument(registry.arg::>("booleanArg")), + .field::>("booleanArgField", i) + .argument(registry.arg::>("booleanArg", i)), registry - .field::>("enumArgField") - .argument(registry.arg::>("enumArg")), + .field::>("enumArgField", i) + .argument(registry.arg::>("enumArg", i)), registry - .field::>("floatArgField") - .argument(registry.arg::>("floatArg")), + .field::>("floatArgField", i) + .argument(registry.arg::>("floatArg", i)), registry - .field::>("idArgField") - .argument(registry.arg::>("idArg")), + .field::>("idArgField", i) + .argument(registry.arg::>("idArg", i)), registry - .field::>("stringListArgField") - .argument(registry.arg::>>>("stringListArg")), + .field::>("stringListArgField", i) + .argument( + registry.arg::>>>("stringListArg", i), + ), registry - .field::>("complexArgField") - .argument(registry.arg::>("complexArg")), + .field::>("complexArgField", i) + .argument(registry.arg::>("complexArg", i)), registry - .field::>("multipleReqs") - .argument(registry.arg::("req1")) - .argument(registry.arg::("req2")), + .field::>("multipleReqs", i) + .argument(registry.arg::("req1", i)) + .argument(registry.arg::("req2", i)), registry - .field::>("multipleOpts") - .argument(registry.arg_with_default("opt1", &0i32)) - .argument(registry.arg_with_default("opt2", &0i32)), + .field::>("multipleOpts", i) + .argument(registry.arg_with_default("opt1", &0i32, i)) + .argument(registry.arg_with_default("opt2", &0i32, i)), registry - .field::>("multipleOptAndReq") - .argument(registry.arg::("req1")) - .argument(registry.arg::("req2")) - .argument(registry.arg_with_default("opt1", &0i32)) - .argument(registry.arg_with_default("opt2", &0i32)), + .field::>("multipleOptAndReq", i) + .argument(registry.arg::("req1", i)) + .argument(registry.arg::("req2", i)) + .argument(registry.arg_with_default("opt1", &0i32, i)) + .argument(registry.arg_with_default("opt2", &0i32, i)), ]; - registry.build_object_type::(fields).into_meta() + registry.build_object_type::(i, fields).into_meta() } } impl GraphQLType for QueryRoot { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some("QueryRoot") } - fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> { + fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> { let fields = &[ registry - .field::>("human") - .argument(registry.arg::>("id")), - registry.field::>("alien"), - registry.field::>("dog"), - registry.field::>("cat"), - registry.field::>("pet"), - registry.field::>("catOrDog"), - registry.field::>("dorOrHuman"), - registry.field::>("humanOrAlien"), - registry.field::>("complicatedArgs"), + .field::>("human", i) + .argument(registry.arg::>("id", i)), + registry.field::>("alien", i), + registry.field::>("dog", i), + registry.field::>("cat", i), + registry.field::>("pet", i), + registry.field::>("catOrDog", i), + registry.field::>("dorOrHuman", i), + registry.field::>("humanOrAlien", i), + registry.field::>("complicatedArgs", i), ]; - registry.build_object_type::(fields).into_meta() + registry.build_object_type::(i, fields).into_meta() } } pub fn validate<'a, R, V, F>(r: R, q: &'a str, factory: F) -> Vec where - R: GraphQLType, + R: GraphQLType, V: Visitor<'a> + 'a, F: Fn() -> V, { @@ -516,7 +545,7 @@ where pub fn expect_passes_rule_with_schema<'a, R, V, F>(r: R, factory: F, q: &'a str) where - R: GraphQLType, + R: GraphQLType, V: Visitor<'a> + 'a, F: Fn() -> V, { @@ -542,7 +571,7 @@ pub fn expect_fails_rule_with_schema<'a, R, V, F>( q: &'a str, expected_errors: &[RuleError], ) where - R: GraphQLType, + R: GraphQLType, V: Visitor<'a> + 'a, F: Fn() -> V, { diff --git a/juniper/src/validation/visitor.rs b/juniper/src/validation/visitor.rs index 188615130..36b97c6c9 100644 --- a/juniper/src/validation/visitor.rs +++ b/juniper/src/validation/visitor.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use ast::{Arguments, Definition, Directive, Document, Field, Fragment, FragmentSpread, InlineFragment, InputValue, Operation, OperationType, Selection, Type, VariableDefinitions}; @@ -25,16 +27,16 @@ fn visit_definitions<'a, V: Visitor<'a>>( .. }, .. - }) => Some(Type::NonNullNamed(name)), + }) => Some(Type::NonNullNamed(Cow::Borrowed(name))), Definition::Operation(Spanning { item: Operation { operation_type: OperationType::Query, .. }, .. - }) => Some(Type::NonNullNamed( + }) => Some(Type::NonNullNamed(Cow::Borrowed( ctx.schema.concrete_query_type().name().unwrap(), - )), + ))), Definition::Operation(Spanning { item: Operation { operation_type: OperationType::Mutation, @@ -43,7 +45,7 @@ fn visit_definitions<'a, V: Visitor<'a>>( .. }) => ctx.schema .concrete_mutation_type() - .map(|t| Type::NonNullNamed(t.name().unwrap())), + .map(|t| Type::NonNullNamed(Cow::Borrowed(t.name().unwrap()))), }; ctx.with_pushed_type(def_type.as_ref(), |ctx| { @@ -240,7 +242,10 @@ fn visit_inline_fragment<'a, V: Visitor<'a>>( item: type_name, .. }) = fragment.item.type_condition { - ctx.with_pushed_type(Some(&Type::NonNullNamed(type_name)), visit_fn); + ctx.with_pushed_type( + Some(&Type::NonNullNamed(Cow::Borrowed(type_name))), + visit_fn, + ); } else { visit_fn(ctx); } @@ -257,7 +262,7 @@ fn visit_input_value<'a, V: Visitor<'a>>( InputValue::Object(ref fields) => for field in fields { let inner_type = ctx.current_input_type_literal() .and_then(|t| match *t { - Type::NonNullNamed(name) | Type::Named(name) => { + Type::NonNullNamed(ref name) | Type::Named(ref name) => { ctx.schema.concrete_type_by_name(name) } _ => None, diff --git a/juniper_codegen/src/derive_enum.rs b/juniper_codegen/src/derive_enum.rs index 29b2aa6ae..46be457b3 100644 --- a/juniper_codegen/src/derive_enum.rs +++ b/juniper_codegen/src/derive_enum.rs @@ -150,20 +150,21 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens { quote! { impl ::juniper::GraphQLType for #ident { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some(#name) } - fn meta<'r>(registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { - let meta = registry.build_enum_type::<#ident>(&[ + fn meta<'r>(_: &(), registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { + let meta = registry.build_enum_type::<#ident>(&(), &[ #(#values)* ]); #meta_description meta.into_meta() } - fn resolve(&self, _: Option<&[::juniper::Selection]>, _: &::juniper::Executor) -> ::juniper::Value { + fn resolve(&self, _: &(), _: Option<&[::juniper::Selection]>, _: &::juniper::Executor) -> ::juniper::Value { match self { #(#resolves)* } diff --git a/juniper_codegen/src/derive_input_object.rs b/juniper_codegen/src/derive_input_object.rs index f5d3c1732..ce2b93dfb 100644 --- a/juniper_codegen/src/derive_input_object.rs +++ b/juniper_codegen/src/derive_input_object.rs @@ -135,12 +135,12 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens { let create_meta_field = match default { Some(ref def) => { quote!{ - let field = registry.arg_with_default::<#field_ty>( #name, &#def); + let field = registry.arg_with_default::<#field_ty>( #name, &#def, &()); } } None => { quote!{ - let field = registry.arg::<#field_ty>(#name); + let field = registry.arg::<#field_ty>(#name, &()); } } }; @@ -186,16 +186,17 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens { quote! { impl ::juniper::GraphQLType for #ident { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&'static str> { Some(#name) } - fn meta<'r>(registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { + fn meta<'r>(_: &(), registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { let fields = &[ #(#meta_fields)* ]; - let meta = registry.build_input_object_type::<#ident>(fields); + let meta = registry.build_input_object_type::<#ident>(&(), fields); #meta_description meta.into_meta() } diff --git a/juniper_codegen/src/derive_object.rs b/juniper_codegen/src/derive_object.rs index 51b0dcd46..2a4e2ff23 100644 --- a/juniper_codegen/src/derive_object.rs +++ b/juniper_codegen/src/derive_object.rs @@ -125,7 +125,7 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens { let meta_field = quote!{ { - let field = registry.field::<#field_ty>(#name); + let field = registry.field::<#field_ty>(#name, &()); let field = #build_description; let field = #build_deprecation; field @@ -137,7 +137,7 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens { let resolver = quote!{ - #name => executor.resolve_with_ctx(&self.#field_ident), + #name => executor.resolve_with_ctx(&(), &self.#field_ident), }; resolvers.push(resolver); } @@ -145,8 +145,9 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens { let toks = quote! { impl ::juniper::GraphQLType for #ident { type Context = (); + type TypeInfo = (); - fn name() -> Option<&'static str> { + fn name(_: &()) -> Option<&str> { Some(#name) } @@ -154,16 +155,16 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens { #name.to_string() } - fn meta<'r>(registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { + fn meta<'r>(_: &(), registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { let fields = &[ #(#meta_fields)* ]; - let builder = registry.build_object_type::<#ident>(fields); + let builder = registry.build_object_type::<#ident>(&(), fields); let builder = #build_description; builder.into_meta() } - fn resolve_field(&self, field_name: &str, _: &::juniper::Arguments, executor: &::juniper::Executor) + fn resolve_field(&self, _: &(), field_name: &str, _: &::juniper::Arguments, executor: &::juniper::Executor) -> ::juniper::ExecutionResult { diff --git a/juniper_tests/src/codegen/derive_enum.rs b/juniper_tests/src/codegen/derive_enum.rs index 28319fd81..f38a1f1e0 100644 --- a/juniper_tests/src/codegen/derive_enum.rs +++ b/juniper_tests/src/codegen/derive_enum.rs @@ -1,5 +1,7 @@ +#[cfg(test)] use std::collections::HashMap; +#[cfg(test)] use juniper::{self, FromInputValue, GraphQLType, InputValue, ToInputValue}; #[derive(GraphQLEnum, Debug, PartialEq)] @@ -14,11 +16,11 @@ enum SomeEnum { #[test] fn test_derived_enum() { // Ensure that rename works. - assert_eq!(SomeEnum::name(), Some("Some")); + assert_eq!(SomeEnum::name(&()), Some("Some")); // Ensure validity of meta info. 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())); diff --git a/juniper_tests/src/codegen/derive_input_object.rs b/juniper_tests/src/codegen/derive_input_object.rs index 490b81141..721c9fa9a 100644 --- a/juniper_tests/src/codegen/derive_input_object.rs +++ b/juniper_tests/src/codegen/derive_input_object.rs @@ -1,5 +1,7 @@ +#[cfg(test)] use std::collections::HashMap; +#[cfg(test)] use juniper::{self, FromInputValue, GraphQLType, ToInputValue}; #[derive(GraphQLInputObject, Debug, PartialEq)] @@ -12,11 +14,11 @@ struct Input { #[test] 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); + let meta = Input::meta(&(), &mut registry); assert_eq!(meta.name(), Some("MyInput")); assert_eq!(meta.description(), Some(&"input descr".to_string())); diff --git a/juniper_tests/src/codegen/derive_object.rs b/juniper_tests/src/codegen/derive_object.rs index a48e93c56..63da87f4f 100644 --- a/juniper_tests/src/codegen/derive_object.rs +++ b/juniper_tests/src/codegen/derive_object.rs @@ -1,5 +1,7 @@ +#[cfg(test)] use std::collections::HashMap; +#[cfg(test)] use juniper::{self, execute, EmptyMutation, GraphQLType, RootNode, Value, Variables}; #[derive(GraphQLObject, Debug, PartialEq)] @@ -23,11 +25,11 @@ graphql_object!(Query: () |&self| { #[test] 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); + let meta = Obj::meta(&(), &mut registry); assert_eq!(meta.name(), Some("MyObj")); assert_eq!(meta.description(), Some(&"obj descr".to_string()));