This commit is contained in:
Koxiaet 2020-09-06 07:16:36 +01:00
parent fca8f6e991
commit c055736101
40 changed files with 292 additions and 207 deletions

View File

@ -5,17 +5,17 @@
//! it into Rust types.
#![forbid(unsafe_code)]
use std::fmt;
use pest::RuleType;
use pest::error::LineColLocation;
use pest::RuleType;
use std::fmt;
pub use pos::{Pos, Positioned};
pub use parser::parse_query;
pub use pos::{Pos, Positioned};
pub mod types;
mod pos;
mod parser;
mod pos;
mod utils;
/// Parser error.
@ -40,7 +40,8 @@ impl<R: RuleType> From<pest::error::Error<R>> for Error {
Error {
pos: {
match err.line_col {
LineColLocation::Pos((line, column)) | LineColLocation::Span((line, column), _) => Pos { line, column },
LineColLocation::Pos((line, column))
| LineColLocation::Span((line, column), _) => Pos { line, column },
}
},
message: err.to_string(),

View File

@ -1,6 +1,6 @@
use crate::pos::Positioned;
use crate::types::*;
use crate::utils::{string_value, block_string_value, PositionCalculator};
use crate::utils::{block_string_value, string_value, PositionCalculator};
use crate::Result;
use pest::iterators::{Pair, Pairs};
use pest::Parser;
@ -17,21 +17,25 @@ struct GraphQLParser;
/// Fails if the query is not a valid GraphQL document.
pub fn parse_query<T: AsRef<str>>(input: T) -> Result<Document> {
let mut pc = PositionCalculator::new(input.as_ref());
Ok(parse_document(exactly_one(GraphQLParser::parse(Rule::document, input.as_ref())?), &mut pc))
Ok(parse_document(
exactly_one(GraphQLParser::parse(Rule::document, input.as_ref())?),
&mut pc,
))
}
fn parse_document(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Document {
debug_assert_eq!(pair.as_rule(), Rule::document);
Document {
definitions: pair.into_inner().filter(|pair| pair.as_rule() != Rule::EOI).map(|pair| parse_definition(pair, pc)).collect(),
definitions: pair
.into_inner()
.filter(|pair| pair.as_rule() != Rule::EOI)
.map(|pair| parse_definition(pair, pc))
.collect(),
}
}
fn parse_definition(
pair: Pair<Rule>,
pc: &mut PositionCalculator,
) -> Definition {
fn parse_definition(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Definition {
debug_assert_eq!(pair.as_rule(), Rule::definition);
let pair = exactly_one(pair.into_inner());
@ -50,17 +54,20 @@ fn parse_operation_definition(
let pos = pc.step(&pair);
let pair = exactly_one(pair.into_inner());
Positioned::new(match pair.as_rule() {
Rule::named_operation_definition => parse_named_operation_definition(pair, pc),
Rule::selection_set => OperationDefinition {
ty: OperationType::Query,
name: None,
variable_definitions: Vec::new(),
directives: Vec::new(),
selection_set: parse_selection_set(pair, pc),
Positioned::new(
match pair.as_rule() {
Rule::named_operation_definition => parse_named_operation_definition(pair, pc),
Rule::selection_set => OperationDefinition {
ty: OperationType::Query,
name: None,
variable_definitions: Vec::new(),
directives: Vec::new(),
selection_set: parse_selection_set(pair, pc),
},
_ => unreachable!(),
},
_ => unreachable!(),
}, pos)
pos,
)
}
fn parse_named_operation_definition(
@ -73,8 +80,10 @@ fn parse_named_operation_definition(
let ty = parse_operation_type(&pairs.next().unwrap(), pc);
let name = next_if_rule(&mut pairs, Rule::name).map(|pair| parse_name(&pair, pc));
let variable_definitions = next_if_rule(&mut pairs, Rule::variable_definitions).map(|pair| parse_variable_definitions(pair, pc));
let directives = next_if_rule(&mut pairs, Rule::directives).map(|pair| parse_directives(pair, pc));
let variable_definitions = next_if_rule(&mut pairs, Rule::variable_definitions)
.map(|pair| parse_variable_definitions(pair, pc));
let directives =
next_if_rule(&mut pairs, Rule::directives).map(|pair| parse_directives(pair, pc));
let selection_set = parse_selection_set(pairs.next().unwrap(), pc);
debug_assert_eq!(pairs.next(), None);
@ -84,21 +93,27 @@ fn parse_named_operation_definition(
name,
variable_definitions: variable_definitions.unwrap_or_default(),
directives: directives.unwrap_or_default(),
selection_set
selection_set,
}
}
fn parse_operation_type(pair: &Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<OperationType> {
fn parse_operation_type(
pair: &Pair<Rule>,
pc: &mut PositionCalculator,
) -> Positioned<OperationType> {
debug_assert_eq!(pair.as_rule(), Rule::operation_type);
let pos = pc.step(&pair);
Positioned::new(match pair.as_str() {
"query" => OperationType::Query,
"mutation" => OperationType::Mutation,
"subscription" => OperationType::Subscription,
_ => unreachable!(),
}, pos)
Positioned::new(
match pair.as_str() {
"query" => OperationType::Query,
"mutation" => OperationType::Mutation,
"subscription" => OperationType::Subscription,
_ => unreachable!(),
},
pos,
)
}
fn parse_variable_definitions(
@ -107,7 +122,9 @@ fn parse_variable_definitions(
) -> Vec<Positioned<VariableDefinition>> {
debug_assert_eq!(pair.as_rule(), Rule::variable_definitions);
pair.into_inner().map(|pair| parse_variable_definition(pair, pc)).collect()
pair.into_inner()
.map(|pair| parse_variable_definition(pair, pc))
.collect()
}
fn parse_variable_definition(
@ -162,7 +179,9 @@ fn parse_value(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<Valu
Positioned::new(
match pair.as_rule() {
Rule::variable => Value::Variable(parse_variable(pair, pc).node),
Rule::float | Rule::int => Value::Number(pair.as_str().parse().expect("failed to parse number")),
Rule::float | Rule::int => {
Value::Number(pair.as_str().parse().expect("failed to parse number"))
}
Rule::string => Value::String({
let pair = exactly_one(pair.into_inner());
match pair.as_rule() {
@ -213,10 +232,7 @@ fn parse_name_value(
(name, value)
}
fn parse_selection_set(
pair: Pair<Rule>,
pc: &mut PositionCalculator,
) -> Positioned<SelectionSet> {
fn parse_selection_set(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<SelectionSet> {
debug_assert_eq!(pair.as_rule(), Rule::selection_set);
let pos = pc.step(&pair);
@ -238,12 +254,15 @@ fn parse_selection(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<
let pos = pc.step(&pair);
let pair = exactly_one(pair.into_inner());
Positioned::new(match pair.as_rule() {
Rule::field => Selection::Field(parse_field(pair, pc)),
Rule::fragment_spread => Selection::FragmentSpread(parse_fragment_spread(pair, pc)),
Rule::inline_fragment => Selection::InlineFragment(parse_inline_fragment(pair, pc)),
_ => unreachable!(),
}, pos)
Positioned::new(
match pair.as_rule() {
Rule::field => Selection::Field(parse_field(pair, pc)),
Rule::fragment_spread => Selection::FragmentSpread(parse_fragment_spread(pair, pc)),
Rule::inline_fragment => Selection::InlineFragment(parse_inline_fragment(pair, pc)),
_ => unreachable!(),
},
pos,
)
}
fn parse_field(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<Field> {
@ -252,19 +271,13 @@ fn parse_field(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<Fiel
let pos = pc.step(&pair);
let mut pairs = pair.into_inner();
let alias = next_if_rule(&mut pairs, Rule::alias)
.map(|pair| parse_alias(pair, pc))
;
let alias = next_if_rule(&mut pairs, Rule::alias).map(|pair| parse_alias(pair, pc));
let name = parse_name(&pairs.next().unwrap(), pc);
let arguments = next_if_rule(&mut pairs, Rule::arguments)
.map(|pair| parse_arguments(pair, pc))
;
let directives = next_if_rule(&mut pairs, Rule::directives)
.map(|pair| parse_directives(pair, pc))
;
let selection_set = next_if_rule(&mut pairs, Rule::selection_set)
.map(|pair| parse_selection_set(pair, pc))
;
let arguments = next_if_rule(&mut pairs, Rule::arguments).map(|pair| parse_arguments(pair, pc));
let directives =
next_if_rule(&mut pairs, Rule::directives).map(|pair| parse_directives(pair, pc));
let selection_set =
next_if_rule(&mut pairs, Rule::selection_set).map(|pair| parse_selection_set(pair, pc));
Positioned::new(
Field {
@ -303,10 +316,7 @@ fn parse_fragment_spread(
let mut pairs = pair.into_inner();
let fragment_name = parse_name(&pairs.next().unwrap(), pc);
let directives = pairs
.next()
.map(|pair| parse_directives(pair, pc))
;
let directives = pairs.next().map(|pair| parse_directives(pair, pc));
debug_assert_eq!(pairs.peek(), None);
@ -328,12 +338,10 @@ fn parse_inline_fragment(
let pos = pc.step(&pair);
let mut pairs = pair.into_inner();
let type_condition = next_if_rule(&mut pairs, Rule::type_condition)
.map(|pair| parse_type_condition(pair, pc))
;
let directives = next_if_rule(&mut pairs, Rule::directives)
.map(|pair| parse_directives(pair, pc))
;
let type_condition =
next_if_rule(&mut pairs, Rule::type_condition).map(|pair| parse_type_condition(pair, pc));
let directives =
next_if_rule(&mut pairs, Rule::directives).map(|pair| parse_directives(pair, pc));
let selection_set = parse_selection_set(pairs.next().unwrap(), pc);
debug_assert_eq!(pairs.next(), None);
@ -359,14 +367,12 @@ fn parse_fragment_definition(
let name = parse_name(&pairs.next().unwrap(), pc);
let type_condition = parse_type_condition(pairs.next().unwrap(), pc);
let directives = next_if_rule(&mut pairs, Rule::directives)
.map(|pair| parse_directives(pair, pc))
;
let directives =
next_if_rule(&mut pairs, Rule::directives).map(|pair| parse_directives(pair, pc));
let selection_set = parse_selection_set(pairs.next().unwrap(), pc);
debug_assert_eq!(pairs.next(), None);
Positioned::new(
FragmentDefinition {
name,
@ -393,13 +399,12 @@ fn parse_type_condition(
)
}
fn parse_directives(
pair: Pair<Rule>,
pc: &mut PositionCalculator,
) -> Vec<Positioned<Directive>> {
fn parse_directives(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Vec<Positioned<Directive>> {
debug_assert_eq!(pair.as_rule(), Rule::directives);
pair.into_inner().map(|pair| parse_directive(pair, pc)).collect()
pair.into_inner()
.map(|pair| parse_directive(pair, pc))
.collect()
}
fn parse_directive(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<Directive> {
@ -409,9 +414,7 @@ fn parse_directive(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Positioned<
let mut pairs = pair.into_inner();
let name = parse_name(&pairs.next().unwrap(), pc);
let arguments = pairs
.next()
.map(|pair| parse_arguments(pair, pc));
let arguments = pairs.next().map(|pair| parse_arguments(pair, pc));
debug_assert_eq!(pairs.peek(), None);

View File

@ -1,9 +1,9 @@
//! GraphQL types.
use crate::pos::{Pos, Positioned};
use std::fmt::{self, Formatter, Write};
use serde::{Serialize, Serializer};
use std::collections::{HashMap, BTreeMap};
use std::collections::{BTreeMap, HashMap};
use std::fmt::{self, Formatter, Write};
use std::fs::File;
/// A complete GraphQL file or request string.
@ -28,7 +28,15 @@ impl Document {
for definition in self.definitions {
match definition {
Definition::Operation(op) if operation_name.zip(op.node.name.as_ref()).map_or(false, |(required_name, op_name)| required_name != op_name.node) => (),
Definition::Operation(op)
if operation_name
.zip(op.node.name.as_ref())
.map_or(false, |(required_name, op_name)| {
required_name != op_name.node
}) =>
{
()
}
Definition::Operation(op) => {
operation.get_or_insert(op);
}
@ -151,11 +159,16 @@ impl VariableDefinition {
/// `Value::Null` if it is nullable and `None` otherwise.
#[must_use]
pub fn default_value(&self) -> Option<&Value> {
self.default_value.as_ref().map(|value| &value.node).or_else(|| if self.var_type.node.nullable {
Some(&Value::Null)
} else {
None
})
self.default_value
.as_ref()
.map(|value| &value.node)
.or_else(|| {
if self.var_type.node.nullable {
Some(&Value::Null)
} else {
None
}
})
}
}
@ -401,7 +414,6 @@ pub struct SelectionSet {
pub items: Vec<Positioned<Selection>>,
}
/// A part of an object to be selected; a single field, a fragment spread or an inline fragment.
///
/// [Reference](https://spec.graphql.org/June2018/#Selection).

View File

@ -87,14 +87,10 @@ pub(crate) fn block_string_value(raw: &str) -> String {
// Put a newline between each line
.enumerate()
.flat_map(|(i, line)| {
if i == 0 {
[].as_ref()
} else {
['\n'].as_ref()
}
.iter()
.copied()
.chain(line.chars())
if i == 0 { [].as_ref() } else { ['\n'].as_ref() }
.iter()
.copied()
.chain(line.chars())
})
.collect()
}

View File

@ -1,9 +1,9 @@
use crate::parser::types::Field;
use crate::registry::Registry;
use crate::{
registry, Context, ContextSelectionSet, FieldResult, InputValueResult, Positioned, QueryError,
Result, Value,
};
use crate::parser::types::Field;
use std::borrow::Cow;
use std::future::Future;
use std::pin::Pin;

View File

@ -1,9 +1,7 @@
use crate::extensions::Extensions;
use crate::parser::types::{
Directive, ExecutableDocument, Field, SelectionSet, Value,
};
use crate::schema::SchemaEnv;
use crate::base::Type;
use crate::extensions::Extensions;
use crate::parser::types::{Directive, ExecutableDocument, Field, SelectionSet, Value};
use crate::schema::SchemaEnv;
use crate::{FieldResult, InputValueType, Lookahead, Pos, Positioned, QueryError, Result};
use fnv::FnvHashMap;
use serde::ser::SerializeSeq;
@ -405,15 +403,28 @@ impl<'a, T> ContextBase<'a, T> {
_ => continue,
};
let Positioned { node: mut condition_input, pos } = directive.node.get_argument("if").ok_or_else(|| QueryError::RequiredDirectiveArgs {
directive: if include { "@skip" } else { "@include" },
arg_name: "if",
arg_type: "Boolean!",
}.into_error(directive.pos))?.clone();
let Positioned {
node: mut condition_input,
pos,
} = directive
.node
.get_argument("if")
.ok_or_else(|| {
QueryError::RequiredDirectiveArgs {
directive: if include { "@skip" } else { "@include" },
arg_name: "if",
arg_type: "Boolean!",
}
.into_error(directive.pos)
})?
.clone();
self.resolve_input_value(&mut condition_input, pos)?;
if include != <bool as InputValueType>::parse(Some(condition_input)).map_err(|e| e.into_error(pos, bool::qualified_type_name()))? {
if include
!= <bool as InputValueType>::parse(Some(condition_input))
.map_err(|e| e.into_error(pos, bool::qualified_type_name()))?
{
return Ok(true);
}
}
@ -466,8 +477,7 @@ impl<'a> ContextBase<'a, &'a Positioned<Field>> {
Some(value) => (value.pos, Some(self.resolved_input_value(value)?)),
None => (Pos::default(), None),
};
InputValueType::parse(value)
.map_err(|e| e.into_error(pos, T::qualified_type_name()))
InputValueType::parse(value).map_err(|e| e.into_error(pos, T::qualified_type_name()))
}
/// Get the position of the current field in the query code.

View File

@ -1,6 +1,6 @@
use crate::extensions::{Extension, ResolveInfo};
use crate::parser::types::{Definition, Document, OperationType, Selection};
use crate::{Error, Variables};
use crate::parser::types::{Definition, Document, Selection, OperationType};
use itertools::Itertools;
use log::{error, info, trace};
use std::borrow::Cow;

View File

@ -10,8 +10,8 @@ use crate::{Result, Variables};
pub use self::apollo_tracing::ApolloTracing;
pub use self::logger::Logger;
pub use self::tracing::Tracing;
use crate::Error;
use crate::parser::types::Document;
use crate::Error;
use serde_json::Value;
pub(crate) type BoxExtension = Box<dyn Extension>;

View File

@ -141,7 +141,7 @@ pub use error::{
ParseRequestError, QueryError, ResultExt, RuleError,
};
pub use look_ahead::Lookahead;
pub use parser::{Pos, Positioned, types::Value};
pub use parser::{types::Value, Pos, Positioned};
pub use query::{IntoQueryBuilder, IntoQueryBuilderOpts, QueryBuilder, QueryResponse};
pub use registry::CacheControl;
pub use scalars::{Any, Json, OutputJson, ID};

View File

@ -37,7 +37,8 @@ fn find<'a>(
}
}
Selection::InlineFragment(inline_fragment) => {
if let Some(field) = find(document, &inline_fragment.node.selection_set.node, name) {
if let Some(field) = find(document, &inline_fragment.node.selection_set.node, name)
{
return Some(field);
}
}

View File

@ -136,8 +136,11 @@ fn do_resolve<'a, T: ObjectType + Send + Sync>(
continue;
}
if let Some(TypeCondition { on: name }) =
inline_fragment.node.type_condition.as_ref().map(|v| &v.node)
if let Some(TypeCondition { on: name }) = inline_fragment
.node
.type_condition
.as_ref()
.map(|v| &v.node)
{
let mut futures = Vec::new();
root.collect_inline_fields(

View File

@ -2,12 +2,12 @@ use crate::context::{Data, ResolveId};
use crate::error::ParseRequestError;
use crate::extensions::{BoxExtension, ErrorLogger, Extension};
use crate::mutation_resolver::do_mutation_resolve;
use crate::parser::types::{OperationType, UploadValue, Value};
use crate::registry::CacheControl;
use crate::{
do_resolve, ContextBase, Error, ObjectType, Pos, QueryEnv, QueryError, Result, Schema,
SubscriptionType, Variables,
};
use crate::parser::types::{OperationType, Value, UploadValue};
use std::any::Any;
use std::fs::File;
use std::sync::atomic::AtomicUsize;
@ -143,22 +143,24 @@ impl QueryBuilder {
let inc_resolve_id = AtomicUsize::default();
let document = match document.into_executable(self.operation_name.as_deref()) {
Some(document) => document,
None => return if let Some(operation_name) = self.operation_name {
Err(Error::Query {
pos: Pos::default(),
path: None,
err: QueryError::UnknownOperationNamed {
name: operation_name,
},
})
} else {
Err(Error::Query {
pos: Pos::default(),
path: None,
err: QueryError::MissingOperation,
})
None => {
return if let Some(operation_name) = self.operation_name {
Err(Error::Query {
pos: Pos::default(),
path: None,
err: QueryError::UnknownOperationNamed {
name: operation_name,
},
})
} else {
Err(Error::Query {
pos: Pos::default(),
path: None,
err: QueryError::MissingOperation,
})
}
.log_error(&extensions)
}
.log_error(&extensions),
};
let env = QueryEnv::new(

View File

@ -1,4 +1,4 @@
use crate::parser::types::{Type as ParsedType, BaseType as ParsedBaseType};
use crate::parser::types::{BaseType as ParsedBaseType, Type as ParsedType};
use crate::validators::InputValueValidator;
use crate::{model, Any, Type as _, Value};
use indexmap::map::IndexMap;
@ -162,7 +162,11 @@ impl CacheControl {
#[must_use]
pub fn value(&self) -> Option<String> {
if self.max_age > 0 {
Some(format!("max-age={}{}", self.max_age, if self.public { "" } else { ", private" }))
Some(format!(
"max-age={}{}",
self.max_age,
if self.public { "" } else { ", private" }
))
} else {
None
}

View File

@ -1,10 +1,10 @@
use crate::parser::types::Field;
use crate::registry::{MetaType, Registry};
use crate::{
ContextSelectionSet, InputValueResult, OutputValueType, Positioned, Result, ScalarType, Type,
Value,
};
use async_graphql_derive::Scalar;
use crate::parser::types::Field;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;

View File

@ -1,9 +1,9 @@
use crate::parser::types::Field;
use crate::{
registry, ContextSelectionSet, InputValueError, InputValueResult, OutputValueType, Positioned,
Result, ScalarType, Type, Value,
};
use async_graphql_derive::Scalar;
use crate::parser::types::Field;
use std::borrow::Cow;
/// The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.

View File

@ -2,6 +2,7 @@ use crate::context::Data;
use crate::extensions::{BoxExtension, ErrorLogger, Extension, Extensions};
use crate::model::__DirectiveLocation;
use crate::parser::parse_query;
use crate::parser::types::{Document, OperationType};
use crate::query::QueryBuilder;
use crate::registry::{MetaDirective, MetaInputValue, Registry};
use crate::subscription::{create_connection, create_subscription_stream, ConnectionTransport};
@ -11,7 +12,6 @@ use crate::{
CacheControl, Error, ObjectType, Pos, QueryEnv, QueryError, QueryResponse, Result,
SubscriptionType, Type, Variables, ID,
};
use crate::parser::types::{Document, OperationType};
use bytes::Bytes;
use futures::channel::mpsc;
use futures::Stream;
@ -379,15 +379,17 @@ where
let document = match document.into_executable(operation_name) {
Some(document) => document,
None => return if let Some(name) = operation_name {
Err(QueryError::UnknownOperationNamed {
name: name.to_string(),
None => {
return if let Some(name) = operation_name {
Err(QueryError::UnknownOperationNamed {
name: name.to_string(),
}
.into_error(Pos::default()))
} else {
Err(QueryError::MissingOperation.into_error(Pos::default()))
}
.into_error(Pos::default()))
} else {
Err(QueryError::MissingOperation.into_error(Pos::default()))
.log_error(&extensions)
}
.log_error(&extensions),
};
if document.operation.node.ty != OperationType::Subscription {

View File

@ -42,19 +42,17 @@ where
continue;
}
match &selection.node {
Selection::Field(field) => {
streams.push(
schema
.subscription
.create_field_stream(
idx,
&ctx.with_field(field),
schema.env.clone(),
environment.clone(),
)
.await?,
)
}
Selection::Field(field) => streams.push(
schema
.subscription
.create_field_stream(
idx,
&ctx.with_field(field),
schema.env.clone(),
environment.clone(),
)
.await?,
),
Selection::FragmentSpread(fragment_spread) => {
if let Some(fragment) = ctx
.query_env
@ -72,8 +70,11 @@ where
}
}
Selection::InlineFragment(inline_fragment) => {
if let Some(TypeCondition { on: name }) =
inline_fragment.node.type_condition.as_ref().map(|v| &v.node)
if let Some(TypeCondition { on: name }) = inline_fragment
.node
.type_condition
.as_ref()
.map(|v| &v.node)
{
if name.node == Subscription::type_name() {
create_subscription_stream(

View File

@ -1,11 +1,11 @@
use crate::connection::edge::Edge;
use crate::connection::page_info::PageInfo;
use crate::parser::types::Field;
use crate::types::connection::{CursorType, EmptyFields};
use crate::{
do_resolve, registry, Context, ContextSelectionSet, FieldResult, ObjectType, OutputValueType,
Positioned, QueryError, Result, Type,
};
use crate::parser::types::Field;
use futures::{Stream, StreamExt, TryStreamExt};
use indexmap::map::IndexMap;
use std::borrow::Cow;

View File

@ -1,10 +1,10 @@
use crate::connection::EmptyFields;
use crate::parser::types::Field;
use crate::types::connection::CursorType;
use crate::{
do_resolve, registry, Context, ContextSelectionSet, ObjectType, OutputValueType, Positioned,
QueryError, Result, Type,
};
use crate::parser::types::Field;
use indexmap::map::IndexMap;
use std::borrow::Cow;

View File

@ -1,8 +1,8 @@
use crate::parser::types::Field;
use crate::{
registry, Context, ContextSelectionSet, Error, ObjectType, OutputValueType, Positioned,
QueryError, Result, Type,
};
use crate::parser::types::Field;
use std::borrow::Cow;
/// Empty mutation

View File

@ -1,8 +1,8 @@
use crate::parser::types::Field;
use crate::{
registry, ContextSelectionSet, InputValueResult, InputValueType, OutputValueType, Positioned,
Result, Type, Value,
};
use crate::parser::types::Field;
use std::borrow::Cow;
impl<T: Type> Type for Vec<T> {

View File

@ -1,9 +1,9 @@
use crate::parser::types::Field;
use crate::registry::{MetaType, Registry};
use crate::{
do_resolve, CacheControl, Context, ContextSelectionSet, Error, ObjectType, OutputValueType,
Positioned, QueryEnv, QueryError, Result, SchemaEnv, SubscriptionType, Type,
};
use crate::parser::types::Field;
use futures::Stream;
use indexmap::IndexMap;
use std::borrow::Cow;

View File

@ -1,8 +1,8 @@
use crate::parser::types::Field;
use crate::{
registry, ContextSelectionSet, InputValueResult, InputValueType, OutputValueType, Positioned,
Result, Type, Value,
};
use crate::parser::types::Field;
use std::borrow::Cow;
impl<T: Type> Type for Option<T> {

View File

@ -1,11 +1,11 @@
use crate::model::{__Schema, __Type};
use crate::parser::types::Field;
use crate::scalars::Any;
use crate::{
do_resolve, registry, Context, ContextSelectionSet, Error, ObjectType, OutputValueType,
Positioned, QueryError, Result, Type,
};
use async_graphql_derive::SimpleObject;
use crate::parser::types::Field;
use indexmap::map::IndexMap;
use std::borrow::Cow;

View File

@ -1,5 +1,5 @@
use crate::{registry, InputValueError, InputValueResult, InputValueType, Type, Value};
use crate::parser::types::UploadValue;
use crate::{registry, InputValueError, InputValueResult, InputValueType, Type, Value};
use std::borrow::Cow;
use std::io::Read;

View File

@ -44,9 +44,9 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
{
if let Some(validator) = &arg.validator {
let value = match &value.node {
Value::Variable(var_name) => {
ctx.variables.and_then(|variables| variables.0.get(var_name))
}
Value::Variable(var_name) => ctx
.variables
.and_then(|variables| variables.0.get(var_name)),
_ => Some(&value.node),
};

View File

@ -1,6 +1,7 @@
use crate::model::__DirectiveLocation;
use crate::parser::types::{
Directive, Field, FragmentDefinition, FragmentSpread, InlineFragment, OperationDefinition, OperationType
Directive, Field, FragmentDefinition, FragmentSpread, InlineFragment, OperationDefinition,
OperationType,
};
use crate::validation::visitor::{Visitor, VisitorContext};
use crate::Positioned;
@ -16,11 +17,12 @@ impl<'a> Visitor<'a> for KnownDirectives {
_ctx: &mut VisitorContext<'a>,
operation_definition: &'a Positioned<OperationDefinition>,
) {
self.location_stack.push(match &operation_definition.node.ty {
OperationType::Query => __DirectiveLocation::QUERY,
OperationType::Mutation => __DirectiveLocation::MUTATION,
OperationType::Subscription => __DirectiveLocation::SUBSCRIPTION,
});
self.location_stack
.push(match &operation_definition.node.ty {
OperationType::Query => __DirectiveLocation::QUERY,
OperationType::Mutation => __DirectiveLocation::MUTATION,
OperationType::Subscription => __DirectiveLocation::SUBSCRIPTION,
});
}
fn exit_operation_definition(

View File

@ -14,7 +14,10 @@ impl<'a> Visitor<'a> for KnownFragmentNames {
if !ctx.is_known_fragment(&fragment_spread.node.fragment_name.node) {
ctx.report_error(
vec![fragment_spread.pos],
format!(r#"Unknown fragment: "{}""#, fragment_spread.node.fragment_name.node),
format!(
r#"Unknown fragment: "{}""#,
fragment_spread.node.fragment_name.node
),
);
}
}

View File

@ -33,8 +33,11 @@ impl<'a> Visitor<'a> for KnownTypeNames {
ctx: &mut VisitorContext<'a>,
inline_fragment: &'a Positioned<InlineFragment>,
) {
if let Some(TypeCondition { on: name }) =
inline_fragment.node.type_condition.as_ref().map(|c| &c.node)
if let Some(TypeCondition { on: name }) = inline_fragment
.node
.type_condition
.as_ref()
.map(|c| &c.node)
{
validate_type(ctx, &name.node, inline_fragment.pos);
}

View File

@ -78,7 +78,8 @@ impl<'a> Visitor<'a> for NoFragmentCycles<'a> {
fragment_definition: &'a Positioned<FragmentDefinition>,
) {
self.current_fragment = Some(&fragment_definition.node.name.node);
self.fragment_order.push(&fragment_definition.node.name.node);
self.fragment_order
.push(&fragment_definition.node.name.node);
}
fn exit_fragment_definition(
@ -98,7 +99,10 @@ impl<'a> Visitor<'a> for NoFragmentCycles<'a> {
self.spreads
.entry(current_fragment)
.or_insert_with(Vec::new)
.push((&fragment_spread.node.fragment_name.node, fragment_spread.pos));
.push((
&fragment_spread.node.fragment_name.node,
fragment_spread.pos,
));
}
}
}

View File

@ -77,7 +77,11 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> {
_ctx: &mut VisitorContext<'a>,
operation_definition: &'a Positioned<OperationDefinition>,
) {
let name = operation_definition.node.name.as_ref().map(|name| &*name.node);
let name = operation_definition
.node
.name
.as_ref()
.map(|name| &*name.node);
self.current_scope = Some(Scope::Operation(name));
self.defined_variables
.insert(name, (operation_definition.pos, HashSet::new()));

View File

@ -37,7 +37,16 @@ impl<'a> Visitor<'a> for NoUnusedFragments<'a> {
for def in &doc.definitions {
if let Definition::Operation(operation_definition) = def {
self.find_reachable_fragments(&Scope::Operation(operation_definition.node.name.as_ref().map(|name| &*name.node)), &mut reachable);
self.find_reachable_fragments(
&Scope::Operation(
operation_definition
.node
.name
.as_ref()
.map(|name| &*name.node),
),
&mut reachable,
);
}
}
@ -56,7 +65,13 @@ impl<'a> Visitor<'a> for NoUnusedFragments<'a> {
_ctx: &mut VisitorContext<'a>,
operation_definition: &'a Positioned<OperationDefinition>,
) {
self.current_scope = Some(Scope::Operation(operation_definition.node.name.as_ref().map(|name| &*name.node)));
self.current_scope = Some(Scope::Operation(
operation_definition
.node
.name
.as_ref()
.map(|name| &*name.node),
));
}
fn enter_fragment_definition(
@ -65,10 +80,8 @@ impl<'a> Visitor<'a> for NoUnusedFragments<'a> {
fragment_definition: &'a Positioned<FragmentDefinition>,
) {
self.current_scope = Some(Scope::Fragment(&fragment_definition.node.name.node));
self.defined_fragments.insert((
&fragment_definition.node.name.node,
fragment_definition.pos,
));
self.defined_fragments
.insert((&fragment_definition.node.name.node, fragment_definition.pos));
}
fn enter_fragment_spread(

View File

@ -77,7 +77,11 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> {
_ctx: &mut VisitorContext<'a>,
operation_definition: &'a Positioned<OperationDefinition>,
) {
let op_name = operation_definition.node.name.as_ref().map(|name| &*name.node);
let op_name = operation_definition
.node
.name
.as_ref()
.map(|name| &*name.node);
self.current_scope = Some(Scope::Operation(op_name));
self.defined_variables.insert(op_name, HashSet::new());
}
@ -97,10 +101,7 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> {
) {
if let Some(Scope::Operation(ref name)) = self.current_scope {
if let Some(vars) = self.defined_variables.get_mut(name) {
vars.insert((
&variable_definition.node.name.node,
variable_definition.pos,
));
vars.insert((&variable_definition.node.name.node, variable_definition.pos));
}
}
}

View File

@ -42,7 +42,9 @@ impl<'a, 'ctx> FindConflicts<'a, 'ctx> {
self.find(&inline_fragment.node.selection_set);
}
Selection::FragmentSpread(fragment_spread) => {
if let Some(fragment) = self.ctx.fragment(&fragment_spread.node.fragment_name.node) {
if let Some(fragment) =
self.ctx.fragment(&fragment_spread.node.fragment_name.node)
{
self.find(&fragment.node.selection_set);
}
}

View File

@ -50,8 +50,11 @@ impl<'a> Visitor<'a> for PossibleFragmentSpreads<'a> {
inline_fragment: &'a Positioned<InlineFragment>,
) {
if let Some(parent_type) = ctx.parent_type() {
if let Some(TypeCondition { on: fragment_type }) =
&inline_fragment.node.type_condition.as_ref().map(|c| &c.node)
if let Some(TypeCondition { on: fragment_type }) = &inline_fragment
.node
.type_condition
.as_ref()
.map(|c| &c.node)
{
if let Some(on_type) = ctx.registry.types.get(&fragment_type.node) {
if !parent_type.type_overlap(&on_type) {

View File

@ -12,7 +12,10 @@ impl<'a> Visitor<'a> for UploadFile {
operation_definition: &'a Positioned<OperationDefinition>,
) {
for var in &operation_definition.node.variable_definitions {
if let Some(ty) = ctx.registry.concrete_type_by_parsed_type(&var.node.var_type.node) {
if let Some(ty) = ctx
.registry
.concrete_type_by_parsed_type(&var.node.var_type.node)
{
if ty.name() == "Upload" {
ctx.report_error(
vec![var.pos],

View File

@ -32,12 +32,13 @@ impl<'a> VariableInAllowedPosition<'a> {
if let Some(usages) = self.variable_usages.get(from) {
for (var_name, usage_pos, var_type) in usages {
if let Some(def) = var_defs.iter().find(|def| def.node.name.node == *var_name) {
let expected_type = if def.node.var_type.node.nullable && def.node.default_value.is_some() {
// A nullable type with a default value functions as a non-nullable
format!("{}!", def.node.var_type.node)
} else {
def.node.var_type.node.to_string()
};
let expected_type =
if def.node.var_type.node.nullable && def.node.default_value.is_some() {
// A nullable type with a default value functions as a non-nullable
format!("{}!", def.node.var_type.node)
} else {
def.node.var_type.node.to_string()
};
if !var_type.is_subtype(&MetaTypeName::create(&expected_type)) {
ctx.report_error(
@ -72,7 +73,13 @@ impl<'a> Visitor<'a> for VariableInAllowedPosition<'a> {
_ctx: &mut VisitorContext<'a>,
operation_definition: &'a Positioned<OperationDefinition>,
) {
self.current_scope = Some(Scope::Operation(operation_definition.node.name.as_ref().map(|name| &*name.node)));
self.current_scope = Some(Scope::Operation(
operation_definition
.node
.name
.as_ref()
.map(|name| &*name.node),
));
}
fn enter_fragment_definition(

View File

@ -2,9 +2,9 @@
#![allow(dead_code)]
#![allow(unreachable_code)]
use crate::parser::types::Document;
use crate::validation::visitor::{visit, Visitor, VisitorContext};
use crate::*;
use crate::parser::types::Document;
use once_cell::sync::Lazy;
#[InputObject(internal)]

View File

@ -538,8 +538,11 @@ fn visit_selection<'a, V: Visitor<'a>>(
visit_fragment_spread(v, ctx, fragment_spread)
}
Selection::InlineFragment(inline_fragment) => {
if let Some(TypeCondition { on: name }) =
&inline_fragment.node.type_condition.as_ref().map(|c| &c.node)
if let Some(TypeCondition { on: name }) = &inline_fragment
.node
.type_condition
.as_ref()
.map(|c| &c.node)
{
ctx.with_type(ctx.registry.types.get(&name.node), |ctx| {
visit_inline_fragment(v, ctx, inline_fragment)

View File

@ -1625,7 +1625,9 @@ pub async fn test_input_validator_variable() {
let validator_length = 6;
for case in &test_cases {
let mut variables = Variables::default();
variables.0.insert("id".to_string(), Value::String(case.to_string()));
variables
.0
.insert("id".to_string(), Value::String(case.to_string()));
let field_query = "query($id: String!) {fieldParameter(id: $id)}";
let object_query = "query($id: String!) {inputObject(input: {id: $id})}";