Merge branch 'master' of https://github.com/graphql-rust/juniper into graphql-rust-master

This commit is contained in:
Cameron Eldridge 2018-05-23 17:57:20 -04:00
commit 934fcbb2bd
89 changed files with 3414 additions and 2542 deletions

View file

@ -6,3 +6,17 @@
**Note:** while this is not a Rust breaking change, if you relied on the serialization format (perhaps by storing serialized data in a database or making asumptions in your client code written in another language) it could be a breaking change for your application.
[#151](https://github.com/graphql-rust/juniper/pull/151)
* The `GraphQLObject`, `GraphQLInputObject`, and `GraphQLEnum` custom derives will reject
invalid [names](http://facebook.github.io/graphql/October2016/#Name) at compile time.
[#170](https://github.com/graphql-rust/juniper/pull/170)
* Large integers (> signed 32bit) are now deserialized as floats. Previously,
they produced the "integer out of range" error. For languages that do not
have distinction between integer and floating point types (including
javascript), this means large floating point values which do not have
fractional part could not be decoded (because they are represented without
a decimal part `.0`).
[#179](https://github.com/graphql-rust/juniper/pull/179)

View file

@ -42,7 +42,7 @@ serde_derive = {version="1.0.2" }
chrono = { version = "0.4.0", optional = true }
serde_json = { version="1.0.2", optional = true }
url = { version = "1.5.1", optional = true }
uuid = { version = "0.5.1", optional = true }
uuid = { version = "> 0.4, < 0.7", optional = true }
[dev-dependencies]
bencher = "0.1.2"

View file

@ -4,8 +4,8 @@ extern crate juniper;
use bencher::Bencher;
use juniper::{execute, EmptyMutation, RootNode, Variables};
use juniper::tests::model::Database;
use juniper::{execute, EmptyMutation, RootNode, Variables};
fn query_type_name(b: &mut Bencher) {
let database = Database::new();

View file

@ -1,8 +1,8 @@
use std::fmt;
use std::borrow::Cow;
use std::fmt;
use std::hash::Hash;
use std::vec;
use std::slice;
use std::vec;
use indexmap::IndexMap;
@ -432,25 +432,25 @@ impl fmt::Display for InputValue {
InputValue::Enum(ref v) => write!(f, "{}", v),
InputValue::Variable(ref v) => write!(f, "${}", v),
InputValue::List(ref v) => {
try!(write!(f, "["));
write!(f, "[")?;
for (i, spanning) in v.iter().enumerate() {
try!(spanning.item.fmt(f));
spanning.item.fmt(f)?;
if i < v.len() - 1 {
try!(write!(f, ", "));
write!(f, ", ")?;
}
}
write!(f, "]")
}
InputValue::Object(ref o) => {
try!(write!(f, "{{"));
write!(f, "{{")?;
for (i, &(ref k, ref v)) in o.iter().enumerate() {
try!(write!(f, "{}: ", k.item));
try!(v.item.fmt(f));
write!(f, "{}: ", k.item)?;
v.item.fmt(f)?;
if i < o.len() - 1 {
try!(write!(f, ", "));
write!(f, ", ")?;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,16 +1,16 @@
use std::cmp::Ordering;
use std::fmt::Display;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt::Display;
use std::sync::RwLock;
use fnv::FnvHashMap;
use GraphQLError;
use ast::{Definition, Document, Fragment, FromInputValue, InputValue, OperationType, Selection,
ToInputValue, Type};
use value::Value;
use GraphQLError;
use parser::SourcePosition;
use value::Value;
use schema::meta::{Argument, EnumMeta, EnumValue, Field, InputObjectMeta, InterfaceMeta, ListMeta,
MetaType, NullableMeta, ObjectMeta, PlaceholderMeta, ScalarMeta, UnionMeta};
@ -19,6 +19,10 @@ use schema::model::{RootNode, SchemaType, TypeType};
use types::base::GraphQLType;
use types::name::Name;
mod look_ahead;
pub use self::look_ahead::{Applies, LookAheadArgument, LookAheadSelection, LookAheadValue, LookAheadMethods, ChildSelection, ConcreteLookAheadSelection};
/// A type registry used to build schemas
///
/// The registry gathers metadata for all types in a schema. It provides
@ -46,6 +50,7 @@ where
fragments: &'a HashMap<&'a str, &'a Fragment<'a>>,
variables: &'a Variables,
current_selection_set: Option<&'a [Selection<'a>]>,
parent_selection_set: Option<&'a [Selection<'a>]>,
current_type: TypeType<'a>,
schema: &'a SchemaType<'a>,
context: &'a CtxT,
@ -220,7 +225,8 @@ impl<'a, T: GraphQLType, C> IntoResolvable<'a, T, C> for FieldResult<(&'a T::Con
}
impl<'a, T: GraphQLType, C> IntoResolvable<'a, Option<T>, C>
for FieldResult<Option<(&'a T::Context, T)>> {
for FieldResult<Option<(&'a T::Context, T)>>
{
fn into(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, Option<T>)>> {
self.map(|o| o.map(|(ctx, v)| (ctx, Some(v))))
}
@ -229,20 +235,20 @@ impl<'a, T: GraphQLType, C> IntoResolvable<'a, Option<T>, C>
/// Conversion trait for context types
///
/// Used to support different context types for different parts of an
/// application. By making each GraphQL type only aware of as much
/// application. By making each `GraphQL` type only aware of as much
/// context as it needs to, isolation and robustness can be
/// improved. Implement this trait if you have contexts that can
/// generally be converted between each other.
///
/// The empty tuple `()` can be converted into from any context type,
/// making it suitable for GraphQL that don't need _any_ context to
/// making it suitable for `GraphQL` that don't need _any_ context to
/// work, e.g. scalars or enums.
pub trait FromContext<T> {
/// Perform the conversion
fn from(value: &T) -> &Self;
}
/// Marker trait for types that can act as context objects for GraphQL types.
/// Marker trait for types that can act as context objects for `GraphQL` types.
pub trait Context {}
impl<'a, C: Context> Context for &'a C {}
@ -313,6 +319,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
fragments: self.fragments,
variables: self.variables,
current_selection_set: self.current_selection_set,
parent_selection_set: self.parent_selection_set,
current_type: self.current_type.clone(),
schema: self.schema,
context: ctx,
@ -333,6 +340,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
fragments: self.fragments,
variables: self.variables,
current_selection_set: selection_set,
parent_selection_set: self.current_selection_set,
current_type: self.schema.make_type(
&self.current_type
.innermost_concrete()
@ -357,6 +365,7 @@ impl<'a, CtxT> Executor<'a, CtxT> {
fragments: self.fragments,
variables: self.variables,
current_selection_set: selection_set,
parent_selection_set: self.current_selection_set,
current_type: match type_name {
Some(type_name) => self.schema.type_by_name(type_name).expect("Type not found"),
None => self.current_type.clone(),
@ -420,6 +429,26 @@ impl<'a, CtxT> Executor<'a, CtxT> {
error: error,
});
}
/// Construct a lookahead selection for the current selection
///
/// This allows to see the whole selection and preform operations
/// affecting the childs
pub fn look_ahead(&'a self) -> LookAheadSelection<'a> {
self.parent_selection_set.map(|p| {
LookAheadSelection::build_from_selection(&p[0], self.variables, self.fragments)
}).unwrap_or_else(||{
LookAheadSelection{
name: self.current_type.innermost_concrete().name().unwrap_or(""),
alias: None,
arguments: Vec::new(),
children: self.current_selection_set.map(|s| s.iter().map(|s| ChildSelection {
inner: LookAheadSelection::build_from_selection(s, self.variables, self.fragments),
applies_for: Applies::All
}).collect()).unwrap_or_else(Vec::new)
}
})
}
}
impl<'a> FieldPath<'a> {
@ -547,6 +576,7 @@ where
.collect(),
variables: final_vars,
current_selection_set: Some(&op.item.selection_set[..]),
parent_selection_set: None,
current_type: root_type,
schema: &root_node.schema,
context: context,

View file

@ -1,9 +1,9 @@
use indexmap::IndexMap;
use value::Value;
use executor::Variables;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct TestType;

View file

@ -1,13 +1,13 @@
use indexmap::IndexMap;
use value::Value;
use ast::InputValue;
use executor::Variables;
use schema::model::RootNode;
use GraphQLError::ValidationError;
use validation::RuleError;
use parser::SourcePosition;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use validation::RuleError;
use value::Value;
use GraphQLError::ValidationError;
#[derive(GraphQLEnum, Debug)]
#[graphql(_internal)]
@ -77,12 +77,10 @@ fn does_not_accept_string_literals() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Invalid value for argument "color", expected type "Color!""#,
&[SourcePosition::new(18, 0, 18)],
),
])
ValidationError(vec![RuleError::new(
r#"Invalid value for argument "color", expected type "Color!""#,
&[SourcePosition::new(18, 0, 18)],
)])
);
}
@ -112,12 +110,10 @@ fn does_not_accept_incorrect_enum_name_in_variables() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$color" got invalid value. Invalid value for enum "Color"."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$color" got invalid value. Invalid value for enum "Color"."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -134,11 +130,9 @@ fn does_not_accept_incorrect_type_in_variables() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
ValidationError(vec![RuleError::new(
r#"Variable "$color" got invalid value. Expected "Color", found not a string or enum."#,
&[SourcePosition::new(8, 0, 8)],
),
])
)])
);
}

View file

@ -1,8 +1,8 @@
mod field_execution {
use value::Value;
use ast::InputValue;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct DataType;
struct DeepDataType;
@ -128,9 +128,9 @@ mod field_execution {
}
mod merge_parallel_fragments {
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Type;
@ -198,9 +198,9 @@ mod merge_parallel_fragments {
}
mod merge_parallel_inline_fragments {
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Type;
struct Other;
@ -270,38 +270,34 @@ mod merge_parallel_inline_fragments {
("b", Value::string("Banana")),
(
"deeper",
Value::list(
vec![
Value::object(
vec![
(
"deepest",
Value::object(
vec![
("b", Value::string("Banana")),
("c", Value::string("Cherry")),
].into_iter()
.collect(),
),
),
].into_iter().collect()
),
Value::object(
vec![
(
"deepest",
Value::object(
vec![
("b", Value::string("Banana")),
("c", Value::string("Cherry")),
].into_iter()
.collect(),
),
),
].into_iter().collect()
),
]
),
Value::list(vec![
Value::object(
vec![(
"deepest",
Value::object(
vec![
("b", Value::string("Banana")),
("c", Value::string("Cherry")),
].into_iter()
.collect(),
),
)].into_iter()
.collect(),
),
Value::object(
vec![(
"deepest",
Value::object(
vec![
("b", Value::string("Banana")),
("c", Value::string("Cherry")),
].into_iter()
.collect(),
),
)].into_iter()
.collect(),
),
]),
),
("c", Value::string("Cherry")),
].into_iter()
@ -317,10 +313,10 @@ mod merge_parallel_inline_fragments {
}
mod threads_context_correctly {
use value::Value;
use types::scalars::EmptyMutation;
use schema::model::RootNode;
use executor::Context;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Schema;
@ -369,11 +365,11 @@ mod threads_context_correctly {
mod dynamic_context_switching {
use indexmap::IndexMap;
use value::Value;
use types::scalars::EmptyMutation;
use schema::model::RootNode;
use parser::SourcePosition;
use executor::{Context, ExecutionError, FieldError, FieldResult};
use parser::SourcePosition;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Schema;
@ -509,16 +505,14 @@ mod dynamic_context_switching {
assert_eq!(
result,
Value::object(
vec![
(
"first",
Value::object(
vec![("value", Value::string("First value"))]
.into_iter()
.collect(),
),
vec![(
"first",
Value::object(
vec![("value", Value::string("First value"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
)
);
@ -557,13 +551,11 @@ mod dynamic_context_switching {
assert_eq!(
errs,
vec![
ExecutionError::new(
SourcePosition::new(25, 2, 12),
&["missing"],
FieldError::new("Could not find key 2", Value::null()),
),
]
vec![ExecutionError::new(
SourcePosition::new(25, 2, 12),
&["missing"],
FieldError::new("Could not find key 2", Value::null()),
)]
);
println!("Result: {:?}", result);
@ -606,13 +598,11 @@ mod dynamic_context_switching {
assert_eq!(
errs,
[
ExecutionError::new(
SourcePosition::new(123, 4, 12),
&["tooLarge"],
FieldError::new("Key too large: 200", Value::null()),
),
]
[ExecutionError::new(
SourcePosition::new(123, 4, 12),
&["tooLarge"],
FieldError::new("Key too large: 200", Value::null()),
)]
);
println!("Result: {:?}", result);
@ -671,16 +661,14 @@ mod dynamic_context_switching {
assert_eq!(
result,
Value::object(
vec![
(
"first",
Value::object(
vec![("value", Value::string("First value"))]
.into_iter()
.collect(),
),
vec![(
"first",
Value::object(
vec![("value", Value::string("First value"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
)
);
@ -688,11 +676,11 @@ mod dynamic_context_switching {
}
mod propagates_errors_to_nullable_fields {
use value::Value;
use schema::model::RootNode;
use executor::{ExecutionError, FieldError, FieldResult};
use parser::SourcePosition;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Schema;
struct Inner;
@ -728,13 +716,11 @@ mod propagates_errors_to_nullable_fields {
assert_eq!(
errs,
vec![
ExecutionError::new(
SourcePosition::new(10, 0, 10),
&["inner", "nullableErrorField"],
FieldError::new("Error for nullableErrorField", Value::null()),
),
]
vec![ExecutionError::new(
SourcePosition::new(10, 0, 10),
&["inner", "nullableErrorField"],
FieldError::new("Error for nullableErrorField", Value::null()),
)]
);
}
@ -753,13 +739,11 @@ mod propagates_errors_to_nullable_fields {
assert_eq!(
errs,
vec![
ExecutionError::new(
SourcePosition::new(10, 0, 10),
&["inner", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
),
]
vec![ExecutionError::new(
SourcePosition::new(10, 0, 10),
&["inner", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
)]
);
}
@ -781,13 +765,11 @@ mod propagates_errors_to_nullable_fields {
assert_eq!(
errs,
vec![
ExecutionError::new(
SourcePosition::new(26, 0, 26),
&["inner", "nullableField", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
),
]
vec![ExecutionError::new(
SourcePosition::new(26, 0, 26),
&["inner", "nullableField", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
)]
);
}
@ -806,13 +788,11 @@ mod propagates_errors_to_nullable_fields {
assert_eq!(
errs,
vec![
ExecutionError::new(
SourcePosition::new(29, 0, 29),
&["inner", "nonNullableField", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
),
]
vec![ExecutionError::new(
SourcePosition::new(29, 0, 29),
&["inner", "nonNullableField", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
)]
);
}
@ -834,13 +814,11 @@ mod propagates_errors_to_nullable_fields {
assert_eq!(
errs,
vec![
ExecutionError::new(
SourcePosition::new(29, 0, 29),
&["inner", "nonNullableField", "nullableErrorField"],
FieldError::new("Error for nullableErrorField", Value::null()),
),
]
vec![ExecutionError::new(
SourcePosition::new(29, 0, 29),
&["inner", "nonNullableField", "nullableErrorField"],
FieldError::new("Error for nullableErrorField", Value::null()),
)]
);
}
@ -859,13 +837,11 @@ mod propagates_errors_to_nullable_fields {
assert_eq!(
errs,
vec![
ExecutionError::new(
SourcePosition::new(11, 0, 11),
&["inners", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
),
]
vec![ExecutionError::new(
SourcePosition::new(11, 0, 11),
&["inners", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()),
)]
);
}
@ -919,9 +895,9 @@ mod propagates_errors_to_nullable_fields {
}
mod named_operations {
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
use GraphQLError;
struct Schema;

View file

@ -1,7 +1,7 @@
mod interface {
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
trait Pet {
fn name(&self) -> &str;
@ -116,27 +116,25 @@ mod interface {
assert_eq!(
result,
Value::object(
vec![
(
"pets",
Value::list(vec![
Value::object(
vec![
("name", Value::string("Odie")),
("woofs", Value::boolean(true)),
].into_iter()
.collect(),
),
Value::object(
vec![
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter()
.collect(),
),
]),
),
].into_iter()
vec![(
"pets",
Value::list(vec![
Value::object(
vec![
("name", Value::string("Odie")),
("woofs", Value::boolean(true)),
].into_iter()
.collect(),
),
Value::object(
vec![
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter()
.collect(),
),
]),
)].into_iter()
.collect()
)
);
@ -144,9 +142,9 @@ mod interface {
}
mod union {
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
trait Pet {
fn as_dog(&self) -> Option<&Dog> {
@ -249,29 +247,27 @@ mod union {
assert_eq!(
result,
Value::object(
vec![
(
"pets",
Value::list(vec![
Value::object(
vec![
("__typename", Value::string("Dog")),
("name", Value::string("Odie")),
("woofs", Value::boolean(true)),
].into_iter()
.collect(),
),
Value::object(
vec![
("__typename", Value::string("Cat")),
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter()
.collect(),
),
]),
),
].into_iter()
vec![(
"pets",
Value::list(vec![
Value::object(
vec![
("__typename", Value::string("Dog")),
("name", Value::string("Odie")),
("woofs", Value::boolean(true)),
].into_iter()
.collect(),
),
Value::object(
vec![
("__typename", Value::string("Cat")),
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter()
.collect(),
),
]),
)].into_iter()
.collect()
)
);

View file

@ -1,9 +1,9 @@
use indexmap::IndexMap;
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
/*
@ -48,15 +48,19 @@ enum EnumDescription {
#[derive(GraphQLEnum)]
#[graphql(_internal)]
enum EnumValueDescription {
#[graphql(description = "The FOO value")] Foo,
#[graphql(description = "The BAR value")] Bar,
#[graphql(description = "The FOO value")]
Foo,
#[graphql(description = "The BAR value")]
Bar,
}
#[derive(GraphQLEnum)]
#[graphql(_internal)]
enum EnumDeprecation {
#[graphql(deprecated = "Please don't use FOO any more")] Foo,
#[graphql(description = "The BAR value", deprecated = "Please don't use BAR any more")] Bar,
#[graphql(deprecated = "Please don't use FOO any more")]
Foo,
#[graphql(description = "The BAR value", deprecated = "Please don't use BAR any more")]
Bar,
}
struct Root;
@ -131,7 +135,7 @@ fn default_name_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -143,7 +147,7 @@ fn default_name_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -180,7 +184,7 @@ fn named_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -192,7 +196,7 @@ fn named_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -232,7 +236,7 @@ fn no_trailing_comma_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -244,7 +248,7 @@ fn no_trailing_comma_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -287,7 +291,7 @@ fn enum_description_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -299,7 +303,7 @@ fn enum_description_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -339,7 +343,7 @@ fn enum_value_description_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -351,7 +355,7 @@ fn enum_value_description_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -394,7 +398,7 @@ fn enum_deprecation_introspection() {
Value::string("Please don't use FOO any more"),
),
].into_iter()
.collect()
.collect(),
))
);
@ -409,7 +413,7 @@ fn enum_deprecation_introspection() {
Value::string("Please don't use BAR any more"),
),
].into_iter()
.collect()
.collect(),
))
);
});

View file

@ -2,9 +2,9 @@ use indexmap::IndexMap;
use ast::{FromInputValue, InputValue};
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Root;
@ -53,8 +53,11 @@ pub struct PublicWithDescription {
}
#[derive(GraphQLInputObject, Debug)]
#[graphql(name = "APublicNamedInputObjectWithDescription",
description = "Description for the input object", _internal)]
#[graphql(
name = "APublicNamedInputObjectWithDescription",
description = "Description for the input object",
_internal
)]
pub struct NamedPublicWithDescription {
field_one: String,
}
@ -68,15 +71,19 @@ pub struct NamedPublic {
#[derive(GraphQLInputObject, Debug)]
#[graphql(_internal)]
struct FieldDescription {
#[graphql(description = "The first field")] field_one: String,
#[graphql(description = "The second field")] field_two: String,
#[graphql(description = "The first field")]
field_one: String,
#[graphql(description = "The second field")]
field_two: String,
}
#[derive(GraphQLInputObject, Debug)]
#[graphql(_internal)]
struct FieldWithDefaults {
#[graphql(default = "123")] field_one: i32,
#[graphql(default = "456", description = "The second field")] field_two: i32,
#[graphql(default = "123")]
field_one: i32,
#[graphql(default = "456", description = "The second field")]
field_two: i32,
}
graphql_object!(Root: () |&self| {
@ -162,22 +169,20 @@ fn default_name_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -189,22 +194,20 @@ fn default_name_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -268,22 +271,20 @@ fn no_trailing_comma_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -295,22 +296,20 @@ fn no_trailing_comma_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -351,22 +350,20 @@ fn derive_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -423,22 +420,20 @@ fn named_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -482,22 +477,20 @@ fn description_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -541,22 +534,20 @@ fn field_description_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -568,22 +559,20 @@ fn field_description_introspection() {
(
"type",
Value::object(
vec![
(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
vec![(
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
});
@ -624,7 +613,7 @@ fn field_with_defaults_introspection() {
),
("defaultValue", Value::string("123")),
].into_iter()
.collect()
.collect(),
))
);
@ -638,7 +627,7 @@ fn field_with_defaults_introspection() {
),
("defaultValue", Value::string("456")),
].into_iter()
.collect()
.collect(),
))
);
});

View file

@ -1,14 +1,14 @@
mod input_object;
mod enums;
mod input_object;
// This asserts that the input objects defined public actually became public
#[allow(unused_imports)]
use self::input_object::{NamedPublic, NamedPublicWithDescription};
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
#[derive(GraphQLEnum)]
#[graphql(name = "SampleEnum", _internal)]
@ -155,7 +155,7 @@ fn enum_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -167,7 +167,7 @@ fn enum_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
}
@ -290,7 +290,7 @@ fn interface_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
}
@ -366,13 +366,11 @@ fn object_introspection() {
);
assert_eq!(
type_info.get("interfaces"),
Some(&Value::list(vec![
Value::object(
vec![("name", Value::string("SampleInterface"))]
.into_iter()
.collect(),
),
]))
Some(&Value::list(vec![Value::object(
vec![("name", Value::string("SampleInterface"))]
.into_iter()
.collect(),
)]))
);
assert_eq!(type_info.get("enumValues"), Some(&Value::null()));
assert_eq!(type_info.get("inputFields"), Some(&Value::null()));
@ -418,7 +416,7 @@ fn object_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
@ -506,7 +504,7 @@ fn object_introspection() {
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
.collect(),
))
);
}

View file

@ -1,6 +1,6 @@
mod introspection;
mod variables;
mod enums;
mod directives;
mod enums;
mod executor;
mod interfaces_unions;
mod introspection;
mod variables;

View file

@ -1,13 +1,13 @@
use indexmap::IndexMap;
use value::Value;
use ast::InputValue;
use executor::Variables;
use schema::model::RootNode;
use GraphQLError::ValidationError;
use validation::RuleError;
use parser::SourcePosition;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use validation::RuleError;
use value::Value;
use GraphQLError::ValidationError;
#[derive(Debug)]
struct TestComplexScalar;
@ -56,7 +56,8 @@ struct ExampleInputObject {
#[derive(GraphQLInputObject, Debug)]
#[graphql(_internal)]
struct InputWithDefaults {
#[graphql(default = "123")] a: i32,
#[graphql(default = "123")]
a: i32,
}
graphql_object!(TestType: () |&self| {
@ -177,19 +178,17 @@ fn inline_runs_from_input_value_on_scalar() {
fn variable_complex_input() {
run_variable_query(
r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::list(vec![InputValue::string("bar")])),
("c", InputValue::string("baz")),
].into_iter()
.collect(),
),
vec![(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::list(vec![InputValue::string("bar")])),
("c", InputValue::string("baz")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
|result| {
assert_eq!(
@ -203,19 +202,17 @@ fn variable_complex_input() {
fn variable_parse_single_value_to_list() {
run_variable_query(
r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
("c", InputValue::string("baz")),
].into_iter()
.collect(),
),
vec![(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
("c", InputValue::string("baz")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
|result| {
assert_eq!(
@ -229,18 +226,16 @@ fn variable_parse_single_value_to_list() {
fn variable_runs_from_input_value_on_scalar() {
run_variable_query(
r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::object(
vec![
("c", InputValue::string("baz")),
("d", InputValue::string("SerializedValue")),
].into_iter()
.collect(),
),
vec![(
"input".to_owned(),
InputValue::object(
vec![
("c", InputValue::string("baz")),
("d", InputValue::string("SerializedValue")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect(),
|result| {
assert_eq!(
@ -255,31 +250,27 @@ fn variable_error_on_nested_non_null() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#;
let vars = vec![
(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
("c", InputValue::null()),
].into_iter()
.collect(),
),
let vars = vec![(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
("c", InputValue::null()),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
ValidationError(vec![RuleError::new(
r#"Variable "$input" got invalid value. In field "c": Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
])
)])
);
}
@ -307,30 +298,26 @@ fn variable_error_on_omit_non_null() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#;
let vars = vec![
(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
].into_iter()
.collect(),
),
let vars = vec![(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
ValidationError(vec![RuleError::new(
r#"Variable "$input" got invalid value. In field "c": Expected "String!", found null."#,
&[SourcePosition::new(8, 0, 8)],
),
])
)])
);
}
@ -340,22 +327,16 @@ fn variable_multiple_errors_with_nesting() {
let query =
r#"query q($input: TestNestedInputObject) { fieldWithNestedObjectInput(input: $input) }"#;
let vars = vec![
(
"input".to_owned(),
InputValue::object(
vec![
(
"na",
InputValue::object(
vec![("a", InputValue::string("foo"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
let vars = vec![(
"input".to_owned(),
InputValue::object(
vec![(
"na",
InputValue::object(vec![("a", InputValue::string("foo"))].into_iter().collect()),
)].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
@ -377,32 +358,28 @@ fn variable_error_on_additional_field() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($input: TestInputObject) { fieldWithObjectInput(input: $input) }"#;
let vars = vec![
(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
("c", InputValue::string("baz")),
("extra", InputValue::string("dog")),
].into_iter()
.collect(),
),
let vars = vec![(
"input".to_owned(),
InputValue::object(
vec![
("a", InputValue::string("foo")),
("b", InputValue::string("bar")),
("c", InputValue::string("baz")),
("extra", InputValue::string("dog")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$input" got invalid value. In field "extra": Unknown field."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$input" got invalid value. In field "extra": Unknown field."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -498,12 +475,10 @@ fn does_not_allow_non_nullable_input_to_be_omitted_in_variable() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$value" of required type "String!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$value" of required type "String!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -520,12 +495,10 @@ fn does_not_allow_non_nullable_input_to_be_set_to_null_in_variable() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$value" of required type "String!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$value" of required type "String!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -575,12 +548,10 @@ fn allow_lists_to_be_null() {
fn allow_lists_to_contain_values() {
run_variable_query(
r#"query q($input: [String]) { list(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
),
].into_iter()
vec![(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
)].into_iter()
.collect(),
|result| {
assert_eq!(
@ -595,16 +566,14 @@ fn allow_lists_to_contain_values() {
fn allow_lists_to_contain_null() {
run_variable_query(
r#"query q($input: [String]) { list(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
),
].into_iter()
vec![(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
)].into_iter()
.collect(),
|result| {
assert_eq!(
@ -628,12 +597,10 @@ fn does_not_allow_non_null_lists_to_be_null() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$input" of required type "[String]!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$input" of required type "[String]!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -641,12 +608,10 @@ fn does_not_allow_non_null_lists_to_be_null() {
fn allow_non_null_lists_to_contain_values() {
run_variable_query(
r#"query q($input: [String]!) { nnList(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
),
].into_iter()
vec![(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
)].into_iter()
.collect(),
|result| {
assert_eq!(result.get("nnList"), Some(&Value::string(r#"[Some("A")]"#)));
@ -657,16 +622,14 @@ fn allow_non_null_lists_to_contain_values() {
fn allow_non_null_lists_to_contain_null() {
run_variable_query(
r#"query q($input: [String]!) { nnList(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
),
].into_iter()
vec![(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
)].into_iter()
.collect(),
|result| {
assert_eq!(
@ -694,12 +657,10 @@ fn allow_lists_of_non_null_to_be_null() {
fn allow_lists_of_non_null_to_contain_values() {
run_variable_query(
r#"query q($input: [String!]) { listNn(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
),
].into_iter()
vec![(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
)].into_iter()
.collect(),
|result| {
assert_eq!(result.get("listNn"), Some(&Value::string(r#"Some(["A"])"#)));
@ -712,16 +673,14 @@ fn does_not_allow_lists_of_non_null_to_contain_null() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($input: [String!]) { listNn(input: $input) }"#;
let vars = vec![
(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
),
].into_iter()
let vars = vec![(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
@ -739,16 +698,14 @@ fn does_not_allow_non_null_lists_of_non_null_to_contain_null() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($input: [String!]!) { nnListNn(input: $input) }"#;
let vars = vec![
(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
),
].into_iter()
let vars = vec![(
"input".to_owned(),
InputValue::list(vec![
InputValue::string("A"),
InputValue::null(),
InputValue::string("B"),
]),
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
@ -774,12 +731,10 @@ fn does_not_allow_non_null_lists_of_non_null_to_be_null() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$input" of required type "[String!]!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$input" of required type "[String!]!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -787,12 +742,10 @@ fn does_not_allow_non_null_lists_of_non_null_to_be_null() {
fn allow_non_null_lists_of_non_null_to_contain_values() {
run_variable_query(
r#"query q($input: [String!]!) { nnListNn(input: $input) }"#,
vec![
(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
),
].into_iter()
vec![(
"input".to_owned(),
InputValue::list(vec![InputValue::string("A")]),
)].into_iter()
.collect(),
|result| {
assert_eq!(result.get("nnListNn"), Some(&Value::string(r#"["A"]"#)));
@ -805,12 +758,10 @@ fn does_not_allow_invalid_types_to_be_used_as_values() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($input: TestType!) { fieldWithObjectInput(input: $input) }"#;
let vars = vec![
(
"value".to_owned(),
InputValue::list(vec![InputValue::string("A"), InputValue::string("B")]),
),
].into_iter()
let vars = vec![(
"value".to_owned(),
InputValue::list(vec![InputValue::string("A"), InputValue::string("B")]),
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
@ -828,12 +779,10 @@ fn does_not_allow_unknown_types_to_be_used_as_values() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($input: UnknownType!) { fieldWithObjectInput(input: $input) }"#;
let vars = vec![
(
"value".to_owned(),
InputValue::list(vec![InputValue::string("A"), InputValue::string("B")]),
),
].into_iter()
let vars = vec![(
"value".to_owned(),
InputValue::list(vec![InputValue::string("A"), InputValue::string("B")]),
)].into_iter()
.collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
@ -953,12 +902,10 @@ fn does_not_allow_missing_required_field() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Invalid value for argument "arg", expected type "ExampleInputObject!""#,
&[SourcePosition::new(20, 0, 20)],
),
])
ValidationError(vec![RuleError::new(
r#"Invalid value for argument "arg", expected type "ExampleInputObject!""#,
&[SourcePosition::new(20, 0, 20)],
)])
);
}
@ -973,12 +920,10 @@ fn does_not_allow_null_in_required_field() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Invalid value for argument "arg", expected type "ExampleInputObject!""#,
&[SourcePosition::new(20, 0, 20)],
),
])
ValidationError(vec![RuleError::new(
r#"Invalid value for argument "arg", expected type "ExampleInputObject!""#,
&[SourcePosition::new(20, 0, 20)],
)])
);
}
@ -993,12 +938,10 @@ fn does_not_allow_missing_variable_for_required_field() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$var" of required type "Int!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$var" of required type "Int!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -1015,12 +958,10 @@ fn does_not_allow_null_variable_for_required_field() {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$var" of required type "Int!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$var" of required type "Int!" was not provided."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -1116,12 +1057,10 @@ mod integers {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$var" got invalid value. Expected "Int"."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$var" got invalid value. Expected "Int"."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
@ -1138,12 +1077,10 @@ mod integers {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$var" got invalid value. Expected "Int"."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$var" got invalid value. Expected "Int"."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
}
@ -1196,12 +1133,10 @@ mod floats {
assert_eq!(
error,
ValidationError(vec![
RuleError::new(
r#"Variable "$var" got invalid value. Expected "Float"."#,
&[SourcePosition::new(8, 0, 8)],
),
])
ValidationError(vec![RuleError::new(
r#"Variable "$var" got invalid value. Expected "Float"."#,
&[SourcePosition::new(8, 0, 8)],
)])
);
}
}

View file

@ -5,9 +5,9 @@ pub mod graphiql;
use serde::ser;
use serde::ser::SerializeMap;
use {GraphQLError, GraphQLType, RootNode, Value, Variables};
use ast::InputValue;
use executor::ExecutionError;
use {GraphQLError, GraphQLType, RootNode, Value, Variables};
/// The result of executing a query
pub trait ExecutionResponse: ser::Serialize {
@ -41,7 +41,8 @@ pub trait Executable {
#[derive(Deserialize, Clone, Serialize, PartialEq, Debug)]
pub struct GraphQLRequest {
query: String,
#[serde(rename = "operationName")] operation_name: Option<String>,
#[serde(rename = "operationName")]
operation_name: Option<String>,
variables: Option<InputValue>,
}
@ -166,22 +167,22 @@ impl<'a> ser::Serialize for GraphQLResponse<'a> {
{
match self.0 {
Ok((ref res, ref err)) => {
let mut map = try!(serializer.serialize_map(None));
let mut map = serializer.serialize_map(None)?;
try!(map.serialize_key("data"));
try!(map.serialize_value(res));
map.serialize_key("data")?;
map.serialize_value(res)?;
if !err.is_empty() {
try!(map.serialize_key("errors"));
try!(map.serialize_value(err));
map.serialize_key("errors")?;
map.serialize_value(err)?;
}
map.end()
}
Err(ref err) => {
let mut map = try!(serializer.serialize_map(Some(1)));
try!(map.serialize_key("errors"));
try!(map.serialize_value(err));
let mut map = serializer.serialize_map(Some(1))?;
map.serialize_key("errors")?;
map.serialize_value(err)?;
map.end()
}
}
@ -223,8 +224,8 @@ impl<'a> ser::Serialize for GraphQLBatchResponse<'a> {
#[cfg(any(test, feature = "expose-test-schema"))]
#[allow(missing_docs)]
pub mod tests {
use serde_json::Value as Json;
use serde_json;
use serde_json::Value as Json;
/// Normalized response content we expect to get back from
/// the http framework integration we are testing.

View file

@ -169,9 +169,9 @@ mod integration_test {
use chrono::Utc;
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
#[test]
fn test_serialization() {

View file

@ -1,35 +1,35 @@
use indexmap::IndexMap;
use serde::{de, ser};
use serde::ser::SerializeMap;
use serde::{de, ser};
use std::fmt;
use {GraphQLError, Value};
use ast::InputValue;
use executor::ExecutionError;
use parser::{ParseError, SourcePosition, Spanning};
use validation::RuleError;
use {GraphQLError, Value};
impl ser::Serialize for ExecutionError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
let mut map = try!(serializer.serialize_map(Some(4)));
let mut map = serializer.serialize_map(Some(4))?;
try!(map.serialize_key("message"));
try!(map.serialize_value(self.error().message()));
map.serialize_key("message")?;
map.serialize_value(self.error().message())?;
let locations = vec![self.location()];
try!(map.serialize_key("locations"));
try!(map.serialize_value(&locations));
map.serialize_key("locations")?;
map.serialize_value(&locations)?;
try!(map.serialize_key("path"));
try!(map.serialize_value(self.path()));
map.serialize_key("path")?;
map.serialize_value(self.path())?;
if !self.error().data().is_null() {
try!(map.serialize_key("data"));
try!(map.serialize_value(self.error().data()));
map.serialize_key("data")?;
map.serialize_value(self.error().data())?;
}
map.end()
@ -76,10 +76,15 @@ impl<'de> de::Deserialize<'de> for InputValue {
where
E: de::Error,
{
if value >= i32::min_value() as i64 && value <= i32::max_value() as i64 {
if value >= i64::from(i32::min_value()) && value <= i64::from(i32::max_value()) {
Ok(InputValue::int(value as i32))
} else {
Err(E::custom(format!("integer out of range")))
// Browser's JSON.stringify serialize all numbers having no
// fractional part as integers (no decimal point), so we
// must parse large integers as floating point otherwise
// we would error on transferring large floating point
// numbers.
Ok(InputValue::float(value as f64))
}
}
@ -90,7 +95,12 @@ impl<'de> de::Deserialize<'de> for InputValue {
if value <= i32::max_value() as u64 {
self.visit_i64(value as i64)
} else {
Err(E::custom(format!("integer out of range")))
// Browser's JSON.stringify serialize all numbers having no
// fractional part as integers (no decimal point), so we
// must parse large integers as floating point otherwise
// we would error on transferring large floating point
// numbers.
Ok(InputValue::float(value as f64))
}
}
@ -123,7 +133,7 @@ impl<'de> de::Deserialize<'de> for InputValue {
{
let mut values = Vec::new();
while let Some(el) = try!(visitor.next_element()) {
while let Some(el) = visitor.next_element()? {
values.push(el);
}
@ -136,7 +146,7 @@ impl<'de> de::Deserialize<'de> for InputValue {
{
let mut values: IndexMap<String, InputValue> = IndexMap::new();
while let Some((key, value)) = try!(visitor.next_entry()) {
while let Some((key, value)) = visitor.next_entry()? {
values.insert(key, value);
}
@ -155,7 +165,7 @@ impl ser::Serialize for InputValue {
{
match *self {
InputValue::Null | InputValue::Variable(_) => serializer.serialize_unit(),
InputValue::Int(v) => serializer.serialize_i64(v as i64),
InputValue::Int(v) => serializer.serialize_i64(i64::from(v)),
InputValue::Float(v) => serializer.serialize_f64(v),
InputValue::String(ref v) | InputValue::Enum(ref v) => serializer.serialize_str(v),
InputValue::Boolean(v) => serializer.serialize_bool(v),
@ -176,13 +186,13 @@ impl ser::Serialize for RuleError {
where
S: ser::Serializer,
{
let mut map = try!(serializer.serialize_map(Some(2)));
let mut map = serializer.serialize_map(Some(2))?;
try!(map.serialize_key("message"));
try!(map.serialize_value(self.message()));
map.serialize_key("message")?;
map.serialize_value(self.message())?;
try!(map.serialize_key("locations"));
try!(map.serialize_value(self.locations()));
map.serialize_key("locations")?;
map.serialize_value(self.locations())?;
map.end()
}
@ -193,15 +203,15 @@ impl ser::Serialize for SourcePosition {
where
S: ser::Serializer,
{
let mut map = try!(serializer.serialize_map(Some(2)));
let mut map = serializer.serialize_map(Some(2))?;
let line = self.line() + 1;
try!(map.serialize_key("line"));
try!(map.serialize_value(&line));
map.serialize_key("line")?;
map.serialize_value(&line)?;
let column = self.column() + 1;
try!(map.serialize_key("column"));
try!(map.serialize_value(&column));
map.serialize_key("column")?;
map.serialize_value(&column)?;
map.end()
}
@ -212,11 +222,11 @@ impl<'a> ser::Serialize for Spanning<ParseError<'a>> {
where
S: ser::Serializer,
{
let mut map = try!(serializer.serialize_map(Some(2)));
let mut map = serializer.serialize_map(Some(2))?;
let message = format!("{}", self.item);
try!(map.serialize_key("message"));
try!(map.serialize_value(&message));
map.serialize_key("message")?;
map.serialize_value(&message)?;
let mut location = IndexMap::new();
location.insert("line".to_owned(), self.start.line() + 1);
@ -224,8 +234,8 @@ impl<'a> ser::Serialize for Spanning<ParseError<'a>> {
let locations = vec![location];
try!(map.serialize_key("locations"));
try!(map.serialize_value(&locations));
map.serialize_key("locations")?;
map.serialize_value(&locations)?;
map.end()
}
@ -238,7 +248,7 @@ impl ser::Serialize for Value {
{
match *self {
Value::Null => serializer.serialize_unit(),
Value::Int(v) => serializer.serialize_i64(v as i64),
Value::Int(v) => serializer.serialize_i64(i64::from(v)),
Value::Float(v) => serializer.serialize_f64(v),
Value::String(ref v) => serializer.serialize_str(v),
Value::Boolean(v) => serializer.serialize_bool(v),
@ -247,3 +257,24 @@ impl ser::Serialize for Value {
}
}
}
#[cfg(test)]
mod tests {
use serde_json::from_str;
use ast::InputValue;
#[test]
fn int() {
assert_eq!(from_str::<InputValue>("1235").unwrap(),
InputValue::int(1235));
}
#[test]
fn float() {
assert_eq!(from_str::<InputValue>("2.0").unwrap(),
InputValue::float(2.0));
// large value without a decimal part is also float
assert_eq!(from_str::<InputValue>("123567890123").unwrap(),
InputValue::float(123567890123.0));
}
}

View file

@ -122,16 +122,16 @@ mod value;
#[macro_use]
mod macros;
mod ast;
pub mod parser;
mod types;
mod schema;
mod validation;
mod util;
mod executor;
pub mod parser;
mod schema;
mod types;
mod util;
mod validation;
// This needs to be public until docs have support for private modules:
// https://github.com/rust-lang/cargo/issues/1520
pub mod integrations;
pub mod http;
pub mod integrations;
// TODO: remove this alias export in 0.10. (breaking change)
pub use http::graphiql;
@ -146,18 +146,19 @@ mod executor_tests;
// Needs to be public because macros use it.
pub use util::to_camel_case;
use executor::execute_validated_query;
use parser::{parse_document_source, ParseError, Spanning};
use validation::{validate_input_values, visit_all_rules, ValidatorContext};
use executor::execute_validated_query;
pub use ast::{FromInputValue, InputValue, Selection, ToInputValue, Type};
pub use value::Value;
pub use types::base::{Arguments, GraphQLType, TypeKind};
pub use executor::{Context, ExecutionError, ExecutionResult, Executor, FieldError, FieldResult,
FromContext, IntoResolvable, Registry, Variables};
pub use validation::RuleError;
pub use types::scalars::{EmptyMutation, ID};
pub use executor::{Applies, LookAheadArgument, LookAheadSelection, LookAheadValue, LookAheadMethods};
pub use schema::model::RootNode;
pub use types::base::{Arguments, GraphQLType, TypeKind};
pub use types::scalars::{EmptyMutation, ID};
pub use validation::RuleError;
pub use value::Value;
pub use schema::meta;
@ -184,7 +185,7 @@ where
QueryT: GraphQLType<Context = CtxT>,
MutationT: GraphQLType<Context = CtxT>,
{
let document = try!(parse_document_source(document_source));
let document = parse_document_source(document_source)?;
{
let errors = validate_input_values(variables, &document, &root_node.schema);

View file

@ -57,7 +57,7 @@ macro_rules! graphql_scalar {
// and body for the from() method on FromInputValue.
(
@generate,
( $name:ty, $outname:tt, $descr:tt ),
( $name:ty, $outname:expr, $descr:tt ),
(
( $resolve_selfvar:ident, $resolve_body:block ),
( $fiv_arg:ident, $fiv_result:ty, $fiv_body:block )
@ -135,7 +135,7 @@ macro_rules! graphql_scalar {
// description: <description>
(
@parse,
( $name:ty, $outname:tt, $_ignored:tt ),
( $name:ty, $outname:expr, $_ignored:tt ),
$acc:tt,
description: $descr:tt $($rest:tt)*
) => {
@ -151,6 +151,6 @@ macro_rules! graphql_scalar {
// Entry point
// RustName { ... }
( $name:ty { $( $items:tt )* }) => {
graphql_scalar!( @parse, ( $name, (stringify!($name)), None ), ( None, None ), $($items)* );
graphql_scalar!( @parse, ( $name, stringify!($name), None ), ( None, None ), $($items)* );
};
}

View file

@ -1,7 +1,7 @@
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Root;
@ -192,7 +192,7 @@ fn introspect_field_exec_arg_and_more() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -225,7 +225,7 @@ fn introspect_field_single_arg() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -258,7 +258,7 @@ fn introspect_field_multi_args() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -284,7 +284,7 @@ fn introspect_field_multi_args() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -317,7 +317,7 @@ fn introspect_field_multi_args_trailing_comma() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -343,7 +343,7 @@ fn introspect_field_multi_args_trailing_comma() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -376,7 +376,7 @@ fn introspect_field_single_arg_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -409,7 +409,7 @@ fn introspect_field_multi_args_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -435,7 +435,7 @@ fn introspect_field_multi_args_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -468,7 +468,7 @@ fn introspect_field_multi_args_descr_trailing_comma() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -494,7 +494,7 @@ fn introspect_field_multi_args_descr_trailing_comma() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -520,7 +520,7 @@ fn introspect_field_arg_with_default() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -546,7 +546,7 @@ fn introspect_field_multi_args_with_default() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -565,7 +565,7 @@ fn introspect_field_multi_args_with_default() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -591,7 +591,7 @@ fn introspect_field_multi_args_with_default_trailing_comma() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -610,7 +610,7 @@ fn introspect_field_multi_args_with_default_trailing_comma() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -636,7 +636,7 @@ fn introspect_field_arg_with_default_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -662,7 +662,7 @@ fn introspect_field_multi_args_with_default_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -681,7 +681,7 @@ fn introspect_field_multi_args_with_default_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -707,7 +707,7 @@ fn introspect_field_multi_args_with_default_trailing_comma_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -726,7 +726,7 @@ fn introspect_field_multi_args_with_default_trailing_comma_descr() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});
@ -752,7 +752,7 @@ fn introspect_field_args_with_complex_default() {
),
),
].into_iter()
.collect()
.collect(),
))
);
@ -774,7 +774,7 @@ fn introspect_field_args_with_complex_default() {
),
),
].into_iter()
.collect()
.collect(),
))
);
});

View file

@ -1,10 +1,10 @@
use indexmap::IndexMap;
use value::Value;
use ast::InputValue;
use schema::model::RootNode;
use executor::FieldResult;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct Interface;
struct Root;

View file

@ -2,9 +2,9 @@ use indexmap::IndexMap;
use std::marker::PhantomData;
use ast::InputValue;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
/*
@ -184,7 +184,7 @@ fn introspect_custom_name() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -200,7 +200,7 @@ fn introspect_with_lifetime() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -216,7 +216,7 @@ fn introspect_with_generics() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -235,7 +235,7 @@ fn introspect_description_first() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -254,7 +254,7 @@ fn introspect_fields_first() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -273,7 +273,7 @@ fn introspect_interfaces_first() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -295,7 +295,7 @@ fn introspect_commas_with_trailing() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -314,7 +314,7 @@ fn introspect_commas_on_meta() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -336,7 +336,7 @@ fn introspect_resolvers_with_trailing_comma() {
fields.contains(&Value::object(
vec![("name", Value::string("simple"))]
.into_iter()
.collect()
.collect(),
))
);
});

View file

@ -1,6 +1,6 @@
mod scalar;
mod args;
mod field;
mod object;
mod interface;
mod object;
mod scalar;
mod union;

View file

@ -2,10 +2,10 @@ use indexmap::IndexMap;
use std::marker::PhantomData;
use ast::InputValue;
use value::Value;
use executor::{Context, FieldResult};
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use executor::{Context, FieldResult};
use value::Value;
/*
@ -250,15 +250,13 @@ fn introspect_description_first() {
);
assert_eq!(
object.get("interfaces"),
Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
Some(&Value::list(vec![Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
)]))
);
assert!(fields.contains(&graphql_value!({
@ -278,15 +276,13 @@ fn introspect_fields_first() {
);
assert_eq!(
object.get("interfaces"),
Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
Some(&Value::list(vec![Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
)]))
);
assert!(fields.contains(&graphql_value!({
@ -306,15 +302,13 @@ fn introspect_interfaces_first() {
);
assert_eq!(
object.get("interfaces"),
Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
Some(&Value::list(vec![Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
)]))
);
assert!(fields.contains(&graphql_value!({
@ -337,15 +331,13 @@ fn introspect_commas_with_trailing() {
);
assert_eq!(
object.get("interfaces"),
Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
Some(&Value::list(vec![Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
)]))
);
assert!(fields.contains(&graphql_value!({
@ -365,15 +357,13 @@ fn introspect_commas_on_meta() {
);
assert_eq!(
object.get("interfaces"),
Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
Some(&Value::list(vec![Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
)]))
);
assert!(fields.contains(&graphql_value!({

View file

@ -1,9 +1,9 @@
use indexmap::IndexMap;
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
struct DefaultName(i32);
struct OtherOrder(i32);

View file

@ -2,9 +2,9 @@ use indexmap::IndexMap;
use std::marker::PhantomData;
use ast::InputValue;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use value::Value;
/*
@ -162,7 +162,7 @@ fn introspect_custom_name() {
possible_types.contains(&Value::object(
vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -178,7 +178,7 @@ fn introspect_with_lifetime() {
possible_types.contains(&Value::object(
vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -194,7 +194,7 @@ fn introspect_with_generics() {
possible_types.contains(&Value::object(
vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -213,7 +213,7 @@ fn introspect_description_first() {
possible_types.contains(&Value::object(
vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -232,7 +232,7 @@ fn introspect_resolvers_first() {
possible_types.contains(&Value::object(
vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -254,7 +254,7 @@ fn introspect_commas_with_trailing() {
possible_types.contains(&Value::object(
vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
.collect(),
))
);
});
@ -276,7 +276,7 @@ fn introspect_resolvers_with_trailing_comma() {
possible_types.contains(&Value::object(
vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
.collect(),
))
);
});

View file

@ -4,14 +4,14 @@ use ast::{Arguments, Definition, Directive, Document, Field, Fragment, FragmentS
InlineFragment, InputValue, Operation, OperationType, Selection, Type,
VariableDefinition, VariableDefinitions};
use parser::value::parse_value_literal;
use parser::{Lexer, OptionParseResult, ParseError, ParseResult, Parser, Spanning, Token,
UnlocatedParseResult};
use parser::value::parse_value_literal;
#[doc(hidden)]
pub fn parse_document_source(s: &str) -> UnlocatedParseResult<Document> {
let mut lexer = Lexer::new(s);
let mut parser = try!(Parser::new(&mut lexer).map_err(|s| s.map(ParseError::LexerError)));
let mut parser = Parser::new(&mut lexer).map_err(|s| s.map(ParseError::LexerError))?;
parse_document(&mut parser)
}
@ -19,7 +19,7 @@ fn parse_document<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Docum
let mut defs = Vec::new();
loop {
defs.push(try!(parse_definition(parser)));
defs.push(parse_definition(parser)?);
if parser.peek().item == Token::EndOfFile {
return Ok(defs);
@ -29,19 +29,17 @@ fn parse_document<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Docum
fn parse_definition<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Definition<'a>> {
match parser.peek().item {
Token::CurlyOpen | Token::Name("query") | Token::Name("mutation") => Ok(
Definition::Operation(try!(parse_operation_definition(parser))),
),
Token::Name("fragment") => Ok(Definition::Fragment(try!(parse_fragment_definition(
parser
)))),
Token::CurlyOpen | Token::Name("query") | Token::Name("mutation") => {
Ok(Definition::Operation(parse_operation_definition(parser)?))
}
Token::Name("fragment") => Ok(Definition::Fragment(parse_fragment_definition(parser)?)),
_ => Err(parser.next()?.map(ParseError::UnexpectedToken)),
}
}
fn parse_operation_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Operation<'a>> {
if parser.peek().item == Token::CurlyOpen {
let selection_set = try!(parse_selection_set(parser));
let selection_set = parse_selection_set(parser)?;
Ok(Spanning::start_end(
&selection_set.start,
@ -56,14 +54,14 @@ fn parse_operation_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Op
))
} else {
let start_pos = parser.peek().start.clone();
let operation_type = try!(parse_operation_type(parser));
let operation_type = parse_operation_type(parser)?;
let name = match parser.peek().item {
Token::Name(_) => Some(try!(parser.expect_name())),
Token::Name(_) => Some(parser.expect_name()?),
_ => None,
};
let variable_definitions = try!(parse_variable_definitions(parser));
let directives = try!(parse_directives(parser));
let selection_set = try!(parse_selection_set(parser));
let variable_definitions = parse_variable_definitions(parser)?;
let directives = parse_directives(parser)?;
let selection_set = parse_selection_set(parser)?;
Ok(Spanning::start_end(
&start_pos,
@ -82,7 +80,7 @@ fn parse_operation_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Op
fn parse_fragment_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Fragment<'a>> {
let Spanning {
start: start_pos, ..
} = try!(parser.expect(&Token::Name("fragment")));
} = parser.expect(&Token::Name("fragment"))?;
let name = match parser.expect_name() {
Ok(n) => if n.item == "on" {
return Err(n.map(|_| ParseError::UnexpectedToken(Token::Name("on"))));
@ -92,10 +90,10 @@ fn parse_fragment_definition<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Fra
Err(e) => return Err(e),
};
try!(parser.expect(&Token::Name("on")));
let type_cond = try!(parser.expect_name());
let directives = try!(parse_directives(parser));
let selection_set = try!(parse_selection_set(parser));
parser.expect(&Token::Name("on"))?;
let type_cond = parser.expect_name()?;
let directives = parse_directives(parser)?;
let selection_set = parse_selection_set(parser)?;
Ok(Spanning::start_end(
&start_pos,
@ -113,7 +111,7 @@ fn parse_optional_selection_set<'a>(
parser: &mut Parser<'a>,
) -> OptionParseResult<'a, Vec<Selection<'a>>> {
if parser.peek().item == Token::CurlyOpen {
Ok(Some(try!(parse_selection_set(parser))))
Ok(Some(parse_selection_set(parser)?))
} else {
Ok(None)
}
@ -134,14 +132,14 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec
let Spanning {
start: ref start_pos,
..
} = try!(parser.expect(&Token::Ellipsis));
} = parser.expect(&Token::Ellipsis)?;
match parser.peek().item {
Token::Name("on") => {
parser.next()?;
let name = try!(parser.expect_name());
let directives = try!(parse_directives(parser));
let selection_set = try!(parse_selection_set(parser));
let name = parser.expect_name()?;
let directives = parse_directives(parser)?;
let selection_set = parse_selection_set(parser)?;
Ok(Selection::InlineFragment(Spanning::start_end(
&start_pos.clone(),
@ -154,7 +152,7 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec
)))
}
Token::CurlyOpen => {
let selection_set = try!(parse_selection_set(parser));
let selection_set = parse_selection_set(parser)?;
Ok(Selection::InlineFragment(Spanning::start_end(
&start_pos.clone(),
@ -167,8 +165,8 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec
)))
}
Token::Name(_) => {
let frag_name = try!(parser.expect_name());
let directives = try!(parse_directives(parser));
let frag_name = parser.expect_name()?;
let directives = parse_directives(parser)?;
Ok(Selection::FragmentSpread(Spanning::start_end(
&start_pos.clone(),
@ -183,8 +181,8 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec
)))
}
Token::At => {
let directives = try!(parse_directives(parser));
let selection_set = try!(parse_selection_set(parser));
let directives = parse_directives(parser)?;
let selection_set = parse_selection_set(parser)?;
Ok(Selection::InlineFragment(Spanning::start_end(
&start_pos.clone(),
@ -201,17 +199,17 @@ fn parse_fragment<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Selec
}
fn parse_field<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Field<'a>> {
let mut alias = Some(try!(parser.expect_name()));
let mut alias = Some(parser.expect_name()?);
let name = if try!(parser.skip(&Token::Colon)).is_some() {
try!(parser.expect_name())
let name = if parser.skip(&Token::Colon)?.is_some() {
parser.expect_name()?
} else {
alias.take().unwrap()
};
let arguments = try!(parse_arguments(parser));
let directives = try!(parse_directives(parser));
let selection_set = try!(parse_optional_selection_set(parser));
let arguments = parse_arguments(parser)?;
let directives = parse_directives(parser)?;
let selection_set = parse_optional_selection_set(parser)?;
Ok(Spanning::start_end(
&alias.as_ref().unwrap_or(&name).start.clone(),
@ -237,13 +235,11 @@ fn parse_arguments<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Argumen
Ok(None)
} else {
Ok(Some(
try!(parser.delimited_nonempty_list(
&Token::ParenOpen,
parse_argument,
&Token::ParenClose
)).map(|args| Arguments {
items: args.into_iter().map(|s| s.item).collect(),
}),
parser
.delimited_nonempty_list(&Token::ParenOpen, parse_argument, &Token::ParenClose)?
.map(|args| Arguments {
items: args.into_iter().map(|s| s.item).collect(),
}),
))
}
}
@ -251,9 +247,9 @@ fn parse_arguments<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Argumen
fn parse_argument<'a>(
parser: &mut Parser<'a>,
) -> ParseResult<'a, (Spanning<&'a str>, Spanning<InputValue>)> {
let name = try!(parser.expect_name());
try!(parser.expect(&Token::Colon));
let value = try!(parse_value_literal(parser, false));
let name = parser.expect_name()?;
parser.expect(&Token::Colon)?;
let value = parse_value_literal(parser, false)?;
Ok(Spanning::start_end(
&name.start.clone(),
@ -277,13 +273,15 @@ fn parse_variable_definitions<'a>(
Ok(None)
} else {
Ok(Some(
try!(parser.delimited_nonempty_list(
&Token::ParenOpen,
parse_variable_definition,
&Token::ParenClose
)).map(|defs| VariableDefinitions {
items: defs.into_iter().map(|s| s.item).collect(),
}),
parser
.delimited_nonempty_list(
&Token::ParenOpen,
parse_variable_definition,
&Token::ParenClose,
)?
.map(|defs| VariableDefinitions {
items: defs.into_iter().map(|s| s.item).collect(),
}),
))
}
}
@ -293,13 +291,13 @@ fn parse_variable_definition<'a>(
) -> ParseResult<'a, (Spanning<&'a str>, VariableDefinition<'a>)> {
let Spanning {
start: start_pos, ..
} = try!(parser.expect(&Token::Dollar));
let var_name = try!(parser.expect_name());
try!(parser.expect(&Token::Colon));
let var_type = try!(parse_type(parser));
} = parser.expect(&Token::Dollar)?;
let var_name = parser.expect_name()?;
parser.expect(&Token::Colon)?;
let var_type = parse_type(parser)?;
let default_value = if try!(parser.skip(&Token::Equals)).is_some() {
Some(try!(parse_value_literal(parser, true)))
let default_value = if parser.skip(&Token::Equals)?.is_some() {
Some(parse_value_literal(parser, true)?)
} else {
None
};
@ -328,7 +326,7 @@ fn parse_directives<'a>(
} else {
let mut items = Vec::new();
while parser.peek().item == Token::At {
items.push(try!(parse_directive(parser)));
items.push(parse_directive(parser)?);
}
Ok(Spanning::spanning(items))
@ -338,9 +336,9 @@ fn parse_directives<'a>(
fn parse_directive<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Directive<'a>> {
let Spanning {
start: start_pos, ..
} = try!(parser.expect(&Token::At));
let name = try!(parser.expect_name());
let arguments = try!(parse_arguments(parser));
} = parser.expect(&Token::At)?;
let name = parser.expect_name()?;
let arguments = parse_arguments(parser)?;
Ok(Spanning::start_end(
&start_pos,
@ -355,20 +353,20 @@ fn parse_directive<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Directive<'a>
pub fn parse_type<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, Type<'a>> {
let parsed_type = if let Some(Spanning {
start: start_pos, ..
}) = try!(parser.skip(&Token::BracketOpen))
}) = parser.skip(&Token::BracketOpen)?
{
let inner_type = try!(parse_type(parser));
let Spanning { end: end_pos, .. } = try!(parser.expect(&Token::BracketClose));
let inner_type = parse_type(parser)?;
let Spanning { end: end_pos, .. } = parser.expect(&Token::BracketClose)?;
Spanning::start_end(&start_pos, &end_pos, Type::List(Box::new(inner_type.item)))
} else {
try!(parser.expect_name()).map(|s| Type::Named(Cow::Borrowed(s)))
parser.expect_name()?.map(|s| Type::Named(Cow::Borrowed(s)))
};
Ok(match *parser.peek() {
Spanning {
item: Token::ExclamationMark,
..
} => try!(wrap_non_null(parser, parsed_type)),
} => wrap_non_null(parser, parsed_type)?,
_ => parsed_type,
})
}
@ -377,7 +375,7 @@ fn wrap_non_null<'a>(
parser: &mut Parser<'a>,
inner: Spanning<Type<'a>>,
) -> ParseResult<'a, Type<'a>> {
let Spanning { end: end_pos, .. } = try!(parser.expect(&Token::ExclamationMark));
let Spanning { end: end_pos, .. } = parser.expect(&Token::ExclamationMark)?;
let wrapped = match inner.item {
Type::Named(name) => Type::NonNullNamed(name),

View file

@ -1,8 +1,8 @@
use std::char;
use std::str::CharIndices;
use std::fmt;
use std::iter::{Iterator, Peekable};
use std::result::Result;
use std::fmt;
use std::str::CharIndices;
use parser::{SourcePosition, Spanning};
@ -160,10 +160,10 @@ impl<'a> Lexer<'a> {
let start_pos = self.position.clone();
for _ in 0..3 {
let (_, ch) = try!(self.next_char().ok_or(Spanning::zero_width(
let (_, ch) = self.next_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnexpectedEndOfFile
)));
LexerError::UnexpectedEndOfFile,
))?;
if ch != '.' {
return Err(Spanning::zero_width(
&start_pos,
@ -181,10 +181,10 @@ impl<'a> Lexer<'a> {
fn scan_name(&mut self) -> LexerResult<'a> {
let start_pos = self.position.clone();
let (start_idx, start_ch) = try!(self.next_char().ok_or(Spanning::zero_width(
let (start_idx, start_ch) = self.next_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnexpectedEndOfFile
)));
LexerError::UnexpectedEndOfFile,
))?;
assert!(is_name_start(start_ch));
let mut end_idx = start_idx;
@ -207,10 +207,10 @@ impl<'a> Lexer<'a> {
fn scan_string(&mut self) -> LexerResult<'a> {
let start_pos = self.position.clone();
let (_, start_ch) = try!(self.next_char().ok_or(Spanning::zero_width(
let (_, start_ch) = self.next_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnexpectedEndOfFile
)));
LexerError::UnexpectedEndOfFile,
))?;
assert!(start_ch == '"');
let mut acc = String::new();
@ -262,7 +262,7 @@ impl<'a> Lexer<'a> {
Some((_, 'u')) => {
let start_pos = self.position.clone();
self.next_char();
acc.push(try!(self.scan_escaped_unicode(&start_pos)));
acc.push(self.scan_escaped_unicode(&start_pos)?);
}
Some((_, ch)) => {
let mut s = String::from("\\");
@ -314,18 +314,18 @@ impl<'a> Lexer<'a> {
&mut self,
start_pos: &SourcePosition,
) -> Result<char, Spanning<LexerError>> {
let (start_idx, _) = try!(self.peek_char().ok_or(Spanning::zero_width(
let (start_idx, _) = self.peek_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnterminatedString
)));
LexerError::UnterminatedString,
))?;
let mut end_idx = start_idx;
let mut len = 0;
for _ in 0..4 {
let (idx, ch) = try!(self.next_char().ok_or(Spanning::zero_width(
let (idx, ch) = self.next_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnterminatedString
)));
LexerError::UnterminatedString,
))?;
if !ch.is_alphanumeric() {
break;
@ -344,12 +344,12 @@ impl<'a> Lexer<'a> {
));
}
let code_point = try!(
u32::from_str_radix(escape, 16).map_err(|_| Spanning::zero_width(
let code_point = u32::from_str_radix(escape, 16).map_err(|_| {
Spanning::zero_width(
start_pos,
LexerError::UnknownEscapeSequence("\\u".to_owned() + escape),
))
);
)
})?;
char::from_u32(code_point).ok_or_else(|| {
Spanning::zero_width(
@ -361,14 +361,14 @@ impl<'a> Lexer<'a> {
fn scan_number(&mut self) -> LexerResult<'a> {
let start_pos = self.position.clone();
let int_part = try!(self.scan_integer_part());
let int_part = self.scan_integer_part()?;
let mut frac_part = None;
let mut exp_part = None;
if let Some((_, '.')) = self.peek_char() {
self.next_char();
frac_part = Some(try!(self.scan_digits()));
frac_part = Some(self.scan_digits()?);
}
if let Some((_, ch)) = self.peek_char() {
@ -385,12 +385,12 @@ impl<'a> Lexer<'a> {
self.next_char();
}
}
exp_part = Some(if is_negative { -1 } else { 1 } * try!(self.scan_digits()));
exp_part = Some(if is_negative { -1 } else { 1 } * self.scan_digits()?);
}
}
let mantissa = frac_part
.map(|f| f as f64)
.map(|f| f64::from(f))
.map(|frac| {
if frac > 0f64 {
frac / 10f64.powf(frac.log10().floor() + 1f64)
@ -400,26 +400,28 @@ impl<'a> Lexer<'a> {
})
.map(|m| if int_part < 0 { -m } else { m });
let exp = exp_part.map(|e| e as f64).map(|e| 10f64.powf(e));
let exp = exp_part.map(|e| f64::from(e)).map(|e| 10f64.powf(e));
Ok(Spanning::start_end(
&start_pos,
&self.position,
match (mantissa, exp) {
(None, None) => Token::Int(int_part),
(None, Some(exp)) => Token::Float((int_part as f64) * exp),
(Some(mantissa), None) => Token::Float((int_part as f64) + mantissa),
(Some(mantissa), Some(exp)) => Token::Float(((int_part as f64) + mantissa) * exp),
(None, Some(exp)) => Token::Float((f64::from(int_part)) * exp),
(Some(mantissa), None) => Token::Float((f64::from(int_part)) + mantissa),
(Some(mantissa), Some(exp)) => {
Token::Float(((f64::from(int_part)) + mantissa) * exp)
}
},
))
}
fn scan_integer_part(&mut self) -> Result<i32, Spanning<LexerError>> {
let is_negative = {
let (_, init_ch) = try!(self.peek_char().ok_or(Spanning::zero_width(
let (_, init_ch) = self.peek_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnexpectedEndOfFile
)));
LexerError::UnexpectedEndOfFile,
))?;
if init_ch == '-' {
self.next_char();
@ -429,10 +431,10 @@ impl<'a> Lexer<'a> {
}
};
let (_, ch) = try!(self.peek_char().ok_or(Spanning::zero_width(
let (_, ch) = self.peek_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnexpectedEndOfFile
)));
LexerError::UnexpectedEndOfFile,
))?;
if ch == '0' {
self.next_char();
@ -445,16 +447,16 @@ impl<'a> Lexer<'a> {
_ => Ok(0),
}
} else {
Ok(try!(self.scan_digits()) * if is_negative { -1 } else { 1 })
Ok(self.scan_digits()? * if is_negative { -1 } else { 1 })
}
}
fn scan_digits(&mut self) -> Result<i32, Spanning<LexerError>> {
let start_pos = self.position.clone();
let (start_idx, ch) = try!(self.peek_char().ok_or(Spanning::zero_width(
let (start_idx, ch) = self.peek_char().ok_or(Spanning::zero_width(
&self.position,
LexerError::UnexpectedEndOfFile
)));
LexerError::UnexpectedEndOfFile,
))?;
let mut end_idx = start_idx;
if !ch.is_digit(10) {

View file

@ -1,16 +1,16 @@
//! Query parser and language utilities
mod utils;
mod document;
mod lexer;
mod parser;
mod utils;
mod value;
mod document;
#[cfg(test)]
mod tests;
pub use self::document::parse_document_source;
pub use self::parser::{OptionParseResult, ParseError, ParseResult, Parser, UnlocatedParseResult};
pub use self::lexer::{Lexer, LexerError, Token};
pub use self::parser::{OptionParseResult, ParseError, ParseResult, Parser, UnlocatedParseResult};
pub use self::utils::{SourcePosition, Spanning};

View file

@ -1,5 +1,5 @@
use std::result::Result;
use std::fmt;
use std::result::Result;
use parser::{Lexer, LexerError, Spanning, Token};
@ -103,15 +103,15 @@ impl<'a> Parser<'a> {
{
let Spanning {
start: start_pos, ..
} = try!(self.expect(opening));
} = self.expect(opening)?;
let mut items = Vec::new();
loop {
if let Some(Spanning { end: end_pos, .. }) = try!(self.skip(closing)) {
if let Some(Spanning { end: end_pos, .. }) = self.skip(closing)? {
return Ok(Spanning::start_end(&start_pos, &end_pos, items));
}
items.push(try!(parser(self)));
items.push(parser(self)?);
}
}
@ -128,13 +128,13 @@ impl<'a> Parser<'a> {
{
let Spanning {
start: start_pos, ..
} = try!(self.expect(opening));
} = self.expect(opening)?;
let mut items = Vec::new();
loop {
items.push(try!(parser(self)));
items.push(parser(self)?);
if let Some(Spanning { end: end_pos, .. }) = try!(self.skip(closing)) {
if let Some(Spanning { end: end_pos, .. }) = self.skip(closing)? {
return Ok(Spanning::start_end(&start_pos, &end_pos, items));
}
}
@ -153,13 +153,13 @@ impl<'a> Parser<'a> {
{
let Spanning {
start: start_pos, ..
} = try!(self.expect(opening));
} = self.expect(opening)?;
let mut items = Vec::new();
loop {
items.push(try!(parser(self)));
items.push(parser(self)?);
if let Some(Spanning { end: end_pos, .. }) = try!(self.skip(closing)) {
if let Some(Spanning { end: end_pos, .. }) = self.skip(closing)? {
return Ok(Spanning::start_end(&start_pos, &end_pos, items));
}
}

View file

@ -1,6 +1,6 @@
use ast::{Arguments, Definition, Document, Field, InputValue, Operation, OperationType, Selection};
use parser::{ParseError, SourcePosition, Spanning, Token};
use parser::document::parse_document_source;
use parser::{ParseError, SourcePosition, Spanning, Token};
fn parse_document(s: &str) -> Document {
parse_document_source(s).expect(&format!("Parse error on input {:#?}", s))
@ -26,85 +26,79 @@ fn simple_ast() {
}
"#
),
vec![
Definition::Operation(Spanning::start_end(
&SourcePosition::new(13, 1, 12),
&SourcePosition::new(124, 6, 13),
Operation {
operation_type: OperationType::Query,
name: None,
variable_definitions: None,
directives: None,
selection_set: vec![
Selection::Field(Spanning::start_end(
vec![Definition::Operation(Spanning::start_end(
&SourcePosition::new(13, 1, 12),
&SourcePosition::new(124, 6, 13),
Operation {
operation_type: OperationType::Query,
name: None,
variable_definitions: None,
directives: None,
selection_set: vec![Selection::Field(Spanning::start_end(
&SourcePosition::new(31, 2, 16),
&SourcePosition::new(110, 5, 17),
Field {
alias: None,
name: Spanning::start_end(
&SourcePosition::new(31, 2, 16),
&SourcePosition::new(110, 5, 17),
Field {
alias: None,
name: Spanning::start_end(
&SourcePosition::new(31, 2, 16),
&SourcePosition::new(35, 2, 20),
"node",
),
arguments: Some(Spanning::start_end(
&SourcePosition::new(35, 2, 20),
&SourcePosition::new(42, 2, 27),
Arguments {
items: vec![
(
Spanning::start_end(
&SourcePosition::new(36, 2, 21),
&SourcePosition::new(38, 2, 23),
"id",
),
Spanning::start_end(
&SourcePosition::new(40, 2, 25),
&SourcePosition::new(41, 2, 26),
InputValue::int(4),
),
),
],
},
)),
directives: None,
selection_set: Some(vec![
Selection::Field(Spanning::start_end(
&SourcePosition::new(65, 3, 20),
&SourcePosition::new(67, 3, 22),
Field {
alias: None,
name: Spanning::start_end(
&SourcePosition::new(65, 3, 20),
&SourcePosition::new(67, 3, 22),
"id",
),
arguments: None,
directives: None,
selection_set: None,
},
)),
Selection::Field(Spanning::start_end(
&SourcePosition::new(88, 4, 20),
&SourcePosition::new(92, 4, 24),
Field {
alias: None,
name: Spanning::start_end(
&SourcePosition::new(88, 4, 20),
&SourcePosition::new(92, 4, 24),
"name",
),
arguments: None,
directives: None,
selection_set: None,
},
)),
]),
&SourcePosition::new(35, 2, 20),
"node",
),
arguments: Some(Spanning::start_end(
&SourcePosition::new(35, 2, 20),
&SourcePosition::new(42, 2, 27),
Arguments {
items: vec![(
Spanning::start_end(
&SourcePosition::new(36, 2, 21),
&SourcePosition::new(38, 2, 23),
"id",
),
Spanning::start_end(
&SourcePosition::new(40, 2, 25),
&SourcePosition::new(41, 2, 26),
InputValue::int(4),
),
)],
},
)),
],
},
)),
]
directives: None,
selection_set: Some(vec![
Selection::Field(Spanning::start_end(
&SourcePosition::new(65, 3, 20),
&SourcePosition::new(67, 3, 22),
Field {
alias: None,
name: Spanning::start_end(
&SourcePosition::new(65, 3, 20),
&SourcePosition::new(67, 3, 22),
"id",
),
arguments: None,
directives: None,
selection_set: None,
},
)),
Selection::Field(Spanning::start_end(
&SourcePosition::new(88, 4, 20),
&SourcePosition::new(92, 4, 24),
Field {
alias: None,
name: Spanning::start_end(
&SourcePosition::new(88, 4, 20),
&SourcePosition::new(92, 4, 24),
"name",
),
arguments: None,
directives: None,
selection_set: None,
},
)),
]),
},
))],
},
))]
)
}

View file

@ -50,9 +50,10 @@ fn tokenize_error(s: &str) -> Spanning<LexerError> {
fn empty_source() {
assert_eq!(
tokenize_to_vec(""),
vec![
Spanning::zero_width(&SourcePosition::new_origin(), Token::EndOfFile),
]
vec![Spanning::zero_width(
&SourcePosition::new_origin(),
Token::EndOfFile,
)]
);
}

View file

@ -1,8 +1,8 @@
use indexmap::IndexMap;
use ast::InputValue;
use parser::{Lexer, Parser, SourcePosition, Spanning};
use parser::value::parse_value_literal;
use parser::{Lexer, Parser, SourcePosition, Spanning};
fn parse_value(s: &str) -> Spanning<InputValue> {
let mut lexer = Lexer::new(s);
@ -142,20 +142,18 @@ fn input_value_literals() {
Spanning::start_end(
&SourcePosition::new(18, 0, 18),
&SourcePosition::new(30, 0, 30),
InputValue::parsed_object(vec![
(
Spanning::start_end(
&SourcePosition::new(19, 0, 19),
&SourcePosition::new(22, 0, 22),
"foo".to_owned(),
),
Spanning::start_end(
&SourcePosition::new(24, 0, 24),
&SourcePosition::new(29, 0, 29),
InputValue::string("bar"),
),
InputValue::parsed_object(vec![(
Spanning::start_end(
&SourcePosition::new(19, 0, 19),
&SourcePosition::new(22, 0, 22),
"foo".to_owned(),
),
]),
Spanning::start_end(
&SourcePosition::new(24, 0, 24),
&SourcePosition::new(29, 0, 29),
InputValue::string("bar"),
),
)]),
),
),
])

View file

@ -63,33 +63,37 @@ pub fn parse_value_literal<'a>(
}
fn parse_list_literal<'a>(parser: &mut Parser<'a>, is_const: bool) -> ParseResult<'a, InputValue> {
Ok(try!(parser.delimited_list(
&Token::BracketOpen,
|p| parse_value_literal(p, is_const),
&Token::BracketClose
)).map(InputValue::parsed_list))
Ok(parser
.delimited_list(
&Token::BracketOpen,
|p| parse_value_literal(p, is_const),
&Token::BracketClose,
)?
.map(InputValue::parsed_list))
}
fn parse_object_literal<'a>(
parser: &mut Parser<'a>,
is_const: bool,
) -> ParseResult<'a, InputValue> {
Ok(try!(parser.delimited_list(
&Token::CurlyOpen,
|p| parse_object_field(p, is_const),
&Token::CurlyClose
)).map(|items| InputValue::parsed_object(items.into_iter().map(|s| s.item).collect())))
Ok(parser
.delimited_list(
&Token::CurlyOpen,
|p| parse_object_field(p, is_const),
&Token::CurlyClose,
)?
.map(|items| InputValue::parsed_object(items.into_iter().map(|s| s.item).collect())))
}
fn parse_object_field<'a>(
parser: &mut Parser<'a>,
is_const: bool,
) -> ParseResult<'a, (Spanning<String>, Spanning<InputValue>)> {
let key = try!(parser.expect_name());
let key = parser.expect_name()?;
try!(parser.expect(&Token::Colon));
parser.expect(&Token::Colon)?;
let value = try!(parse_value_literal(parser, is_const));
let value = parse_value_literal(parser, is_const)?;
Ok(Spanning::start_end(
&key.start.clone(),
@ -101,12 +105,12 @@ fn parse_object_field<'a>(
fn parse_variable_literal<'a>(parser: &mut Parser<'a>) -> ParseResult<'a, InputValue> {
let Spanning {
start: start_pos, ..
} = try!(parser.expect(&Token::Dollar));
} = parser.expect(&Token::Dollar)?;
let Spanning {
item: name,
end: end_pos,
..
} = try!(parser.expect_name());
} = parser.expect_name()?;
Ok(Spanning::start_end(
&start_pos,

View file

@ -1,4 +1,4 @@
//! Types used to describe a GraphQL schema
//! Types used to describe a `GraphQL` schema
use std::borrow::Cow;
use std::fmt;
@ -8,62 +8,85 @@ use types::base::TypeKind;
/// Scalar type metadata
pub struct ScalarMeta<'a> {
#[doc(hidden)] pub name: Cow<'a, str>,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
#[doc(hidden)]
pub name: Cow<'a, str>,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
}
/// List type metadata
#[derive(Debug)]
pub struct ListMeta<'a> {
#[doc(hidden)] pub of_type: Type<'a>,
#[doc(hidden)]
pub of_type: Type<'a>,
}
/// Nullable type metadata
#[derive(Debug)]
pub struct NullableMeta<'a> {
#[doc(hidden)] pub of_type: Type<'a>,
#[doc(hidden)]
pub of_type: Type<'a>,
}
/// Object type metadata
#[derive(Debug)]
pub struct ObjectMeta<'a> {
#[doc(hidden)] pub name: Cow<'a, str>,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub fields: Vec<Field<'a>>,
#[doc(hidden)] pub interface_names: Vec<String>,
#[doc(hidden)]
pub name: Cow<'a, str>,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub fields: Vec<Field<'a>>,
#[doc(hidden)]
pub interface_names: Vec<String>,
}
/// Enum type metadata
pub struct EnumMeta<'a> {
#[doc(hidden)] pub name: Cow<'a, str>,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub values: Vec<EnumValue>,
#[doc(hidden)] pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
#[doc(hidden)]
pub name: Cow<'a, str>,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub values: Vec<EnumValue>,
#[doc(hidden)]
pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
}
/// Interface type metadata
#[derive(Debug)]
pub struct InterfaceMeta<'a> {
#[doc(hidden)] pub name: Cow<'a, str>,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub fields: Vec<Field<'a>>,
#[doc(hidden)]
pub name: Cow<'a, str>,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub fields: Vec<Field<'a>>,
}
/// Union type metadata
#[derive(Debug)]
pub struct UnionMeta<'a> {
#[doc(hidden)] pub name: Cow<'a, str>,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub of_type_names: Vec<String>,
#[doc(hidden)]
pub name: Cow<'a, str>,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub of_type_names: Vec<String>,
}
/// Input object metadata
pub struct InputObjectMeta<'a> {
#[doc(hidden)] pub name: Cow<'a, str>,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub input_fields: Vec<Argument<'a>>,
#[doc(hidden)] pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
#[doc(hidden)]
pub name: Cow<'a, str>,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub input_fields: Vec<Argument<'a>>,
#[doc(hidden)]
pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
}
/// A placeholder for not-yet-registered types
@ -72,40 +95,59 @@ pub struct InputObjectMeta<'a> {
/// is inserted into a registry to indicate existence.
#[derive(Debug)]
pub struct PlaceholderMeta<'a> {
#[doc(hidden)] pub of_type: Type<'a>,
#[doc(hidden)]
pub of_type: Type<'a>,
}
/// Generic type metadata
#[derive(Debug)]
pub enum MetaType<'a> {
#[doc(hidden)] Scalar(ScalarMeta<'a>),
#[doc(hidden)] List(ListMeta<'a>),
#[doc(hidden)] Nullable(NullableMeta<'a>),
#[doc(hidden)] Object(ObjectMeta<'a>),
#[doc(hidden)] Enum(EnumMeta<'a>),
#[doc(hidden)] Interface(InterfaceMeta<'a>),
#[doc(hidden)] Union(UnionMeta<'a>),
#[doc(hidden)] InputObject(InputObjectMeta<'a>),
#[doc(hidden)] Placeholder(PlaceholderMeta<'a>),
#[doc(hidden)]
Scalar(ScalarMeta<'a>),
#[doc(hidden)]
List(ListMeta<'a>),
#[doc(hidden)]
Nullable(NullableMeta<'a>),
#[doc(hidden)]
Object(ObjectMeta<'a>),
#[doc(hidden)]
Enum(EnumMeta<'a>),
#[doc(hidden)]
Interface(InterfaceMeta<'a>),
#[doc(hidden)]
Union(UnionMeta<'a>),
#[doc(hidden)]
InputObject(InputObjectMeta<'a>),
#[doc(hidden)]
Placeholder(PlaceholderMeta<'a>),
}
/// Metadata for a field
#[derive(Debug, Clone)]
pub struct Field<'a> {
#[doc(hidden)] pub name: String,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub arguments: Option<Vec<Argument<'a>>>,
#[doc(hidden)] pub field_type: Type<'a>,
#[doc(hidden)] pub deprecation_reason: Option<String>,
#[doc(hidden)]
pub name: String,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub arguments: Option<Vec<Argument<'a>>>,
#[doc(hidden)]
pub field_type: Type<'a>,
#[doc(hidden)]
pub deprecation_reason: Option<String>,
}
/// Metadata for an argument to a field
#[derive(Debug, Clone)]
pub struct Argument<'a> {
#[doc(hidden)] pub name: String,
#[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] pub arg_type: Type<'a>,
#[doc(hidden)] pub default_value: Option<InputValue>,
#[doc(hidden)]
pub name: String,
#[doc(hidden)]
pub description: Option<String>,
#[doc(hidden)]
pub arg_type: Type<'a>,
#[doc(hidden)]
pub default_value: Option<InputValue>,
}
/// Metadata for a single value in an enum

View file

@ -1,3 +1,3 @@
pub mod meta;
pub mod model;
pub mod schema;
pub mod meta;

View file

@ -2,22 +2,27 @@ use std::fmt;
use fnv::FnvHashMap;
use ast::Type;
use executor::{Context, Registry};
use schema::meta::{Argument, InterfaceMeta, MetaType, ObjectMeta, PlaceholderMeta, UnionMeta};
use types::base::GraphQLType;
use types::name::Name;
use executor::{Context, Registry};
use ast::Type;
use schema::meta::{Argument, InterfaceMeta, MetaType, ObjectMeta, PlaceholderMeta, UnionMeta};
/// Root query node of a schema
///
/// This brings the mutation and query types together, and provides the
/// predefined metadata fields.
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>,
#[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>,
}
/// Metadata for a schema
@ -50,9 +55,12 @@ pub enum DirectiveLocation {
Query,
Mutation,
Field,
#[graphql(name = "FRAGMENT_DEFINITION")] FragmentDefinition,
#[graphql(name = "FRAGMENT_SPREAD")] FragmentSpread,
#[graphql(name = "INLINE_SPREAD")] InlineFragment,
#[graphql(name = "FRAGMENT_DEFINITION")]
FragmentDefinition,
#[graphql(name = "FRAGMENT_SPREAD")]
FragmentSpread,
#[graphql(name = "INLINE_SPREAD")]
InlineFragment,
}
impl<'a, QueryT, MutationT> RootNode<'a, QueryT, MutationT>

View file

@ -1,5 +1,5 @@
use types::base::{Arguments, GraphQLType, TypeKind};
use executor::{ExecutionResult, Executor, Registry};
use types::base::{Arguments, GraphQLType, TypeKind};
use schema::meta::{Argument, EnumMeta, EnumValue, Field, InputObjectMeta, InterfaceMeta, MetaType,
ObjectMeta, UnionMeta};

View file

@ -1,10 +1,10 @@
use std::collections::HashSet;
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use tests::model::Database;
use types::scalars::EmptyMutation;
use value::Value;
#[test]
fn test_query_type_name() {
@ -23,24 +23,18 @@ fn test_query_type_name() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"__schema",
Value::object(
vec![
(
"queryType",
Value::object(
vec![("name", Value::string("Query"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
vec![(
"__schema",
Value::object(
vec![(
"queryType",
Value::object(
vec![("name", Value::string("Query"))].into_iter().collect(),
),
)].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -63,12 +57,10 @@ fn test_specific_type_name() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"__type",
Value::object(vec![("name", Value::string("Droid"))].into_iter().collect()),
),
].into_iter()
vec![(
"__type",
Value::object(vec![("name", Value::string("Droid"))].into_iter().collect()),
)].into_iter()
.collect()
),
vec![]
@ -93,18 +85,16 @@ fn test_specific_object_type_name_and_kind() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"__type",
Value::object(
vec![
("name", Value::string("Droid")),
("kind", Value::string("OBJECT")),
].into_iter()
.collect(),
),
vec![(
"__type",
Value::object(
vec![
("name", Value::string("Droid")),
("kind", Value::string("OBJECT")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -129,18 +119,16 @@ fn test_specific_interface_type_name_and_kind() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"__type",
Value::object(
vec![
("name", Value::string("Character")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
vec![(
"__type",
Value::object(
vec![
("name", Value::string("Character")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -165,23 +153,19 @@ fn test_documentation() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"__type",
Value::object(
vec![
("name", Value::string("Droid")),
(
"description",
Value::string(
"A mechanical creature in the Star Wars universe.",
),
),
].into_iter()
.collect(),
),
vec![(
"__type",
Value::object(
vec![
("name", Value::string("Droid")),
(
"description",
Value::string("A mechanical creature in the Star Wars universe."),
),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]

View file

@ -1,10 +1,10 @@
//! Library tests and fixtures
pub mod model;
mod schema;
#[cfg(test)]
mod query_tests;
#[cfg(test)]
mod introspection_tests;
pub mod model;
#[cfg(test)]
mod query_tests;
mod schema;
#[cfg(test)]
mod type_info_tests;

View file

@ -5,7 +5,8 @@ use std::collections::HashMap;
#[derive(GraphQLEnum, Copy, Clone, Eq, PartialEq, Debug)]
#[graphql(_internal)]
pub enum Episode {
#[graphql(name = "NEW_HOPE")] NewHope,
#[graphql(name = "NEW_HOPE")]
NewHope,
Empire,
Jedi,
}

View file

@ -1,9 +1,9 @@
use ast::InputValue;
use executor::Variables;
use value::Value;
use schema::model::RootNode;
use types::scalars::EmptyMutation;
use tests::model::Database;
use types::scalars::EmptyMutation;
use value::Value;
#[test]
fn test_hero_name() {
@ -20,12 +20,10 @@ fn test_hero_name() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"hero",
Value::object(vec![("name", Value::string("R2-D2"))].into_iter().collect()),
),
].into_iter()
vec![(
"hero",
Value::object(vec![("name", Value::string("R2-D2"))].into_iter().collect()),
)].into_iter()
.collect()
),
vec![]
@ -49,18 +47,16 @@ fn test_hero_field_order() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"hero",
Value::object(
vec![
("id", Value::string("2001")),
("name", Value::string("R2-D2")),
].into_iter()
.collect(),
),
vec![(
"hero",
Value::object(
vec![
("id", Value::string("2001")),
("name", Value::string("R2-D2")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -78,18 +74,16 @@ fn test_hero_field_order() {
::execute(doc_reversed, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"hero",
Value::object(
vec![
("name", Value::string("R2-D2")),
("id", Value::string("2001")),
].into_iter()
.collect(),
),
vec![(
"hero",
Value::object(
vec![
("name", Value::string("R2-D2")),
("id", Value::string("2001")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -116,38 +110,36 @@ fn test_hero_name_and_friends() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"hero",
Value::object(
vec![
("id", Value::string("2001")),
("name", Value::string("R2-D2")),
(
"friends",
Value::list(vec![
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("Han Solo"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("Leia Organa"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
vec![(
"hero",
Value::object(
vec![
("id", Value::string("2001")),
("name", Value::string("R2-D2")),
(
"friends",
Value::list(vec![
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("Han Solo"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("Leia Organa"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -178,153 +170,141 @@ fn test_hero_name_and_friends_and_friends_of_friends() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"hero",
Value::object(
vec![
("id", Value::string("2001")),
("name", Value::string("R2-D2")),
(
"friends",
Value::list(vec![
Value::object(
vec![
("name", Value::string("Luke Skywalker")),
(
"appearsIn",
Value::list(vec![
Value::string("NEW_HOPE"),
Value::string("EMPIRE"),
Value::string("JEDI"),
]),
),
(
"friends",
Value::list(vec![
Value::object(
vec![
("name", Value::string("Han Solo")),
].into_iter()
.collect(),
),
Value::object(
vec![
(
"name",
Value::string("Leia Organa"),
),
].into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("C-3PO"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
Value::object(
vec![
("name", Value::string("Han Solo")),
(
"appearsIn",
Value::list(vec![
Value::string("NEW_HOPE"),
Value::string("EMPIRE"),
Value::string("JEDI"),
]),
),
(
"friends",
Value::list(vec![
Value::object(
vec![
(
"name",
Value::string("Luke Skywalker"),
),
].into_iter()
.collect(),
),
Value::object(
vec![
(
"name",
Value::string("Leia Organa"),
),
].into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
Value::object(
vec![
("name", Value::string("Leia Organa")),
(
"appearsIn",
Value::list(vec![
Value::string("NEW_HOPE"),
Value::string("EMPIRE"),
Value::string("JEDI"),
]),
),
(
"friends",
Value::list(vec![
Value::object(
vec![
(
"name",
Value::string("Luke Skywalker"),
),
].into_iter()
.collect(),
),
Value::object(
vec![
("name", Value::string("Han Solo")),
].into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("C-3PO"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
vec![(
"hero",
Value::object(
vec![
("id", Value::string("2001")),
("name", Value::string("R2-D2")),
(
"friends",
Value::list(vec![
Value::object(
vec![
("name", Value::string("Luke Skywalker")),
(
"appearsIn",
Value::list(vec![
Value::string("NEW_HOPE"),
Value::string("EMPIRE"),
Value::string("JEDI"),
]),
),
(
"friends",
Value::list(vec![
Value::object(
vec![("name", Value::string("Han Solo"))]
.into_iter()
.collect(),
),
Value::object(
vec![(
"name",
Value::string("Leia Organa"),
)].into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("C-3PO"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
Value::object(
vec![
("name", Value::string("Han Solo")),
(
"appearsIn",
Value::list(vec![
Value::string("NEW_HOPE"),
Value::string("EMPIRE"),
Value::string("JEDI"),
]),
),
(
"friends",
Value::list(vec![
Value::object(
vec![(
"name",
Value::string("Luke Skywalker"),
)].into_iter()
.collect(),
),
Value::object(
vec![(
"name",
Value::string("Leia Organa"),
)].into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
Value::object(
vec![
("name", Value::string("Leia Organa")),
(
"appearsIn",
Value::list(vec![
Value::string("NEW_HOPE"),
Value::string("EMPIRE"),
Value::string("JEDI"),
]),
),
(
"friends",
Value::list(vec![
Value::object(
vec![(
"name",
Value::string("Luke Skywalker"),
)].into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("Han Solo"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("C-3PO"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))]
.into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -342,16 +322,14 @@ fn test_query_name() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"human",
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
vec![(
"human",
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -369,16 +347,14 @@ fn test_query_alias_single() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"luke",
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
vec![(
"luke",
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -487,16 +463,14 @@ fn test_query_name_variable() {
::execute(doc, None, &schema, &vars, &database),
Ok((
Value::object(
vec![
(
"human",
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
vec![(
"human",
Value::object(
vec![("name", Value::string("Luke Skywalker"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -533,41 +507,33 @@ fn test_query_friends_names() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"human",
Value::object(
vec![
(
"friends",
Value::list(vec![
Value::object(
vec![("name", Value::string("Han Solo"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("Leia Organa"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("C-3PO"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))]
.into_iter()
.collect(),
),
]),
vec![(
"human",
Value::object(
vec![(
"friends",
Value::list(vec![
Value::object(
vec![("name", Value::string("Han Solo"))]
.into_iter()
.collect(),
),
].into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("Leia Organa"))]
.into_iter()
.collect(),
),
Value::object(
vec![("name", Value::string("C-3PO"))].into_iter().collect(),
),
Value::object(
vec![("name", Value::string("R2-D2"))].into_iter().collect(),
),
]),
)].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -596,19 +562,17 @@ fn test_query_inline_fragments_droid() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"hero",
Value::object(
vec![
("name", Value::string("R2-D2")),
("__typename", Value::string("Droid")),
("primaryFunction", Value::string("Astromech")),
].into_iter()
.collect(),
),
vec![(
"hero",
Value::object(
vec![
("name", Value::string("R2-D2")),
("__typename", Value::string("Droid")),
("primaryFunction", Value::string("Astromech")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -633,18 +597,16 @@ fn test_query_inline_fragments_human() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"hero",
Value::object(
vec![
("name", Value::string("Luke Skywalker")),
("__typename", Value::string("Human")),
].into_iter()
.collect(),
),
vec![(
"hero",
Value::object(
vec![
("name", Value::string("Luke Skywalker")),
("__typename", Value::string("Human")),
].into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]
@ -667,16 +629,14 @@ fn test_object_typename() {
::execute(doc, None, &schema, &Variables::new(), &database),
Ok((
Value::object(
vec![
(
"human",
Value::object(
vec![("__typename", Value::string("Human"))]
.into_iter()
.collect(),
),
vec![(
"human",
Value::object(
vec![("__typename", Value::string("Human"))]
.into_iter()
.collect(),
),
].into_iter()
)].into_iter()
.collect()
),
vec![]

View file

@ -1,5 +1,5 @@
use tests::model::{Character, Database, Droid, Episode, Human};
use executor::Context;
use tests::model::{Character, Database, Droid, Episode, Human};
impl Context for Database {}

View file

@ -1,11 +1,11 @@
use indexmap::IndexMap;
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;
use value::Value;
pub struct NodeTypeInfo {
name: String,

View file

@ -1,13 +1,13 @@
use indexmap::IndexMap;
use indexmap::map::Entry;
use indexmap::IndexMap;
use ast::{Directive, FromInputValue, InputValue, Selection};
use executor::Variables;
use value::Value;
use schema::meta::{Argument, MetaType};
use executor::{ExecutionResult, Executor, Registry};
use parser::Spanning;
use schema::meta::{Argument, MetaType};
/// GraphQL type kind
///
@ -374,7 +374,7 @@ where
let sub_exec = executor.field_sub_executor(
response_name,
&f.name.item,
f.name.item,
start_pos.clone(),
f.selection_set.as_ref().map(|v| &v[..]),
);
@ -505,29 +505,28 @@ fn is_excluded(directives: &Option<Vec<Spanning<Directive>>>, vars: &Variables)
fn merge_key_into(result: &mut IndexMap<String, Value>, response_name: &str, value: Value) {
match result.entry(response_name.to_owned()) {
Entry::Occupied(mut e) => {
match e.get_mut() {
&mut Value::Object(ref mut dest_obj) => {
if let Value::Object(src_obj) = value {
merge_maps(dest_obj, src_obj);
}
},
&mut Value::List(ref mut dest_list) => {
if let Value::List(src_list) = value {
dest_list.iter_mut().zip(src_list.into_iter()).for_each(|(d, s)| {
match d {
&mut Value::Object(ref mut d_obj) => {
if let Value::Object(s_obj) = s {
merge_maps(d_obj, s_obj);
}
},
_ => {},
}
});
}
},
_ => {}
Entry::Occupied(mut e) => match e.get_mut() {
&mut Value::Object(ref mut dest_obj) => {
if let Value::Object(src_obj) = value {
merge_maps(dest_obj, src_obj);
}
}
&mut Value::List(ref mut dest_list) => {
if let Value::List(src_list) = value {
dest_list
.iter_mut()
.zip(src_list.into_iter())
.for_each(|(d, s)| match d {
&mut Value::Object(ref mut d_obj) => {
if let Value::Object(s_obj) = s {
merge_maps(d_obj, s_obj);
}
}
_ => {}
});
}
}
_ => {}
},
Entry::Vacant(e) => {
e.insert(value);

View file

@ -1,6 +1,6 @@
use ast::{FromInputValue, InputValue, Selection, ToInputValue};
use value::Value;
use schema::meta::MetaType;
use value::Value;
use executor::{Executor, Registry};
use types::base::GraphQLType;

View file

@ -1,6 +1,6 @@
pub mod base;
pub mod scalars;
pub mod pointers;
pub mod containers;
pub mod utilities;
pub mod name;
pub mod pointers;
pub mod scalars;
pub mod utilities;

View file

@ -30,7 +30,7 @@ impl Name {
}
}
}
return input.len() > 0;
return !input.is_empty();
}
}

View file

@ -1,8 +1,8 @@
use ast::{FromInputValue, InputValue, Selection, ToInputValue};
use value::Value;
use schema::meta::MetaType;
use executor::{ExecutionResult, Executor, Registry};
use schema::meta::MetaType;
use types::base::{Arguments, GraphQLType};
impl<T, CtxT> GraphQLType for Box<T>

View file

@ -113,7 +113,7 @@ graphql_scalar!(f64 as "Float" {
from_input_value(v: &InputValue) -> Option<f64> {
match *v {
InputValue::Int(i) => Some(i as f64),
InputValue::Int(i) => Some(f64::from(i)),
InputValue::Float(f) => Some(f),
_ => None,
}

View file

@ -1,7 +1,7 @@
use std::collections::HashSet;
use ast::InputValue;
use schema::model::{SchemaType, TypeType};
use schema::meta::{EnumMeta, InputObjectMeta, MetaType};
use schema::model::{SchemaType, TypeType};
use std::collections::HashSet;
pub fn is_valid_literal_value(
schema: &SchemaType,

View file

@ -1,12 +1,12 @@
use std::collections::HashSet;
use std::fmt;
use parser::SourcePosition;
use ast::{Definition, Document, InputValue, VariableDefinitions};
use executor::Variables;
use validation::RuleError;
use schema::model::{SchemaType, TypeType};
use parser::SourcePosition;
use schema::meta::{EnumMeta, InputObjectMeta, MetaType, ScalarMeta};
use schema::model::{SchemaType, TypeType};
use validation::RuleError;
#[derive(Debug)]
enum Path<'a> {

View file

@ -1,21 +1,21 @@
//! Query validation related methods and data structures
mod visitor;
mod traits;
mod context;
mod input_value;
mod multi_visitor;
mod rules;
mod input_value;
mod traits;
mod visitor;
#[cfg(test)]
mod test_harness;
pub use self::context::{RuleError, ValidatorContext};
pub use self::input_value::validate_input_values;
pub use self::multi_visitor::{MultiVisitor, MultiVisitorNil};
pub use self::rules::visit_all_rules;
pub use self::traits::Visitor;
pub use self::visitor::visit;
pub use self::context::{RuleError, ValidatorContext};
pub use self::rules::visit_all_rules;
pub use self::multi_visitor::{MultiVisitor, MultiVisitorNil};
pub use self::input_value::validate_input_values;
#[cfg(test)]
pub use self::test_harness::{expect_fails_rule, expect_fails_rule_with_schema, expect_passes_rule,

View file

@ -1,7 +1,7 @@
use ast::{Directive, Field, InputValue};
use parser::Spanning;
use schema::meta::Argument;
use types::utilities::is_valid_literal_value;
use parser::Spanning;
use validation::{ValidatorContext, Visitor};
pub struct ArgumentsOfCorrectType<'a> {
@ -96,12 +96,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("nonNullIntArg", "Int!"),
&[SourcePosition::new(97, 3, 50)],
),
],
&[RuleError::new(
&error_message("nonNullIntArg", "Int!"),
&[SourcePosition::new(97, 3, 50)],
)],
);
}
@ -228,12 +226,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
),
],
&[RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
)],
);
}
@ -248,12 +244,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
),
],
&[RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
)],
);
}
@ -268,12 +262,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
),
],
&[RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
)],
);
}
@ -288,12 +280,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
),
],
&[RuleError::new(
&error_message("stringArg", "String"),
&[SourcePosition::new(89, 3, 42)],
)],
);
}
@ -308,12 +298,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
),
],
&[RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
)],
);
}
@ -328,12 +316,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
),
],
&[RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
)],
);
}
@ -348,12 +334,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
),
],
&[RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
)],
);
}
@ -368,12 +352,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
),
],
&[RuleError::new(
&error_message("intArg", "Int"),
&[SourcePosition::new(83, 3, 36)],
)],
);
}
@ -388,12 +370,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("floatArg", "Float"),
&[SourcePosition::new(87, 3, 40)],
),
],
&[RuleError::new(
&error_message("floatArg", "Float"),
&[SourcePosition::new(87, 3, 40)],
)],
);
}
@ -408,12 +388,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("floatArg", "Float"),
&[SourcePosition::new(87, 3, 40)],
),
],
&[RuleError::new(
&error_message("floatArg", "Float"),
&[SourcePosition::new(87, 3, 40)],
)],
);
}
@ -428,12 +406,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("floatArg", "Float"),
&[SourcePosition::new(87, 3, 40)],
),
],
&[RuleError::new(
&error_message("floatArg", "Float"),
&[SourcePosition::new(87, 3, 40)],
)],
);
}
@ -448,12 +424,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
),
],
&[RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
)],
);
}
@ -468,12 +442,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
),
],
&[RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
)],
);
}
@ -488,12 +460,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
),
],
&[RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
)],
);
}
@ -508,12 +478,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
),
],
&[RuleError::new(
&error_message("booleanArg", "Boolean"),
&[SourcePosition::new(91, 3, 44)],
)],
);
}
@ -528,12 +496,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("idArg", "ID"),
&[SourcePosition::new(81, 3, 34)],
),
],
&[RuleError::new(
&error_message("idArg", "ID"),
&[SourcePosition::new(81, 3, 34)],
)],
);
}
@ -548,12 +514,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("idArg", "ID"),
&[SourcePosition::new(81, 3, 34)],
),
],
&[RuleError::new(
&error_message("idArg", "ID"),
&[SourcePosition::new(81, 3, 34)],
)],
);
}
@ -568,12 +532,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("idArg", "ID"),
&[SourcePosition::new(81, 3, 34)],
),
],
&[RuleError::new(
&error_message("idArg", "ID"),
&[SourcePosition::new(81, 3, 34)],
)],
);
}
@ -588,12 +550,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
),
],
&[RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
)],
);
}
@ -608,12 +568,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
),
],
&[RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
)],
);
}
@ -628,12 +586,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
),
],
&[RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
)],
);
}
@ -648,12 +604,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
),
],
&[RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
)],
);
}
@ -668,12 +622,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
),
],
&[RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
)],
);
}
@ -688,12 +640,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
),
],
&[RuleError::new(
&error_message("dogCommand", "DogCommand"),
&[SourcePosition::new(79, 3, 44)],
)],
);
}
@ -750,12 +700,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringListArg", "[String]"),
&[SourcePosition::new(97, 3, 50)],
),
],
&[RuleError::new(
&error_message("stringListArg", "[String]"),
&[SourcePosition::new(97, 3, 50)],
)],
);
}
@ -770,12 +718,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringListArg", "[String]"),
&[SourcePosition::new(97, 3, 50)],
),
],
&[RuleError::new(
&error_message("stringListArg", "[String]"),
&[SourcePosition::new(97, 3, 50)],
)],
);
}
@ -954,12 +900,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("req1", "Int!"),
&[SourcePosition::new(82, 3, 35)],
),
],
&[RuleError::new(
&error_message("req1", "Int!"),
&[SourcePosition::new(82, 3, 35)],
)],
);
}
@ -1070,12 +1014,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("complexArg", "ComplexInput"),
&[SourcePosition::new(91, 3, 44)],
),
],
&[RuleError::new(
&error_message("complexArg", "ComplexInput"),
&[SourcePosition::new(91, 3, 44)],
)],
);
}
@ -1093,12 +1035,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("complexArg", "ComplexInput"),
&[SourcePosition::new(91, 3, 44)],
),
],
&[RuleError::new(
&error_message("complexArg", "ComplexInput"),
&[SourcePosition::new(91, 3, 44)],
)],
);
}
@ -1116,12 +1056,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("complexArg", "ComplexInput"),
&[SourcePosition::new(91, 3, 44)],
),
],
&[RuleError::new(
&error_message("complexArg", "ComplexInput"),
&[SourcePosition::new(91, 3, 44)],
)],
);
}

View file

@ -1,6 +1,6 @@
use ast::VariableDefinition;
use types::utilities::is_valid_literal_value;
use parser::Spanning;
use types::utilities::is_valid_literal_value;
use validation::{ValidatorContext, Visitor};
pub struct DefaultValuesOfCorrectType {}
@ -162,12 +162,10 @@ mod tests {
dog { name }
}
"#,
&[
RuleError::new(
&type_error_message("a", "ComplexInput"),
&[SourcePosition::new(57, 1, 56)],
),
],
&[RuleError::new(
&type_error_message("a", "ComplexInput"),
&[SourcePosition::new(57, 1, 56)],
)],
);
}
@ -180,12 +178,10 @@ mod tests {
dog { name }
}
"#,
&[
RuleError::new(
&type_error_message("a", "[String]"),
&[SourcePosition::new(44, 1, 43)],
),
],
&[RuleError::new(
&type_error_message("a", "[String]"),
&[SourcePosition::new(44, 1, 43)],
)],
);
}

View file

@ -1,7 +1,7 @@
use ast::Field;
use parser::Spanning;
use schema::meta::MetaType;
use validation::{ValidatorContext, Visitor};
use parser::Spanning;
pub struct FieldsOnCorrectType {}
@ -160,12 +160,10 @@ mod tests {
meowVolume
}
"#,
&[
RuleError::new(
&error_message("meowVolume", "Dog"),
&[SourcePosition::new(57, 2, 12)],
),
],
&[RuleError::new(
&error_message("meowVolume", "Dog"),
&[SourcePosition::new(57, 2, 12)],
)],
);
}
@ -180,12 +178,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("unknown_field", "Dog"),
&[SourcePosition::new(61, 2, 12)],
),
],
&[RuleError::new(
&error_message("unknown_field", "Dog"),
&[SourcePosition::new(61, 2, 12)],
)],
);
}
@ -200,12 +196,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("unknown_field", "Pet"),
&[SourcePosition::new(83, 3, 14)],
),
],
&[RuleError::new(
&error_message("unknown_field", "Pet"),
&[SourcePosition::new(83, 3, 14)],
)],
);
}
@ -220,12 +214,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("meowVolume", "Dog"),
&[SourcePosition::new(84, 3, 14)],
),
],
&[RuleError::new(
&error_message("meowVolume", "Dog"),
&[SourcePosition::new(84, 3, 14)],
)],
);
}
@ -238,12 +230,10 @@ mod tests {
volume : mooVolume
}
"#,
&[
RuleError::new(
&error_message("mooVolume", "Dog"),
&[SourcePosition::new(79, 2, 21)],
),
],
&[RuleError::new(
&error_message("mooVolume", "Dog"),
&[SourcePosition::new(79, 2, 21)],
)],
);
}
@ -256,12 +246,10 @@ mod tests {
barkVolume : kawVolume
}
"#,
&[
RuleError::new(
&error_message("kawVolume", "Dog"),
&[SourcePosition::new(88, 2, 25)],
),
],
&[RuleError::new(
&error_message("kawVolume", "Dog"),
&[SourcePosition::new(88, 2, 25)],
)],
);
}
@ -274,12 +262,10 @@ mod tests {
tailLength
}
"#,
&[
RuleError::new(
&error_message("tailLength", "Pet"),
&[SourcePosition::new(63, 2, 12)],
),
],
&[RuleError::new(
&error_message("tailLength", "Pet"),
&[SourcePosition::new(63, 2, 12)],
)],
);
}
@ -292,12 +278,10 @@ mod tests {
nickname
}
"#,
&[
RuleError::new(
&error_message("nickname", "Pet"),
&[SourcePosition::new(78, 2, 12)],
),
],
&[RuleError::new(
&error_message("nickname", "Pet"),
&[SourcePosition::new(78, 2, 12)],
)],
);
}
@ -322,12 +306,10 @@ mod tests {
name
}
"#,
&[
RuleError::new(
&error_message("name", "CatOrDog"),
&[SourcePosition::new(82, 2, 12)],
),
],
&[RuleError::new(
&error_message("name", "CatOrDog"),
&[SourcePosition::new(82, 2, 12)],
)],
);
}

View file

@ -145,12 +145,10 @@ mod tests {
bad
}
"#,
&[
RuleError::new(
&error_message(Some("scalarFragment"), "Boolean"),
&[SourcePosition::new(38, 1, 37)],
),
],
&[RuleError::new(
&error_message(Some("scalarFragment"), "Boolean"),
&[SourcePosition::new(38, 1, 37)],
)],
);
}
@ -163,12 +161,10 @@ mod tests {
bad
}
"#,
&[
RuleError::new(
&error_message(Some("scalarFragment"), "FurColor"),
&[SourcePosition::new(38, 1, 37)],
),
],
&[RuleError::new(
&error_message(Some("scalarFragment"), "FurColor"),
&[SourcePosition::new(38, 1, 37)],
)],
);
}
@ -181,12 +177,10 @@ mod tests {
stringField
}
"#,
&[
RuleError::new(
&error_message(Some("inputFragment"), "ComplexInput"),
&[SourcePosition::new(37, 1, 36)],
),
],
&[RuleError::new(
&error_message(Some("inputFragment"), "ComplexInput"),
&[SourcePosition::new(37, 1, 36)],
)],
);
}
@ -201,12 +195,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(None, "String"),
&[SourcePosition::new(64, 2, 19)],
),
],
&[RuleError::new(
&error_message(None, "String"),
&[SourcePosition::new(64, 2, 19)],
)],
);
}
}

View file

@ -1,6 +1,6 @@
use ast::{Directive, Field, InputValue};
use schema::meta::Argument;
use parser::Spanning;
use schema::meta::Argument;
use validation::{ValidatorContext, Visitor};
#[derive(Debug)]
@ -204,12 +204,10 @@ mod tests {
dog @skip(unless: true)
}
"#,
&[
RuleError::new(
&directive_error_message("unless", "skip"),
&[SourcePosition::new(35, 2, 22)],
),
],
&[RuleError::new(
&directive_error_message("unless", "skip"),
&[SourcePosition::new(35, 2, 22)],
)],
);
}
@ -222,12 +220,10 @@ mod tests {
doesKnowCommand(unknown: true)
}
"#,
&[
RuleError::new(
&field_error_message("unknown", "doesKnowCommand", "Dog"),
&[SourcePosition::new(72, 2, 28)],
),
],
&[RuleError::new(
&field_error_message("unknown", "doesKnowCommand", "Dog"),
&[SourcePosition::new(72, 2, 28)],
)],
);
}

View file

@ -1,7 +1,7 @@
use ast::{Directive, Field, Fragment, FragmentSpread, InlineFragment, Operation, OperationType};
use validation::{ValidatorContext, Visitor};
use schema::model::DirectiveLocation;
use parser::Spanning;
use schema::model::DirectiveLocation;
use validation::{ValidatorContext, Visitor};
pub struct KnownDirectives {
location_stack: Vec<DirectiveLocation>,
@ -141,8 +141,8 @@ mod tests {
use super::{factory, misplaced_error_message, unknown_error_message};
use parser::SourcePosition;
use validation::{expect_fails_rule, expect_passes_rule, RuleError};
use schema::model::DirectiveLocation;
use validation::{expect_fails_rule, expect_passes_rule, RuleError};
#[test]
fn with_no_directives() {
@ -189,12 +189,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&unknown_error_message("unknown"),
&[SourcePosition::new(29, 2, 16)],
),
],
&[RuleError::new(
&unknown_error_message("unknown"),
&[SourcePosition::new(29, 2, 16)],
)],
);
}

View file

@ -1,6 +1,6 @@
use ast::FragmentSpread;
use validation::{ValidatorContext, Visitor};
use parser::Spanning;
use validation::{ValidatorContext, Visitor};
pub struct KnownFragmentNames {}

View file

@ -1,6 +1,6 @@
use ast::{Fragment, InlineFragment, VariableDefinition};
use validation::{ValidatorContext, Visitor};
use parser::{SourcePosition, Spanning};
use validation::{ValidatorContext, Visitor};
pub struct KnownTypeNames {}

View file

@ -1,6 +1,6 @@
use ast::{Definition, Document, Operation};
use validation::{ValidatorContext, Visitor};
use parser::Spanning;
use validation::{ValidatorContext, Visitor};
pub struct LoneAnonymousOperation {
operation_count: Option<usize>,
@ -134,9 +134,10 @@ mod tests {
fieldB
}
"#,
&[
RuleError::new(error_message(), &[SourcePosition::new(11, 1, 10)]),
],
&[RuleError::new(
error_message(),
&[SourcePosition::new(11, 1, 10)],
)],
);
}
}

View file

@ -1,8 +1,8 @@
use std::collections::{HashMap, HashSet};
use ast::{Document, Fragment, FragmentSpread};
use validation::{RuleError, ValidatorContext, Visitor};
use parser::Spanning;
use validation::{RuleError, ValidatorContext, Visitor};
pub struct NoFragmentCycles<'a> {
current_fragment: Option<&'a str>,
@ -203,9 +203,10 @@ mod tests {
r#"
fragment fragA on Human { relatives { ...fragA } },
"#,
&[
RuleError::new(&error_message("fragA"), &[SourcePosition::new(49, 1, 48)]),
],
&[RuleError::new(
&error_message("fragA"),
&[SourcePosition::new(49, 1, 48)],
)],
);
}
@ -216,9 +217,10 @@ mod tests {
r#"
fragment fragA on Dog { ...fragA }
"#,
&[
RuleError::new(&error_message("fragA"), &[SourcePosition::new(35, 1, 34)]),
],
&[RuleError::new(
&error_message("fragA"),
&[SourcePosition::new(35, 1, 34)],
)],
);
}
@ -233,9 +235,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(&error_message("fragA"), &[SourcePosition::new(74, 3, 14)]),
],
&[RuleError::new(
&error_message("fragA"),
&[SourcePosition::new(74, 3, 14)],
)],
);
}
@ -247,9 +250,10 @@ mod tests {
fragment fragA on Dog { ...fragB }
fragment fragB on Dog { ...fragA }
"#,
&[
RuleError::new(&error_message("fragA"), &[SourcePosition::new(35, 1, 34)]),
],
&[RuleError::new(
&error_message("fragA"),
&[SourcePosition::new(35, 1, 34)],
)],
);
}
@ -261,9 +265,10 @@ mod tests {
fragment fragB on Dog { ...fragA }
fragment fragA on Dog { ...fragB }
"#,
&[
RuleError::new(&error_message("fragB"), &[SourcePosition::new(35, 1, 34)]),
],
&[RuleError::new(
&error_message("fragB"),
&[SourcePosition::new(35, 1, 34)],
)],
);
}
@ -283,9 +288,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(&error_message("fragA"), &[SourcePosition::new(74, 3, 14)]),
],
&[RuleError::new(
&error_message("fragA"),
&[SourcePosition::new(74, 3, 14)],
)],
);
}

View file

@ -1,7 +1,7 @@
use std::collections::{HashMap, HashSet};
use ast::{Document, Fragment, FragmentSpread, InputValue, Operation, VariableDefinition};
use validation::{RuleError, ValidatorContext, Visitor};
use parser::{SourcePosition, Spanning};
use std::collections::{HashMap, HashSet};
use validation::{RuleError, ValidatorContext, Visitor};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Scope<'a> {
@ -302,15 +302,13 @@ mod tests {
field(a: $a, b: $b, c: $c, d: $d)
}
"#,
&[
RuleError::new(
&error_message("d", Some("Foo")),
&[
SourcePosition::new(101, 2, 42),
SourcePosition::new(11, 1, 10),
],
),
],
&[RuleError::new(
&error_message("d", Some("Foo")),
&[
SourcePosition::new(101, 2, 42),
SourcePosition::new(11, 1, 10),
],
)],
);
}
@ -323,15 +321,13 @@ mod tests {
field(a: $a)
}
"#,
&[
RuleError::new(
&error_message("a", None),
&[
SourcePosition::new(34, 2, 21),
SourcePosition::new(11, 1, 10),
],
),
],
&[RuleError::new(
&error_message("a", None),
&[
SourcePosition::new(34, 2, 21),
SourcePosition::new(11, 1, 10),
],
)],
);
}
@ -375,15 +371,13 @@ mod tests {
field(a: $a)
}
"#,
&[
RuleError::new(
&error_message("a", None),
&[
SourcePosition::new(102, 5, 21),
SourcePosition::new(11, 1, 10),
],
),
],
&[RuleError::new(
&error_message("a", None),
&[
SourcePosition::new(102, 5, 21),
SourcePosition::new(11, 1, 10),
],
)],
);
}
@ -409,15 +403,13 @@ mod tests {
field(c: $c)
}
"#,
&[
RuleError::new(
&error_message("c", Some("Foo")),
&[
SourcePosition::new(358, 15, 21),
SourcePosition::new(11, 1, 10),
],
),
],
&[RuleError::new(
&error_message("c", Some("Foo")),
&[
SourcePosition::new(358, 15, 21),
SourcePosition::new(11, 1, 10),
],
)],
);
}

View file

@ -1,8 +1,8 @@
use std::collections::{HashMap, HashSet};
use ast::{Definition, Document, Fragment, FragmentSpread, Operation};
use validation::{ValidatorContext, Visitor};
use parser::Spanning;
use validation::{ValidatorContext, Visitor};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Scope<'a> {
@ -270,9 +270,10 @@ mod tests {
name
}
"#,
&[
RuleError::new(&error_message("foo"), &[SourcePosition::new(107, 6, 10)]),
],
&[RuleError::new(
&error_message("foo"),
&[SourcePosition::new(107, 6, 10)],
)],
);
}
}

View file

@ -1,7 +1,7 @@
use std::collections::{HashMap, HashSet};
use ast::{Document, Fragment, FragmentSpread, InputValue, Operation, VariableDefinition};
use validation::{RuleError, ValidatorContext, Visitor};
use parser::Spanning;
use std::collections::{HashMap, HashSet};
use validation::{RuleError, ValidatorContext, Visitor};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Scope<'a> {
@ -274,9 +274,10 @@ mod tests {
field(a: $a, b: $b)
}
"#,
&[
RuleError::new(&error_message("c", None), &[SourcePosition::new(42, 1, 41)]),
],
&[RuleError::new(
&error_message("c", None),
&[SourcePosition::new(42, 1, 41)],
)],
);
}
@ -324,12 +325,10 @@ mod tests {
field
}
"#,
&[
RuleError::new(
&error_message("c", Some("Foo")),
&[SourcePosition::new(45, 1, 44)],
),
],
&[RuleError::new(
&error_message("c", Some("Foo")),
&[SourcePosition::new(45, 1, 44)],
)],
);
}
@ -383,12 +382,10 @@ mod tests {
field(b: $b)
}
"#,
&[
RuleError::new(
&error_message("b", Some("Foo")),
&[SourcePosition::new(21, 1, 20)],
),
],
&[RuleError::new(
&error_message("b", Some("Foo")),
&[SourcePosition::new(21, 1, 20)],
)],
);
}

View file

@ -1,11 +1,11 @@
use std::collections::HashMap;
use std::cell::RefCell;
use std::hash::Hash;
use std::borrow::Borrow;
use ast::{Arguments, Definition, Document, Field, Fragment, FragmentSpread, Selection, Type};
use validation::{ValidatorContext, Visitor};
use parser::{SourcePosition, Spanning};
use schema::meta::{Field as FieldType, MetaType};
use std::borrow::Borrow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::hash::Hash;
use validation::{ValidatorContext, Visitor};
#[derive(Debug)]
struct Conflict(ConflictReason, Vec<SourcePosition>, Vec<SourcePosition>);
@ -708,13 +708,13 @@ fn format_reason(reason: &ConflictReasonMessage) -> String {
#[cfg(test)]
mod tests {
use super::{error_message, factory, ConflictReason};
use super::ConflictReasonMessage::*;
use super::{error_message, factory, ConflictReason};
use types::base::GraphQLType;
use executor::Registry;
use types::scalars::ID;
use schema::meta::MetaType;
use types::base::GraphQLType;
use types::scalars::ID;
use parser::SourcePosition;
use validation::{expect_fails_rule, expect_fails_rule_with_schema, expect_passes_rule,
@ -821,18 +821,16 @@ mod tests {
fido: nickname
}
"#,
&[
RuleError::new(
&error_message(
"fido",
&Message("name and nickname are different fields".to_owned()),
),
&[
SourcePosition::new(78, 2, 12),
SourcePosition::new(101, 3, 12),
],
&[RuleError::new(
&error_message(
"fido",
&Message("name and nickname are different fields".to_owned()),
),
],
&[
SourcePosition::new(78, 2, 12),
SourcePosition::new(101, 3, 12),
],
)],
);
}
@ -863,18 +861,16 @@ mod tests {
name
}
"#,
&[
RuleError::new(
&error_message(
"name",
&Message("nickname and name are different fields".to_owned()),
),
&[
SourcePosition::new(71, 2, 12),
SourcePosition::new(98, 3, 12),
],
&[RuleError::new(
&error_message(
"name",
&Message("nickname and name are different fields".to_owned()),
),
],
&[
SourcePosition::new(71, 2, 12),
SourcePosition::new(98, 3, 12),
],
)],
);
}
@ -888,18 +884,16 @@ mod tests {
doesKnowCommand(dogCommand: HEEL)
}
"#,
&[
RuleError::new(
&error_message(
"doesKnowCommand",
&Message("they have differing arguments".to_owned()),
),
&[
SourcePosition::new(57, 2, 12),
SourcePosition::new(85, 3, 12),
],
&[RuleError::new(
&error_message(
"doesKnowCommand",
&Message("they have differing arguments".to_owned()),
),
],
&[
SourcePosition::new(57, 2, 12),
SourcePosition::new(85, 3, 12),
],
)],
);
}
@ -913,18 +907,16 @@ mod tests {
doesKnowCommand
}
"#,
&[
RuleError::new(
&error_message(
"doesKnowCommand",
&Message("they have differing arguments".to_owned()),
),
&[
SourcePosition::new(57, 2, 12),
SourcePosition::new(102, 3, 12),
],
&[RuleError::new(
&error_message(
"doesKnowCommand",
&Message("they have differing arguments".to_owned()),
),
],
&[
SourcePosition::new(57, 2, 12),
SourcePosition::new(102, 3, 12),
],
)],
);
}
@ -938,18 +930,16 @@ mod tests {
doesKnowCommand(dogCommand: HEEL)
}
"#,
&[
RuleError::new(
&error_message(
"doesKnowCommand",
&Message("they have differing arguments".to_owned()),
),
&[
SourcePosition::new(57, 2, 12),
SourcePosition::new(102, 3, 12),
],
&[RuleError::new(
&error_message(
"doesKnowCommand",
&Message("they have differing arguments".to_owned()),
),
],
&[
SourcePosition::new(57, 2, 12),
SourcePosition::new(102, 3, 12),
],
)],
);
}
@ -986,15 +976,13 @@ mod tests {
x: b
}
"#,
&[
RuleError::new(
&error_message("x", &Message("a and b are different fields".to_owned())),
&[
SourcePosition::new(102, 6, 12),
SourcePosition::new(162, 9, 12),
],
),
],
&[RuleError::new(
&error_message("x", &Message("a and b are different fields".to_owned())),
&[
SourcePosition::new(102, 6, 12),
SourcePosition::new(162, 9, 12),
],
)],
);
}
@ -1065,25 +1053,21 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"field",
&Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
]),
),
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(47, 3, 14),
SourcePosition::new(79, 5, 12),
SourcePosition::new(101, 6, 14),
],
&[RuleError::new(
&error_message(
"field",
&Nested(vec![ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
)]),
),
],
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(47, 3, 14),
SourcePosition::new(79, 5, 12),
SourcePosition::new(101, 6, 14),
],
)],
);
}
@ -1103,31 +1087,29 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"field",
&Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
ConflictReason(
"y".to_owned(),
Message("c and d are different fields".to_owned()),
),
]),
),
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(47, 3, 14),
SourcePosition::new(66, 4, 14),
SourcePosition::new(98, 6, 12),
SourcePosition::new(120, 7, 14),
SourcePosition::new(139, 8, 14),
],
&[RuleError::new(
&error_message(
"field",
&Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
ConflictReason(
"y".to_owned(),
Message("c and d are different fields".to_owned()),
),
]),
),
],
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(47, 3, 14),
SourcePosition::new(66, 4, 14),
SourcePosition::new(98, 6, 12),
SourcePosition::new(120, 7, 14),
SourcePosition::new(139, 8, 14),
],
)],
);
}
@ -1149,32 +1131,26 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"field",
&Nested(vec![
ConflictReason(
"deepField".to_owned(),
Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
]),
),
]),
),
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(47, 3, 14),
SourcePosition::new(75, 4, 16),
SourcePosition::new(123, 7, 12),
SourcePosition::new(145, 8, 14),
SourcePosition::new(173, 9, 16),
],
&[RuleError::new(
&error_message(
"field",
&Nested(vec![ConflictReason(
"deepField".to_owned(),
Nested(vec![ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
)]),
)]),
),
],
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(47, 3, 14),
SourcePosition::new(75, 4, 16),
SourcePosition::new(123, 7, 12),
SourcePosition::new(145, 8, 14),
SourcePosition::new(173, 9, 16),
],
)],
);
}
@ -1199,25 +1175,21 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"deepField",
&Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
]),
),
&[
SourcePosition::new(47, 3, 14),
SourcePosition::new(75, 4, 16),
SourcePosition::new(110, 6, 14),
SourcePosition::new(138, 7, 16),
],
&[RuleError::new(
&error_message(
"deepField",
&Nested(vec![ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
)]),
),
],
&[
SourcePosition::new(47, 3, 14),
SourcePosition::new(75, 4, 16),
SourcePosition::new(110, 6, 14),
SourcePosition::new(138, 7, 16),
],
)],
);
}
@ -1250,25 +1222,21 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"deeperField",
&Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
]),
),
&[
SourcePosition::new(197, 11, 14),
SourcePosition::new(227, 12, 16),
SourcePosition::new(262, 14, 14),
SourcePosition::new(292, 15, 16),
],
&[RuleError::new(
&error_message(
"deeperField",
&Nested(vec![ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
)]),
),
],
&[
SourcePosition::new(197, 11, 14),
SourcePosition::new(227, 12, 16),
SourcePosition::new(262, 14, 14),
SourcePosition::new(292, 15, 16),
],
)],
);
}
@ -1300,31 +1268,29 @@ mod tests {
x: b
}
"#,
&[
RuleError::new(
&error_message(
"field",
&Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
ConflictReason(
"y".to_owned(),
Message("c and d are different fields".to_owned()),
),
]),
),
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(171, 10, 12),
SourcePosition::new(245, 14, 12),
SourcePosition::new(78, 5, 12),
SourcePosition::new(376, 21, 12),
SourcePosition::new(302, 17, 12),
],
&[RuleError::new(
&error_message(
"field",
&Nested(vec![
ConflictReason(
"x".to_owned(),
Message("a and b are different fields".to_owned()),
),
ConflictReason(
"y".to_owned(),
Message("c and d are different fields".to_owned()),
),
]),
),
],
&[
SourcePosition::new(25, 2, 12),
SourcePosition::new(171, 10, 12),
SourcePosition::new(245, 14, 12),
SourcePosition::new(78, 5, 12),
SourcePosition::new(376, 21, 12),
SourcePosition::new(302, 17, 12),
],
)],
);
}
@ -1594,18 +1560,16 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"scalar",
&Message("they return conflicting types Int and String!".to_owned()),
),
&[
SourcePosition::new(88, 4, 18),
SourcePosition::new(173, 7, 18),
],
&[RuleError::new(
&error_message(
"scalar",
&Message("they return conflicting types Int and String!".to_owned()),
),
],
&[
SourcePosition::new(88, 4, 18),
SourcePosition::new(173, 7, 18),
],
)],
);
}
@ -1650,18 +1614,16 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"scalar",
&Message("they return conflicting types Int and String".to_owned()),
),
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(167, 7, 18),
],
&[RuleError::new(
&error_message(
"scalar",
&Message("they return conflicting types Int and String".to_owned()),
),
],
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(167, 7, 18),
],
)],
);
}
@ -1714,27 +1676,21 @@ mod tests {
scalar: unrelatedField
}
"#,
&[
RuleError::new(
&error_message(
"other",
&Nested(vec![
ConflictReason(
"scalar".to_owned(),
Message(
"scalar and unrelatedField are different fields".to_owned(),
),
),
]),
),
&[
SourcePosition::new(703, 30, 14),
SourcePosition::new(889, 38, 14),
SourcePosition::new(771, 33, 14),
SourcePosition::new(960, 41, 14),
],
&[RuleError::new(
&error_message(
"other",
&Nested(vec![ConflictReason(
"scalar".to_owned(),
Message("scalar and unrelatedField are different fields".to_owned()),
)]),
),
],
&[
SourcePosition::new(703, 30, 14),
SourcePosition::new(889, 38, 14),
SourcePosition::new(771, 33, 14),
SourcePosition::new(960, 41, 14),
],
)],
);
}
@ -1755,18 +1711,16 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"scalar",
&Message("they return conflicting types String! and String".to_owned()),
),
&[
SourcePosition::new(100, 4, 18),
SourcePosition::new(178, 7, 18),
],
&[RuleError::new(
&error_message(
"scalar",
&Message("they return conflicting types String! and String".to_owned()),
),
],
&[
SourcePosition::new(100, 4, 18),
SourcePosition::new(178, 7, 18),
],
)],
);
}
@ -1791,20 +1745,16 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"box",
&Message(
"they return conflicting types [StringBox] and StringBox".to_owned(),
),
),
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(228, 9, 18),
],
&[RuleError::new(
&error_message(
"box",
&Message("they return conflicting types [StringBox] and StringBox".to_owned()),
),
],
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(228, 9, 18),
],
)],
);
expect_fails_rule_with_schema(
@ -1826,20 +1776,16 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"box",
&Message(
"they return conflicting types StringBox and [StringBox]".to_owned(),
),
),
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(224, 9, 18),
],
&[RuleError::new(
&error_message(
"box",
&Message("they return conflicting types StringBox and [StringBox]".to_owned()),
),
],
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(224, 9, 18),
],
)],
);
}
@ -1865,18 +1811,16 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"val",
&Message("scalar and unrelatedField are different fields".to_owned()),
),
&[
SourcePosition::new(126, 5, 20),
SourcePosition::new(158, 6, 20),
],
&[RuleError::new(
&error_message(
"val",
&Message("scalar and unrelatedField are different fields".to_owned()),
),
],
&[
SourcePosition::new(126, 5, 20),
SourcePosition::new(158, 6, 20),
],
)],
);
}
@ -1901,25 +1845,21 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"box",
&Nested(vec![
ConflictReason(
"scalar".to_owned(),
Message("they return conflicting types String and Int".to_owned()),
),
]),
),
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(126, 5, 20),
SourcePosition::new(224, 9, 18),
SourcePosition::new(258, 10, 20),
],
&[RuleError::new(
&error_message(
"box",
&Nested(vec![ConflictReason(
"scalar".to_owned(),
Message("they return conflicting types String and Int".to_owned()),
)]),
),
],
&[
SourcePosition::new(89, 4, 18),
SourcePosition::new(126, 5, 20),
SourcePosition::new(224, 9, 18),
SourcePosition::new(258, 10, 20),
],
)],
);
}
@ -2004,32 +1944,26 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message(
"edges",
&Nested(vec![
ConflictReason(
"node".to_owned(),
Nested(vec![
ConflictReason(
"id".to_owned(),
Message("name and id are different fields".to_owned()),
),
]),
),
]),
),
&[
SourcePosition::new(84, 4, 16),
SourcePosition::new(110, 5, 18),
SourcePosition::new(137, 6, 20),
SourcePosition::new(273, 13, 14),
SourcePosition::new(297, 14, 16),
SourcePosition::new(322, 15, 18),
],
&[RuleError::new(
&error_message(
"edges",
&Nested(vec![ConflictReason(
"node".to_owned(),
Nested(vec![ConflictReason(
"id".to_owned(),
Message("name and id are different fields".to_owned()),
)]),
)]),
),
],
&[
SourcePosition::new(84, 4, 16),
SourcePosition::new(110, 5, 18),
SourcePosition::new(137, 6, 20),
SourcePosition::new(273, 13, 14),
SourcePosition::new(297, 14, 16),
SourcePosition::new(322, 15, 18),
],
)],
);
}

View file

@ -1,8 +1,8 @@
use std::collections::HashMap;
use ast::{Definition, Document, FragmentSpread, InlineFragment};
use validation::{ValidatorContext, Visitor};
use parser::Spanning;
use schema::meta::MetaType;
use std::collections::HashMap;
use validation::{ValidatorContext, Visitor};
pub struct PossibleFragmentSpreads<'a> {
fragment_types: HashMap<&'a str, &'a MetaType<'a>>,
@ -223,12 +223,10 @@ mod tests {
fragment invalidObjectWithinObject on Cat { ...dogFragment }
fragment dogFragment on Dog { barkVolume }
"#,
&[
RuleError::new(
&error_message(Some("dogFragment"), "Cat", "Dog"),
&[SourcePosition::new(55, 1, 54)],
),
],
&[RuleError::new(
&error_message(Some("dogFragment"), "Cat", "Dog"),
&[SourcePosition::new(55, 1, 54)],
)],
);
}
@ -241,12 +239,10 @@ mod tests {
... on Dog { barkVolume }
}
"#,
&[
RuleError::new(
&error_message(None, "Cat", "Dog"),
&[SourcePosition::new(71, 2, 12)],
),
],
&[RuleError::new(
&error_message(None, "Cat", "Dog"),
&[SourcePosition::new(71, 2, 12)],
)],
);
}
@ -258,12 +254,10 @@ mod tests {
fragment invalidObjectWithinInterface on Pet { ...humanFragment }
fragment humanFragment on Human { pets { name } }
"#,
&[
RuleError::new(
&error_message(Some("humanFragment"), "Pet", "Human"),
&[SourcePosition::new(58, 1, 57)],
),
],
&[RuleError::new(
&error_message(Some("humanFragment"), "Pet", "Human"),
&[SourcePosition::new(58, 1, 57)],
)],
);
}
@ -275,12 +269,10 @@ mod tests {
fragment invalidObjectWithinUnion on CatOrDog { ...humanFragment }
fragment humanFragment on Human { pets { name } }
"#,
&[
RuleError::new(
&error_message(Some("humanFragment"), "CatOrDog", "Human"),
&[SourcePosition::new(59, 1, 58)],
),
],
&[RuleError::new(
&error_message(Some("humanFragment"), "CatOrDog", "Human"),
&[SourcePosition::new(59, 1, 58)],
)],
);
}
@ -292,12 +284,10 @@ mod tests {
fragment invalidUnionWithinObject on Human { ...catOrDogFragment }
fragment catOrDogFragment on CatOrDog { __typename }
"#,
&[
RuleError::new(
&error_message(Some("catOrDogFragment"), "Human", "CatOrDog"),
&[SourcePosition::new(56, 1, 55)],
),
],
&[RuleError::new(
&error_message(Some("catOrDogFragment"), "Human", "CatOrDog"),
&[SourcePosition::new(56, 1, 55)],
)],
);
}
@ -309,12 +299,10 @@ mod tests {
fragment invalidUnionWithinInterface on Pet { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename }
"#,
&[
RuleError::new(
&error_message(Some("humanOrAlienFragment"), "Pet", "HumanOrAlien"),
&[SourcePosition::new(57, 1, 56)],
),
],
&[RuleError::new(
&error_message(Some("humanOrAlienFragment"), "Pet", "HumanOrAlien"),
&[SourcePosition::new(57, 1, 56)],
)],
);
}
@ -326,12 +314,10 @@ mod tests {
fragment invalidUnionWithinUnion on CatOrDog { ...humanOrAlienFragment }
fragment humanOrAlienFragment on HumanOrAlien { __typename }
"#,
&[
RuleError::new(
&error_message(Some("humanOrAlienFragment"), "CatOrDog", "HumanOrAlien"),
&[SourcePosition::new(58, 1, 57)],
),
],
&[RuleError::new(
&error_message(Some("humanOrAlienFragment"), "CatOrDog", "HumanOrAlien"),
&[SourcePosition::new(58, 1, 57)],
)],
);
}
@ -343,12 +329,10 @@ mod tests {
fragment invalidInterfaceWithinObject on Cat { ...intelligentFragment }
fragment intelligentFragment on Intelligent { iq }
"#,
&[
RuleError::new(
&error_message(Some("intelligentFragment"), "Cat", "Intelligent"),
&[SourcePosition::new(58, 1, 57)],
),
],
&[RuleError::new(
&error_message(Some("intelligentFragment"), "Cat", "Intelligent"),
&[SourcePosition::new(58, 1, 57)],
)],
);
}
@ -362,12 +346,10 @@ mod tests {
}
fragment intelligentFragment on Intelligent { iq }
"#,
&[
RuleError::new(
&error_message(Some("intelligentFragment"), "Pet", "Intelligent"),
&[SourcePosition::new(73, 2, 12)],
),
],
&[RuleError::new(
&error_message(Some("intelligentFragment"), "Pet", "Intelligent"),
&[SourcePosition::new(73, 2, 12)],
)],
);
}
@ -380,12 +362,10 @@ mod tests {
...on Intelligent { iq }
}
"#,
&[
RuleError::new(
&error_message(None, "Pet", "Intelligent"),
&[SourcePosition::new(77, 2, 12)],
),
],
&[RuleError::new(
&error_message(None, "Pet", "Intelligent"),
&[SourcePosition::new(77, 2, 12)],
)],
);
}
@ -397,12 +377,10 @@ mod tests {
fragment invalidInterfaceWithinUnion on HumanOrAlien { ...petFragment }
fragment petFragment on Pet { name }
"#,
&[
RuleError::new(
&error_message(Some("petFragment"), "HumanOrAlien", "Pet"),
&[SourcePosition::new(66, 1, 65)],
),
],
&[RuleError::new(
&error_message(Some("petFragment"), "HumanOrAlien", "Pet"),
&[SourcePosition::new(66, 1, 65)],
)],
);
}

View file

@ -1,8 +1,8 @@
use ast::{Directive, Field};
use validation::{ValidatorContext, Visitor};
use parser::Spanning;
use schema::meta::Field as FieldType;
use schema::model::DirectiveType;
use validation::{ValidatorContext, Visitor};
pub struct ProvidedNonNullArguments {}
@ -262,12 +262,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&field_error_message("multipleReqs", "req1", "Int!"),
&[SourcePosition::new(63, 3, 16)],
),
],
&[RuleError::new(
&field_error_message("multipleReqs", "req1", "Int!"),
&[SourcePosition::new(63, 3, 16)],
)],
);
}
@ -306,12 +304,10 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&field_error_message("multipleReqs", "req2", "Int!"),
&[SourcePosition::new(63, 3, 16)],
),
],
&[RuleError::new(
&field_error_message("multipleReqs", "req2", "Int!"),
&[SourcePosition::new(63, 3, 16)],
)],
);
}

View file

@ -1,6 +1,6 @@
use ast::Field;
use validation::{RuleError, ValidatorContext, Visitor};
use parser::Spanning;
use validation::{RuleError, ValidatorContext, Visitor};
pub struct ScalarLeafs {}
@ -77,12 +77,10 @@ mod tests {
human
}
"#,
&[
RuleError::new(
&required_error_message("human", "Human"),
&[SourcePosition::new(67, 2, 12)],
),
],
&[RuleError::new(
&required_error_message("human", "Human"),
&[SourcePosition::new(67, 2, 12)],
)],
);
}
@ -95,12 +93,10 @@ mod tests {
human { pets }
}
"#,
&[
RuleError::new(
&required_error_message("pets", "[Pet]"),
&[SourcePosition::new(33, 2, 20)],
),
],
&[RuleError::new(
&required_error_message("pets", "[Pet]"),
&[SourcePosition::new(33, 2, 20)],
)],
);
}
@ -125,12 +121,10 @@ mod tests {
barks { sinceWhen }
}
"#,
&[
RuleError::new(
&no_allowed_error_message("barks", "Boolean"),
&[SourcePosition::new(77, 2, 12)],
),
],
&[RuleError::new(
&no_allowed_error_message("barks", "Boolean"),
&[SourcePosition::new(77, 2, 12)],
)],
);
}
@ -143,12 +137,10 @@ mod tests {
furColor { inHexdec }
}
"#,
&[
RuleError::new(
&no_allowed_error_message("furColor", "FurColor"),
&[SourcePosition::new(74, 2, 12)],
),
],
&[RuleError::new(
&no_allowed_error_message("furColor", "FurColor"),
&[SourcePosition::new(74, 2, 12)],
)],
);
}
@ -161,12 +153,10 @@ mod tests {
doesKnowCommand(dogCommand: SIT) { sinceWhen }
}
"#,
&[
RuleError::new(
&no_allowed_error_message("doesKnowCommand", "Boolean"),
&[SourcePosition::new(76, 2, 12)],
),
],
&[RuleError::new(
&no_allowed_error_message("doesKnowCommand", "Boolean"),
&[SourcePosition::new(76, 2, 12)],
)],
);
}
@ -179,12 +169,10 @@ mod tests {
name @include(if: true) { isAlsoHumanName }
}
"#,
&[
RuleError::new(
&no_allowed_error_message("name", "String"),
&[SourcePosition::new(82, 2, 12)],
),
],
&[RuleError::new(
&no_allowed_error_message("name", "String"),
&[SourcePosition::new(82, 2, 12)],
)],
);
}
@ -197,12 +185,10 @@ mod tests {
doesKnowCommand(dogCommand: SIT) @include(if: true) { sinceWhen }
}
"#,
&[
RuleError::new(
&no_allowed_error_message("doesKnowCommand", "Boolean"),
&[SourcePosition::new(89, 2, 12)],
),
],
&[RuleError::new(
&no_allowed_error_message("doesKnowCommand", "Boolean"),
&[SourcePosition::new(89, 2, 12)],
)],
);
}

View file

@ -1,8 +1,8 @@
use std::collections::hash_map::{Entry, HashMap};
use ast::{Directive, Field, InputValue};
use validation::{ValidatorContext, Visitor};
use parser::{SourcePosition, Spanning};
use validation::{ValidatorContext, Visitor};
pub struct UniqueArgumentNames<'a> {
known_names: HashMap<&'a str, SourcePosition>,
@ -171,15 +171,13 @@ mod tests {
field(arg1: "value", arg1: "value")
}
"#,
&[
RuleError::new(
&error_message("arg1"),
&[
SourcePosition::new(31, 2, 18),
SourcePosition::new(46, 2, 33),
],
),
],
&[RuleError::new(
&error_message("arg1"),
&[
SourcePosition::new(31, 2, 18),
SourcePosition::new(46, 2, 33),
],
)],
);
}
@ -220,15 +218,13 @@ mod tests {
field @directive(arg1: "value", arg1: "value")
}
"#,
&[
RuleError::new(
&error_message("arg1"),
&[
SourcePosition::new(42, 2, 29),
SourcePosition::new(57, 2, 44),
],
),
],
&[RuleError::new(
&error_message("arg1"),
&[
SourcePosition::new(42, 2, 29),
SourcePosition::new(57, 2, 44),
],
)],
);
}

View file

@ -143,15 +143,13 @@ mod tests {
fieldB
}
"#,
&[
RuleError::new(
&duplicate_message("fragA"),
&[
SourcePosition::new(65, 4, 19),
SourcePosition::new(131, 7, 19),
],
),
],
&[RuleError::new(
&duplicate_message("fragA"),
&[
SourcePosition::new(65, 4, 19),
SourcePosition::new(131, 7, 19),
],
)],
);
}
@ -167,15 +165,13 @@ mod tests {
fieldB
}
"#,
&[
RuleError::new(
&duplicate_message("fragA"),
&[
SourcePosition::new(20, 1, 19),
SourcePosition::new(86, 4, 19),
],
),
],
&[RuleError::new(
&duplicate_message("fragA"),
&[
SourcePosition::new(20, 1, 19),
SourcePosition::new(86, 4, 19),
],
)],
);
}
}

View file

@ -1,8 +1,8 @@
use std::collections::hash_map::{Entry, HashMap};
use ast::InputValue;
use validation::{ValidatorContext, Visitor};
use parser::{SourcePosition, Spanning};
use validation::{ValidatorContext, Visitor};
pub struct UniqueInputFieldNames<'a> {
known_name_stack: Vec<HashMap<&'a str, SourcePosition>>,
@ -128,15 +128,13 @@ mod tests {
field(arg: { f1: "value", f1: "value" })
}
"#,
&[
RuleError::new(
&error_message("f1"),
&[
SourcePosition::new(38, 2, 25),
SourcePosition::new(51, 2, 38),
],
),
],
&[RuleError::new(
&error_message("f1"),
&[
SourcePosition::new(38, 2, 25),
SourcePosition::new(51, 2, 38),
],
)],
);
}

View file

@ -142,15 +142,13 @@ mod tests {
fieldB
}
"#,
&[
RuleError::new(
&error_message("Foo"),
&[
SourcePosition::new(11, 1, 10),
SourcePosition::new(64, 4, 10),
],
),
],
&[RuleError::new(
&error_message("Foo"),
&[
SourcePosition::new(11, 1, 10),
SourcePosition::new(64, 4, 10),
],
)],
);
}
@ -166,15 +164,13 @@ mod tests {
fieldB
}
"#,
&[
RuleError::new(
&error_message("Foo"),
&[
SourcePosition::new(11, 1, 10),
SourcePosition::new(64, 4, 10),
],
),
],
&[RuleError::new(
&error_message("Foo"),
&[
SourcePosition::new(11, 1, 10),
SourcePosition::new(64, 4, 10),
],
)],
);
}
}

View file

@ -383,15 +383,13 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("intArg", "Int", "Int!"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(117, 3, 48),
],
),
],
&[RuleError::new(
&error_message("intArg", "Int", "Int!"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(117, 3, 48),
],
)],
);
}
@ -410,15 +408,13 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("intArg", "Int", "Int!"),
&[
SourcePosition::new(154, 5, 22),
SourcePosition::new(110, 2, 46),
],
),
],
&[RuleError::new(
&error_message("intArg", "Int", "Int!"),
&[
SourcePosition::new(154, 5, 22),
SourcePosition::new(110, 2, 46),
],
)],
);
}
@ -441,15 +437,13 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("intArg", "Int", "Int!"),
&[
SourcePosition::new(255, 9, 22),
SourcePosition::new(211, 6, 46),
],
),
],
&[RuleError::new(
&error_message("intArg", "Int", "Int!"),
&[
SourcePosition::new(255, 9, 22),
SourcePosition::new(211, 6, 46),
],
)],
);
}
@ -464,15 +458,13 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringVar", "String", "Boolean"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(117, 3, 42),
],
),
],
&[RuleError::new(
&error_message("stringVar", "String", "Boolean"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(117, 3, 42),
],
)],
);
}
@ -487,15 +479,13 @@ mod tests {
}
}
"#,
&[
RuleError::new(
&error_message("stringVar", "String", "[String]"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(123, 3, 48),
],
),
],
&[RuleError::new(
&error_message("stringVar", "String", "[String]"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(123, 3, 48),
],
)],
);
}
@ -508,15 +498,13 @@ mod tests {
dog @include(if: $boolVar)
}
"#,
&[
RuleError::new(
&error_message("boolVar", "Boolean", "Boolean!"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(73, 2, 29),
],
),
],
&[RuleError::new(
&error_message("boolVar", "Boolean", "Boolean!"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(73, 2, 29),
],
)],
);
}
@ -529,15 +517,13 @@ mod tests {
dog @include(if: $stringVar)
}
"#,
&[
RuleError::new(
&error_message("stringVar", "String", "Boolean!"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(74, 2, 29),
],
),
],
&[RuleError::new(
&error_message("stringVar", "String", "Boolean!"),
&[
SourcePosition::new(23, 1, 22),
SourcePosition::new(74, 2, 29),
],
)],
);
}
}

View file

@ -1,10 +1,10 @@
use parser::parse_document_source;
use ast::{FromInputValue, InputValue};
use types::base::GraphQLType;
use executor::Registry;
use types::scalars::{EmptyMutation, ID};
use schema::model::{DirectiveLocation, DirectiveType, RootNode};
use parser::parse_document_source;
use schema::meta::{EnumValue, MetaType};
use schema::model::{DirectiveLocation, DirectiveType, RootNode};
use types::base::GraphQLType;
use types::scalars::{EmptyMutation, ID};
use validation::{visit, MultiVisitor, MultiVisitorNil, RuleError, ValidatorContext, Visitor};
struct Being;
@ -60,11 +60,9 @@ impl GraphQLType for Being {
}
fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> {
let fields = &[
registry
.field::<Option<String>>("name", i)
.argument(registry.arg::<Option<bool>>("surname", i)),
];
let fields = &[registry
.field::<Option<String>>("name", i)
.argument(registry.arg::<Option<bool>>("surname", i))];
registry.build_interface_type::<Self>(i, fields).into_meta()
}
@ -79,11 +77,9 @@ impl GraphQLType for Pet {
}
fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> {
let fields = &[
registry
.field::<Option<String>>("name", i)
.argument(registry.arg::<Option<bool>>("surname", i)),
];
let fields = &[registry
.field::<Option<String>>("name", i)
.argument(registry.arg::<Option<bool>>("surname", i))];
registry.build_interface_type::<Self>(i, fields).into_meta()
}
@ -98,11 +94,9 @@ impl GraphQLType for Canine {
}
fn meta<'r>(i: &(), registry: &mut Registry<'r>) -> MetaType<'r> {
let fields = &[
registry
.field::<Option<String>>("name", i)
.argument(registry.arg::<Option<bool>>("surname", i)),
];
let fields = &[registry
.field::<Option<String>>("name", i)
.argument(registry.arg::<Option<bool>>("surname", i))];
registry.build_interface_type::<Self>(i, fields).into_meta()
}

View file

@ -3,8 +3,8 @@ use std::borrow::Cow;
use ast::{Arguments, Definition, Directive, Document, Field, Fragment, FragmentSpread,
InlineFragment, InputValue, Operation, OperationType, Selection, Type,
VariableDefinitions};
use schema::meta::Argument;
use parser::Spanning;
use schema::meta::Argument;
use validation::{ValidatorContext, Visitor};
#[doc(hidden)]

View file

@ -1,8 +1,8 @@
use indexmap::IndexMap;
use std::hash::Hash;
use parser::Spanning;
use ast::{InputValue, ToInputValue};
use parser::Spanning;
/// Serializable value returned from query and field execution.
///
@ -13,7 +13,7 @@ use ast::{InputValue, ToInputValue};
/// values or variables. Also, lists and objects do not contain any location
/// information since they are generated by resolving fields and values rather
/// than parsing a source query.
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
#[allow(missing_docs)]
pub enum Value {
Null,
@ -276,7 +276,7 @@ mod tests {
Value::object(
vec![("key", Value::int(123)), ("next", Value::boolean(true))]
.into_iter()
.collect()
.collect(),
)
);
}

View file

@ -14,8 +14,10 @@ repository = "https://github.com/graphql-rust/juniper"
proc-macro = true
[dependencies]
syn = "0.11"
quote = "0.3"
syn = { version = "0.13.*", features = ["full", "extra-traits"] }
quote = "0.5.*"
regex = "0.2.10"
lazy_static = "1.0.0"
[badges]
travis-ci = { repository = "graphql-rust/juniper" }

View file

@ -1,5 +1,13 @@
use syn;
use syn::*;
use syn::{
DeriveInput,
Meta,
NestedMeta,
Data,
Fields,
Ident,
Variant,
};
use quote::Tokens;
use util::*;
@ -23,16 +31,21 @@ impl EnumAttrs {
// Check attributes for name and description.
if let Some(items) = get_graphl_attr(&input.attrs) {
for item in items {
if let Some(val) = keyed_item_value(item, "name", true) {
res.name = Some(val);
continue;
if let Some(val) = keyed_item_value(&item, "name", true) {
if is_valid_name(&*val) {
res.name = Some(val);
continue;
} else {
panic!("Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{}\" does not",
&*val);
}
}
if let Some(val) = keyed_item_value(item, "description", true) {
if let Some(val) = keyed_item_value(&item, "description", true) {
res.description = Some(val);
continue;
}
match item {
&NestedMetaItem::MetaItem(MetaItem::Word(ref ident)) => {
NestedMeta::Meta(Meta::Word(ref ident)) => {
if ident == "_internal" {
res.internal = true;
continue;
@ -64,15 +77,20 @@ impl EnumVariantAttrs {
// Check attributes for name and description.
if let Some(items) = get_graphl_attr(&variant.attrs) {
for item in items {
if let Some(val) = keyed_item_value(item, "name", true) {
res.name = Some(val);
continue;
if let Some(val) = keyed_item_value(&item, "name", true) {
if is_valid_name(&*val) {
res.name = Some(val);
continue;
} else {
panic!("Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{}\" does not",
&*val);
}
}
if let Some(val) = keyed_item_value(item, "description", true) {
if let Some(val) = keyed_item_value(&item, "description", true) {
res.description = Some(val);
continue;
}
if let Some(val) = keyed_item_value(item, "deprecated", true) {
if let Some(val) = keyed_item_value(&item, "deprecated", true) {
res.deprecation = Some(val);
continue;
}
@ -87,9 +105,9 @@ impl EnumVariantAttrs {
}
pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
let variants = match ast.body {
Body::Enum(ref var) => var,
Body::Struct(_) => {
let variants = match ast.data {
Data::Enum(ref enum_data) => enum_data.variants.iter().collect::<Vec<_>>(),
_ => {
panic!("#[derive(GraphlQLEnum)] may only be applied to enums, not to structs");
}
};
@ -110,12 +128,16 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
let mut to_inputs = Vec::<Tokens>::new();
for variant in variants {
if variant.data != VariantData::Unit {
panic!(format!(
"Invalid enum variant {}.\nGraphQL enums may only contain unit variants.",
variant.ident
));
}
match variant.fields {
Fields::Unit => {},
_ => {
panic!(format!(
"Invalid enum variant {}.\nGraphQL enums may only contain unit variants.",
variant.ident
));
}
} ;
let var_attrs = EnumVariantAttrs::from_input(variant);
let var_ident = &variant.ident;
@ -209,7 +231,7 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
}
};
let dummy_const = Ident::new(format!("_IMPL_GRAPHQLENUM_FOR_{}", ident));
let dummy_const = Ident::from(format!("_IMPL_GRAPHQLENUM_FOR_{}", ident).as_str());
// This ugly hack makes it possible to use the derive inside juniper itself.
// FIXME: Figure out a better way to do this!

View file

@ -1,6 +1,16 @@
use syn;
use syn::*;
use quote::Tokens;
use std::str::FromStr;
use syn::{
self,
DeriveInput,
NestedMeta,
Meta,
Field,
Fields,
Data,
Ident,
};
use quote::{Tokens, ToTokens};
use util::*;
@ -18,16 +28,21 @@ impl ObjAttrs {
// Check attributes for name and description.
if let Some(items) = get_graphl_attr(&input.attrs) {
for item in items {
if let Some(val) = keyed_item_value(item, "name", true) {
res.name = Some(val);
continue;
if let Some(val) = keyed_item_value(&item, "name", true) {
if is_valid_name(&*val) {
res.name = Some(val);
continue;
} else {
panic!("Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{}\" does not",
&*val);
}
}
if let Some(val) = keyed_item_value(item, "description", true) {
if let Some(val) = keyed_item_value(&item, "description", true) {
res.description = Some(val);
continue;
}
match item {
&NestedMetaItem::MetaItem(MetaItem::Word(ref ident)) => {
NestedMeta::Meta(Meta::Word(ref ident)) => {
if ident == "_internal" {
res.internal = true;
continue;
@ -60,20 +75,25 @@ impl ObjFieldAttrs {
// Check attributes for name and description.
if let Some(items) = get_graphl_attr(&variant.attrs) {
for item in items {
if let Some(val) = keyed_item_value(item, "name", true) {
res.name = Some(val);
continue;
if let Some(val) = keyed_item_value(&item, "name", true) {
if is_valid_name(&*val) {
res.name = Some(val);
continue;
} else {
panic!("Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{}\" does not",
&*val);
}
}
if let Some(val) = keyed_item_value(item, "description", true) {
if let Some(val) = keyed_item_value(&item, "description", true) {
res.description = Some(val);
continue;
}
if let Some(val) = keyed_item_value(item, "default", true) {
if let Some(val) = keyed_item_value(&item, "default", true) {
res.default_expr = Some(val);
continue;
}
match item {
&NestedMetaItem::MetaItem(MetaItem::Word(ref ident)) => {
NestedMeta::Meta(Meta::Word(ref ident)) => {
if ident == "default" {
res.default = true;
continue;
@ -92,16 +112,16 @@ impl ObjFieldAttrs {
}
pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
let fields = match ast.body {
Body::Struct(ref data) => match data {
&VariantData::Struct(ref fields) => fields,
let fields = match ast.data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref named) => named.named.iter().collect::<Vec<_>>(),
_ => {
panic!(
"#[derive(GraphQLInputObject)] may only be used on regular structs with fields"
);
}
},
Body::Enum(_) => {
_ => {
panic!("#[derive(GraphlQLInputObject)] may only be applied to structs, not to enums");
}
};
@ -146,8 +166,17 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
Some(quote! { Default::default() })
} else {
match field_attrs.default_expr {
Some(ref def) => match syn::parse_token_trees(def) {
Ok(t) => Some(quote! { #(#t)* }),
Some(ref def) => match ::proc_macro::TokenStream::from_str(def) {
Ok(t) => {
match syn::parse::<syn::Expr>(t) {
Ok(e) => {
Some(e.into_tokens())
},
Err(_) => {
panic!("#graphql(default = ?) must be a valid Rust expression inside a string");
},
}
},
Err(_) => {
panic!("#graphql(default = ?) must be a valid Rust expression inside a string");
}
@ -256,7 +285,7 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
}
};
let dummy_const = Ident::new(format!("_IMPL_GRAPHQLINPUTOBJECT_FOR_{}", ident));
let dummy_const = Ident::from(format!("_IMPL_GRAPHQLINPUTOBJECT_FOR_{}", ident).as_str());
// This ugly hack makes it possible to use the derive inside juniper itself.
// FIXME: Figure out a better way to do this!

View file

@ -1,5 +1,10 @@
use syn;
use syn::*;
use syn::{
DeriveInput,
Data,
Fields,
Field,
};
use quote::Tokens;
use util::*;
@ -17,11 +22,16 @@ impl ObjAttrs {
// Check attributes for name and description.
if let Some(items) = get_graphl_attr(&input.attrs) {
for item in items {
if let Some(val) = keyed_item_value(item, "name", true) {
res.name = Some(val);
continue;
if let Some(val) = keyed_item_value(&item, "name", true) {
if is_valid_name(&*val) {
res.name = Some(val);
continue;
} else {
panic!("Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{}\" does not",
&*val);
}
}
if let Some(val) = keyed_item_value(item, "description", true) {
if let Some(val) = keyed_item_value(&item, "description", true) {
res.description = Some(val);
continue;
}
@ -49,15 +59,20 @@ impl ObjFieldAttrs {
// Check attributes for name and description.
if let Some(items) = get_graphl_attr(&variant.attrs) {
for item in items {
if let Some(val) = keyed_item_value(item, "name", true) {
res.name = Some(val);
continue;
if let Some(val) = keyed_item_value(&item, "name", true) {
if is_valid_name(&*val) {
res.name = Some(val);
continue;
} else {
panic!("Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ but \"{}\" does not",
&*val);
}
}
if let Some(val) = keyed_item_value(item, "description", true) {
if let Some(val) = keyed_item_value(&item, "description", true) {
res.description = Some(val);
continue;
}
if let Some(val) = keyed_item_value(item, "deprecation", true) {
if let Some(val) = keyed_item_value(&item, "deprecation", true) {
res.deprecation = Some(val);
continue;
}
@ -72,14 +87,14 @@ impl ObjFieldAttrs {
}
pub fn impl_object(ast: &syn::DeriveInput) -> Tokens {
let fields = match ast.body {
Body::Struct(ref data) => match data {
&VariantData::Struct(ref fields) => fields,
let fields = match ast.data {
Data::Struct(ref data) => match data.fields {
Fields::Named(ref fields) => fields.named.iter().collect::<Vec<_>>(),
_ => {
panic!("#[derive(GraphQLObject)] may only be used on regular structs with fields");
}
},
Body::Enum(_) => {
_ => {
panic!("#[derive(GraphlQLObject)] may only be applied to structs, not to enums");
}
};

View file

@ -10,6 +10,9 @@ extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;
#[macro_use]
extern crate lazy_static;
extern crate regex;
mod util;
mod derive_enum;
@ -20,24 +23,21 @@ use proc_macro::TokenStream;
#[proc_macro_derive(GraphQLEnum, attributes(graphql))]
pub fn derive_enum(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
let gen = derive_enum::impl_enum(&ast);
gen.parse().unwrap()
gen.into()
}
#[proc_macro_derive(GraphQLInputObject, attributes(graphql))]
pub fn derive_input_object(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
let gen = derive_input_object::impl_input_object(&ast);
gen.parse().unwrap()
gen.into()
}
#[proc_macro_derive(GraphQLObject, attributes(graphql))]
pub fn derive_object(input: TokenStream) -> TokenStream {
let s = input.to_string();
let ast = syn::parse_derive_input(&s).unwrap();
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
let gen = derive_object::impl_object(&ast);
gen.parse().unwrap()
gen.into()
}

View file

@ -1,10 +1,17 @@
use syn::*;
use syn::{
Attribute,
Meta,
NestedMeta,
Lit,
};
use regex::Regex;
pub fn get_graphl_attr(attrs: &Vec<Attribute>) -> Option<&Vec<NestedMetaItem>> {
// Get the nested items of a a #[graphql(...)] attribute.
pub fn get_graphl_attr(attrs: &Vec<Attribute>) -> Option<Vec<NestedMeta>> {
for attr in attrs {
match attr.value {
MetaItem::List(ref attr_name, ref items) => if attr_name == "graphql" {
return Some(items);
match attr.interpret_meta() {
Some(Meta::List(ref list)) if list.ident == "graphql" => {
return Some(list.nested.iter().map(|x| x.clone()).collect());
},
_ => {}
}
@ -12,33 +19,24 @@ pub fn get_graphl_attr(attrs: &Vec<Attribute>) -> Option<&Vec<NestedMetaItem>> {
None
}
pub fn keyed_item_value(item: &NestedMetaItem, name: &str, must_be_string: bool) -> Option<String> {
let item = match item {
&NestedMetaItem::MetaItem(ref item) => item,
_ => {
return None;
}
};
let lit = match item {
&MetaItem::NameValue(ref ident, ref lit) => if ident == name {
lit
} else {
return None;
},
_ => {
return None;
}
};
match lit {
&Lit::Str(ref val, _) => Some(val.clone()),
_ => if must_be_string {
panic!(format!(
"Invalid format for attribute \"{:?}\": expected a string",
item
));
} else {
None
pub fn keyed_item_value(item: &NestedMeta, name: &str, must_be_string: bool) -> Option<String> {
match item {
&NestedMeta::Meta(Meta::NameValue(ref nameval)) if nameval.ident == name => {
match &nameval.lit {
&Lit::Str(ref strlit) => {
Some(strlit.value())
},
_ => if must_be_string {
panic!(format!(
"Invalid format for attribute \"{:?}\": expected a string",
item
));
} else {
None
},
}
},
_ => None,
}
}
@ -114,3 +112,24 @@ fn test_to_upper_snake_case() {
assert_eq!(to_upper_snake_case("someINpuT"), "SOME_INPU_T");
assert_eq!(to_upper_snake_case("some_INpuT"), "SOME_INPU_T");
}
#[doc(hidden)]
pub fn is_valid_name(field_name: &str) -> bool {
lazy_static!{
static ref GRAPHQL_NAME_SPEC: Regex = Regex::new("^[_A-Za-z][_0-9A-Za-z]*$").unwrap();
}
GRAPHQL_NAME_SPEC.is_match(field_name)
}
#[test]
fn test_is_valid_name(){
assert_eq!(is_valid_name("yesItIs"), true);
assert_eq!(is_valid_name("NoitIsnt"), true);
assert_eq!(is_valid_name("iso6301"), true);
assert_eq!(is_valid_name("thisIsATest"), true);
assert_eq!(is_valid_name("i6Op"), true);
assert_eq!(is_valid_name("i!"), false);
assert_eq!(is_valid_name(""), false);
assert_eq!(is_valid_name("aTest"), true);
assert_eq!(is_valid_name("__Atest90"), true);
}

View file

@ -37,7 +37,7 @@ fn main() {
chain.link_before(logger_before);
chain.link_after(logger_after);
let host = env::var("LISTEN").unwrap_or("0.0.0.0:8080".to_owned());
let host = env::var("LISTEN").unwrap_or_else(|_| "0.0.0.0:8080".to_owned());
println!("GraphQL server started on {}", host);
Iron::new(chain).http(host.as_str()).unwrap();
}

View file

@ -125,7 +125,7 @@ use serde_json::error::Error as SerdeError;
use juniper::{GraphQLType, InputValue, RootNode};
use juniper::http::{self, ExecutionResponse, Executable};
/// Handler that executes GraphQL queries in the given schema
/// Handler that executes `GraphQL` queries in the given schema
///
/// The handler responds to GET requests and POST requests only. In GET
/// requests, the query should be supplied in the `query` URL parameter, e.g.
@ -146,7 +146,7 @@ where
root_node: RootNode<'a, Query, Mutation>,
}
/// Handler that renders GraphiQL - a graphical query editor interface
/// Handler that renders `GraphiQL` - a graphical query editor interface
pub struct GraphiQLHandler {
graphql_url: String,
}
@ -201,7 +201,7 @@ where
fn handle_get(&self, req: &mut Request) -> IronResult<http::GraphQLBatchRequest> {
let url_query_string = req.get_mut::<UrlEncodedQuery>()
.map_err(|e| GraphQLIronError::Url(e))?;
.map_err(GraphQLIronError::Url)?;
let input_query = parse_url_param(url_query_string.remove("query"))?
.ok_or_else(|| GraphQLIronError::InvalidData("No query provided"))?;
@ -220,8 +220,8 @@ where
itry!(req.body.read_to_string(&mut request_payload));
Ok(
serde_json::from_str::<http::GraphQLBatchRequest>(request_payload.as_str())
.map_err(|err| GraphQLIronError::Serde(err))?,
serde_json::from_str::<http::GraphQLRequest>(request_payload.as_str())
.map_err(GraphQLIronError::Serde)?,
)
}
@ -296,7 +296,7 @@ impl fmt::Display for GraphQLIronError {
match *self {
GraphQLIronError::Serde(ref err) => fmt::Display::fmt(err, &mut f),
GraphQLIronError::Url(ref err) => fmt::Display::fmt(err, &mut f),
GraphQLIronError::InvalidData(ref err) => fmt::Display::fmt(err, &mut f),
GraphQLIronError::InvalidData(err) => fmt::Display::fmt(err, &mut f),
}
}
}
@ -306,7 +306,7 @@ impl Error for GraphQLIronError {
match *self {
GraphQLIronError::Serde(ref err) => err.description(),
GraphQLIronError::Url(ref err) => err.description(),
GraphQLIronError::InvalidData(ref err) => err,
GraphQLIronError::InvalidData(err) => err,
}
}

View file

@ -16,8 +16,8 @@ serde_derive = {version="1.0.2" }
serde_json = { version = "1.0.2" }
juniper = { version = "0.9.2" , path = "../juniper"}
rocket = { version = "0.3.6" }
rocket_codegen = { version = "0.3.6" }
rocket = { version = "0.3.9" }
rocket_codegen = { version = "0.3.9" }
[dev-dependencies.juniper]
version = "0.9.2"

View file

@ -8,8 +8,7 @@ use juniper::{self, FromInputValue, GraphQLType, InputValue, ToInputValue};
#[graphql(name = "Some", description = "enum descr")]
enum SomeEnum {
Regular,
#[graphql(name = "full", description = "field descr", deprecated = "depr")] Full,
#[graphql(name = "FULL", description = "field descr", deprecated = "depr")] Full,
}
#[test]
@ -37,10 +36,10 @@ fn test_derived_enum() {
// Test FULL variant.
assert_eq!(
SomeEnum::Full.to_input_value(),
InputValue::String("full".into())
InputValue::String("FULL".into())
);
assert_eq!(
FromInputValue::from_input_value(&InputValue::String("full".into())),
FromInputValue::from_input_value(&InputValue::String("FULL".into())),
Some(SomeEnum::Full)
);
}