Refactor GraphQLType::resolve to return Result<>

This unifies the output type of all resolvers.

Required for future step of making the output a associated type.
This commit is contained in:
Christoph Herzog 2019-11-14 09:51:32 +01:00
parent 6fcdd32c84
commit ad16093b88
8 changed files with 40 additions and 36 deletions

View file

@ -361,7 +361,7 @@ where
where
T: GraphQLType<S, Context = CtxT>,
{
Ok(value.resolve(info, self.current_selection_set, self))
value.resolve(info, self.current_selection_set, self)
}
/// Resolve a single arbitrary value into an `ExecutionResult`

View file

@ -107,8 +107,8 @@ macro_rules! graphql_scalar {
_: &$crate::Executor<
Self::Context,
$crate::__juniper_insert_generic!($($scalar)+)
>) -> $crate::Value<$crate::__juniper_insert_generic!($($scalar)+)> {
$resolve_body
>) -> $crate::ExecutionResult<$crate::__juniper_insert_generic!($($scalar)+)> {
Ok($resolve_body)
}
});

View file

@ -59,16 +59,17 @@ where
info: &Self::TypeInfo,
selection_set: Option<&[Selection<S>]>,
executor: &Executor<Self::Context, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
use crate::{types::base::resolve_selection_set_into, value::Object};
if let Some(selection_set) = selection_set {
let mut result = Object::with_capacity(selection_set.len());
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
Value::Object(result)
Ok(Value::Object(result))
} else {
Value::null()
Ok(Value::null())
}
} else {
// TODO: this panic seems useless, investigate why it is here.
panic!("resolve() must be implemented by non-object output types");
}
}

View file

@ -165,7 +165,7 @@ struct Database { users: HashMap<String, User> }
impl Context for Database {}
impl GraphQLType for User
impl GraphQLType<DefaultScalarValue> for User
{
type Context = Database;
type TypeInfo = ();
@ -298,7 +298,7 @@ where
executor: &Executor<Self::Context, S>,
) -> ExecutionResult<S> {
if Self::name(info).unwrap() == type_name {
Ok(self.resolve(info, selection_set, executor))
self.resolve(info, selection_set, executor)
} else {
panic!("resolve_into_type must be implemented by unions and interfaces");
}
@ -318,23 +318,26 @@ where
/// of the object should simply be returned.
///
/// For objects, all fields in the selection set should be resolved.
///
/// The default implementation uses `resolve_field` to resolve all fields,
/// including those through fragment expansion, for object types. For
/// non-object types, this method panics.
/// including those through fragment expansion.
///
/// Since the GraphQL spec specificies that errors during field processing
/// should result in a null-value, this might return Ok(Null) in case of
/// failure. Errors are recorded internally.
fn resolve(
&self,
info: &Self::TypeInfo,
selection_set: Option<&[Selection<S>]>,
executor: &Executor<Self::Context, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
if let Some(selection_set) = selection_set {
let mut result = Object::with_capacity(selection_set.len());
if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
let out = if resolve_selection_set_into(self, info, selection_set, executor, &mut result) {
Value::Object(result)
} else {
Value::null()
}
};
Ok(out)
} else {
panic!("resolve() must be implemented by non-object output types");
}

View file

@ -2,6 +2,7 @@ use crate::{
ast::{FromInputValue, InputValue, Selection, ToInputValue},
schema::meta::MetaType,
value::{ScalarValue, Value},
executor::ExecutionResult,
};
use crate::{
@ -33,10 +34,10 @@ where
info: &T::TypeInfo,
_: Option<&[Selection<S>]>,
executor: &Executor<CtxT, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
match *self {
Some(ref obj) => executor.resolve_into_value(info, obj),
None => Value::null(),
Some(ref obj) => executor.resolve(info, obj),
None => Ok(Value::null()),
}
}
}
@ -94,7 +95,7 @@ where
info: &T::TypeInfo,
_: Option<&[Selection<S>]>,
executor: &Executor<CtxT, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
resolve_into_list(executor, info, self.iter())
}
}
@ -161,7 +162,7 @@ where
info: &T::TypeInfo,
_: Option<&[Selection<S>]>,
executor: &Executor<CtxT, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
resolve_into_list(executor, info, self.iter())
}
}
@ -180,7 +181,7 @@ fn resolve_into_list<S, T, I>(
executor: &Executor<T::Context, S>,
info: &T::TypeInfo,
iter: I,
) -> Value<S>
) -> ExecutionResult<S>
where
S: ScalarValue,
I: Iterator<Item = T> + ExactSizeIterator,
@ -191,19 +192,17 @@ where
.list_contents()
.expect("Current type is not a list type")
.is_non_null();
let mut result = Vec::with_capacity(iter.len());
for o in iter {
let value = executor.resolve_into_value(info, &o);
if stop_on_null && value.is_null() {
return value;
match executor.resolve(info, &o) {
Ok(value) if stop_on_null && value.is_null() => { return Ok(value) },
Ok(value) => { result.push(value) },
Err(e) => { return Err(e) },
}
result.push(value);
}
Value::list(result)
Ok(Value::list(result))
}
#[cfg(feature = "async")]

View file

@ -52,7 +52,7 @@ where
info: &T::TypeInfo,
selection_set: Option<&[Selection<S>]>,
executor: &Executor<CtxT, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
(**self).resolve(info, selection_set, executor)
}
}
@ -124,7 +124,7 @@ where
info: &T::TypeInfo,
selection_set: Option<&[Selection<S>]>,
executor: &Executor<CtxT, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
(**self).resolve(info, selection_set, executor)
}
}
@ -211,7 +211,7 @@ where
info: &T::TypeInfo,
selection_set: Option<&[Selection<S>]>,
executor: &Executor<T::Context, S>,
) -> Value<S> {
) -> ExecutionResult<S> {
(**self).resolve(info, selection_set, executor)
}
}

View file

@ -3,7 +3,7 @@ use std::{char, convert::From, marker::PhantomData, ops::Deref, u32};
use crate::{
ast::{InputValue, Selection, ToInputValue},
executor::{Executor, Registry},
executor::{Executor, Registry, ExecutionResult},
parser::{LexerError, ParseError, ScalarToken, Token},
schema::meta::MetaType,
types::base::GraphQLType,
@ -189,8 +189,8 @@ where
_: &(),
_: Option<&[Selection<S>]>,
_: &Executor<Self::Context, S>,
) -> Value<S> {
Value::scalar(String::from(*self))
) -> ExecutionResult<S> {
Ok(Value::scalar(String::from(*self)))
}
}

View file

@ -257,10 +257,11 @@ pub fn impl_enum(ast: &syn::DeriveInput, is_internal: bool) -> TokenStream {
_: &(),
_: Option<&[#juniper_path::Selection<__S>]>,
_: &#juniper_path::Executor<Self::Context, __S>
) -> #juniper_path::Value<__S> {
match self {
) -> #juniper_path::ExecutionResult<__S> {
let v = match self {
#resolves
}
};
Ok(v)
}
}