Improve GraphQL query parser performance. #76
This commit is contained in:
parent
1726c64e7a
commit
8299a54456
|
@ -1,5 +1,5 @@
|
|||
use crate::utils::{get_rustdoc, parse_guards, parse_validator};
|
||||
use async_graphql_parser::{parse_value, Value};
|
||||
use async_graphql_parser::{parse_value, ParsedValue};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{Attribute, AttributeArgs, Error, Lit, Meta, MetaList, NestedMeta, Result, Type};
|
||||
|
@ -126,7 +126,7 @@ impl Object {
|
|||
pub struct Argument {
|
||||
pub name: Option<String>,
|
||||
pub desc: Option<String>,
|
||||
pub default: Option<Value>,
|
||||
pub default: Option<ParsedValue>,
|
||||
pub validator: TokenStream,
|
||||
}
|
||||
|
||||
|
@ -163,12 +163,6 @@ impl Argument {
|
|||
} else if nv.path.is_ident("default") {
|
||||
if let syn::Lit::Str(lit) = &nv.lit {
|
||||
match parse_value(&lit.value()) {
|
||||
Ok(Value::Variable(_)) => {
|
||||
return Err(Error::new_spanned(
|
||||
&nv.lit,
|
||||
"The default cannot be a variable",
|
||||
))
|
||||
}
|
||||
Ok(value) => default = Some(value),
|
||||
Err(err) => {
|
||||
return Err(Error::new_spanned(
|
||||
|
@ -436,7 +430,7 @@ impl EnumItem {
|
|||
pub struct InputField {
|
||||
pub name: Option<String>,
|
||||
pub desc: Option<String>,
|
||||
pub default: Option<Value>,
|
||||
pub default: Option<ParsedValue>,
|
||||
pub validator: TokenStream,
|
||||
}
|
||||
|
||||
|
@ -480,12 +474,6 @@ impl InputField {
|
|||
} else if nv.path.is_ident("default") {
|
||||
if let syn::Lit::Str(lit) = &nv.lit {
|
||||
match parse_value(&lit.value()) {
|
||||
Ok(Value::Variable(_)) => {
|
||||
return Err(Error::new_spanned(
|
||||
&lit,
|
||||
"The default cannot be a variable",
|
||||
))
|
||||
}
|
||||
Ok(value) => default = Some(value),
|
||||
Err(err) => {
|
||||
return Err(Error::new_spanned(
|
||||
|
@ -578,7 +566,7 @@ pub struct InterfaceFieldArgument {
|
|||
pub name: String,
|
||||
pub desc: Option<String>,
|
||||
pub ty: Type,
|
||||
pub default: Option<Value>,
|
||||
pub default: Option<ParsedValue>,
|
||||
}
|
||||
|
||||
impl InterfaceFieldArgument {
|
||||
|
@ -624,12 +612,6 @@ impl InterfaceFieldArgument {
|
|||
} else if nv.path.is_ident("default") {
|
||||
if let syn::Lit::Str(lit) = &nv.lit {
|
||||
match parse_value(&lit.value()) {
|
||||
Ok(Value::Variable(_)) => {
|
||||
return Err(Error::new_spanned(
|
||||
&nv.lit,
|
||||
"The default cannot be a variable",
|
||||
))
|
||||
}
|
||||
Ok(value) => default = Some(value),
|
||||
Err(err) => {
|
||||
return Err(Error::new_spanned(
|
||||
|
|
|
@ -242,7 +242,7 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
};
|
||||
|
||||
resolvers.push(quote! {
|
||||
if ctx.name.as_str() == #name {
|
||||
if ctx.name.node == #name {
|
||||
#(#get_params)*
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return #crate_name::OutputValueType::resolve(&#resolve_obj, &ctx_obj, ctx.position()).await;
|
||||
|
@ -307,14 +307,14 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
|
||||
#(#resolvers)*
|
||||
Err(#crate_name::QueryError::FieldNotFound {
|
||||
field_name: ctx.name.clone_inner(),
|
||||
field_name: ctx.name.to_string(),
|
||||
object: #gql_typename.to_string(),
|
||||
}.into_error(ctx.position()))
|
||||
}
|
||||
|
||||
fn collect_inline_fields<'a>(
|
||||
&'a self,
|
||||
name: &#crate_name::Positioned<String>,
|
||||
name: &str,
|
||||
ctx: &#crate_name::ContextSelectionSet<'a>,
|
||||
futures: &mut Vec<#crate_name::BoxFieldFuture<'a>>,
|
||||
) -> #crate_name::Result<()> {
|
||||
|
|
|
@ -386,7 +386,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
});
|
||||
|
||||
resolvers.push(quote! {
|
||||
if ctx.name.as_str() == #field_name {
|
||||
if ctx.name.node == #field_name {
|
||||
use #crate_name::OutputValueType;
|
||||
#(#get_params)*
|
||||
#guard
|
||||
|
@ -460,7 +460,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
|
||||
#(#resolvers)*
|
||||
Err(#crate_name::QueryError::FieldNotFound {
|
||||
field_name: ctx.name.clone_inner(),
|
||||
field_name: ctx.name.to_string(),
|
||||
object: #gql_typename.to_string(),
|
||||
}.into_error(ctx.position()))
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ pub fn generate(object_args: &args::Object, input: &mut DeriveInput) -> Result<T
|
|||
}
|
||||
|
||||
resolvers.push(quote! {
|
||||
if ctx.name.as_str() == #field_name {
|
||||
if ctx.name.node == #field_name {
|
||||
#guard
|
||||
let res = self.#ident(ctx).await.map_err(|err| err.into_error_with_path(ctx.position(), ctx.path_node.as_ref().unwrap().to_json()))?;
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
|
@ -177,7 +177,7 @@ pub fn generate(object_args: &args::Object, input: &mut DeriveInput) -> Result<T
|
|||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
|
||||
#(#resolvers)*
|
||||
Err(#crate_name::QueryError::FieldNotFound {
|
||||
field_name: ctx.name.clone_inner(),
|
||||
field_name: ctx.name.to_string(),
|
||||
object: #gql_typename.to_string(),
|
||||
}.into_error(ctx.position()))
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
#(#schema_args)*
|
||||
args
|
||||
},
|
||||
ty: <#stream_ty as #crate_name::futures::stream::Stream>::Item::create_type_info(registry),
|
||||
ty: <<#stream_ty as #crate_name::futures::stream::Stream>::Item as #crate_name::Type>::create_type_info(registry),
|
||||
deprecation: #field_deprecation,
|
||||
cache_control: Default::default(),
|
||||
external: false,
|
||||
|
@ -236,13 +236,21 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
});
|
||||
|
||||
create_stream.push(quote! {
|
||||
if ctx.name.as_str() == #field_name {
|
||||
if ctx.name.node == #field_name {
|
||||
use #crate_name::futures::stream::{StreamExt, TryStreamExt};
|
||||
|
||||
#(#get_params)*
|
||||
#guard
|
||||
let field_name = std::sync::Arc::new(ctx.result_name().to_string());
|
||||
let field_selection_set = std::sync::Arc::new(ctx.selection_set.clone());
|
||||
|
||||
// I think the code here is safe because the lifetime of selection_set is always less than the environment.
|
||||
let field_selection_set = unsafe {
|
||||
(&ctx.selection_set
|
||||
as *const Positioned<#crate_name::parser::ast::SelectionSet>)
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
let schema = schema.clone();
|
||||
let pos = ctx.position();
|
||||
let environment = environment.clone();
|
||||
|
@ -261,7 +269,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
parent: None,
|
||||
segment: #crate_name::QueryPathSegment::Name(&field_name),
|
||||
}),
|
||||
&*field_selection_set,
|
||||
field_selection_set,
|
||||
&resolve_id,
|
||||
);
|
||||
#crate_name::OutputValueType::resolve(&msg, &ctx_selection_set, pos).await
|
||||
|
@ -325,6 +333,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
#[allow(bare_trait_objects)]
|
||||
async fn create_field_stream<Query, Mutation>(
|
||||
&self,
|
||||
idx: usize,
|
||||
ctx: &#crate_name::Context<'_>,
|
||||
schema: &#crate_name::Schema<Query, Mutation, Self>,
|
||||
environment: std::sync::Arc<#crate_name::Environment>,
|
||||
|
@ -338,7 +347,7 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
|
||||
#(#create_stream)*
|
||||
Err(#crate_name::QueryError::FieldNotFound {
|
||||
field_name: ctx.name.clone_inner(),
|
||||
field_name: ctx.name.to_string(),
|
||||
object: #gql_typename.to_string(),
|
||||
}.into_error(ctx.position()))
|
||||
}
|
||||
|
|
|
@ -132,14 +132,14 @@ pub fn generate(union_args: &args::Interface, input: &DeriveInput) -> Result<Tok
|
|||
impl #generics #crate_name::ObjectType for #ident #generics {
|
||||
async fn resolve_field(&self, ctx: &#crate_name::Context<'_>) -> #crate_name::Result<#crate_name::serde_json::Value> {
|
||||
Err(#crate_name::QueryError::FieldNotFound {
|
||||
field_name: ctx.name.clone_inner(),
|
||||
field_name: ctx.name.to_string(),
|
||||
object: #gql_typename.to_string(),
|
||||
}.into_error(ctx.position()))
|
||||
}
|
||||
|
||||
fn collect_inline_fields<'a>(
|
||||
&'a self,
|
||||
name: &#crate_name::Positioned<String>,
|
||||
name: &str,
|
||||
ctx: &#crate_name::ContextSelectionSet<'a>,
|
||||
futures: &mut Vec<#crate_name::BoxFieldFuture<'a>>,
|
||||
) -> #crate_name::Result<()> {
|
||||
|
|
|
@ -22,7 +22,7 @@ pub fn build_value_repr(crate_name: &TokenStream, value: &Value) -> TokenStream
|
|||
quote! { #crate_name::Value::Float(#n) }
|
||||
}
|
||||
Value::String(s) => {
|
||||
quote! { #crate_name::Value::String(#s.to_string()) }
|
||||
quote! { #crate_name::Value::String(#s.to_string().into()) }
|
||||
}
|
||||
Value::Boolean(n) => {
|
||||
quote! { #crate_name::Value::Boolean(#n) }
|
||||
|
@ -46,7 +46,7 @@ pub fn build_value_repr(crate_name: &TokenStream, value: &Value) -> TokenStream
|
|||
.map(|(n, v)| {
|
||||
let value = build_value_repr(crate_name, v);
|
||||
quote! {
|
||||
obj.insert(#n.to_string(), #value);
|
||||
obj.insert(#n.to_string().into(), #value);
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
|
|
@ -17,3 +17,4 @@ pest = "2.1.3"
|
|||
pest_derive = "2.1.0"
|
||||
thiserror = "1.0.11"
|
||||
serde_json = "1.0.48"
|
||||
arrayvec = "0.5.1"
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::pos::Positioned;
|
||||
use crate::value::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Type {
|
||||
Named(String),
|
||||
Named(&'static str),
|
||||
List(Box<Type>),
|
||||
NonNull(Box<Type>),
|
||||
}
|
||||
|
@ -19,46 +20,147 @@ impl fmt::Display for Type {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Directive {
|
||||
pub name: Positioned<String>,
|
||||
pub arguments: Vec<(Positioned<String>, Positioned<Value>)>,
|
||||
pub name: Positioned<&'static str>,
|
||||
pub arguments: Vec<(Positioned<&'static str>, Positioned<Value>)>,
|
||||
}
|
||||
|
||||
impl Directive {
|
||||
pub fn get_argument(&self, name: &str) -> Option<&Positioned<Value>> {
|
||||
self.arguments
|
||||
.iter()
|
||||
.find(|item| item.0.as_str() == name)
|
||||
.find(|item| item.0.node == name)
|
||||
.map(|item| &item.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Document {
|
||||
pub definitions: Vec<Positioned<Definition>>,
|
||||
pub type FragmentsMap = HashMap<&'static str, Positioned<FragmentDefinition>>;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
pub enum OperationType {
|
||||
Query,
|
||||
Mutation,
|
||||
Subscription,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct CurrentOperation {
|
||||
pub ty: OperationType,
|
||||
pub variable_definitions: Vec<Positioned<VariableDefinition>>,
|
||||
pub selection_set: Positioned<SelectionSet>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Document {
|
||||
pub(crate) source: String,
|
||||
pub(crate) definitions: Vec<Positioned<Definition>>,
|
||||
pub(crate) fragments: FragmentsMap,
|
||||
pub(crate) current_operation: Option<CurrentOperation>,
|
||||
}
|
||||
|
||||
impl Document {
|
||||
#[inline]
|
||||
pub fn definitions(&self) -> &[Positioned<Definition>] {
|
||||
&self.definitions
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fragments(&self) -> &FragmentsMap {
|
||||
&self.fragments
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn current_operation(&self) -> &CurrentOperation {
|
||||
self.current_operation
|
||||
.as_ref()
|
||||
.expect("Must first call retain_operation")
|
||||
}
|
||||
|
||||
pub fn retain_operation(&mut self, operation_name: Option<&str>) -> bool {
|
||||
let mut fragments = HashMap::new();
|
||||
|
||||
for definition in self.definitions.drain(..) {
|
||||
match definition.node {
|
||||
Definition::Operation(operation_definition) if self.current_operation.is_none() => {
|
||||
match operation_definition.node {
|
||||
OperationDefinition::SelectionSet(s) => {
|
||||
self.current_operation = Some(CurrentOperation {
|
||||
ty: OperationType::Query,
|
||||
variable_definitions: Vec::new(),
|
||||
selection_set: s,
|
||||
});
|
||||
}
|
||||
OperationDefinition::Query(query)
|
||||
if query.name.is_none()
|
||||
|| operation_name.is_none()
|
||||
|| query.name.as_ref().map(|name| name.node)
|
||||
== operation_name.as_deref() =>
|
||||
{
|
||||
self.current_operation = Some(CurrentOperation {
|
||||
ty: OperationType::Query,
|
||||
variable_definitions: query.node.variable_definitions,
|
||||
selection_set: query.node.selection_set,
|
||||
});
|
||||
}
|
||||
OperationDefinition::Mutation(mutation)
|
||||
if mutation.name.is_none()
|
||||
|| operation_name.is_none()
|
||||
|| mutation.name.as_ref().map(|name| name.node)
|
||||
== operation_name.as_deref() =>
|
||||
{
|
||||
self.current_operation = Some(CurrentOperation {
|
||||
ty: OperationType::Mutation,
|
||||
variable_definitions: mutation.node.variable_definitions,
|
||||
selection_set: mutation.node.selection_set,
|
||||
});
|
||||
}
|
||||
OperationDefinition::Subscription(subscription)
|
||||
if subscription.name.is_none()
|
||||
|| operation_name.is_none()
|
||||
|| subscription.name.as_ref().map(|name| name.node)
|
||||
== operation_name.as_deref() =>
|
||||
{
|
||||
self.current_operation = Some(CurrentOperation {
|
||||
ty: OperationType::Subscription,
|
||||
variable_definitions: subscription.node.variable_definitions,
|
||||
selection_set: subscription.node.selection_set,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Definition::Operation(_) => {}
|
||||
Definition::Fragment(fragment) => {
|
||||
fragments.insert(fragment.name.node, fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.fragments = fragments;
|
||||
self.current_operation.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Definition {
|
||||
Operation(Positioned<OperationDefinition>),
|
||||
Fragment(Positioned<FragmentDefinition>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub enum TypeCondition {
|
||||
On(Positioned<String>),
|
||||
On(Positioned<&'static str>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct FragmentDefinition {
|
||||
pub name: Positioned<String>,
|
||||
pub name: Positioned<&'static str>,
|
||||
pub type_condition: Positioned<TypeCondition>,
|
||||
pub directives: Vec<Positioned<Directive>>,
|
||||
pub selection_set: Positioned<SelectionSet>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub enum OperationDefinition {
|
||||
SelectionSet(Positioned<SelectionSet>),
|
||||
Query(Positioned<Query>),
|
||||
|
@ -66,54 +168,54 @@ pub enum OperationDefinition {
|
|||
Subscription(Positioned<Subscription>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Query {
|
||||
pub name: Option<Positioned<String>>,
|
||||
pub name: Option<Positioned<&'static str>>,
|
||||
pub variable_definitions: Vec<Positioned<VariableDefinition>>,
|
||||
pub directives: Vec<Positioned<Directive>>,
|
||||
pub selection_set: Positioned<SelectionSet>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Mutation {
|
||||
pub name: Option<Positioned<String>>,
|
||||
pub name: Option<Positioned<&'static str>>,
|
||||
pub variable_definitions: Vec<Positioned<VariableDefinition>>,
|
||||
pub directives: Vec<Positioned<Directive>>,
|
||||
pub selection_set: Positioned<SelectionSet>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Subscription {
|
||||
pub name: Option<Positioned<String>>,
|
||||
pub name: Option<Positioned<&'static str>>,
|
||||
pub variable_definitions: Vec<Positioned<VariableDefinition>>,
|
||||
pub directives: Vec<Positioned<Directive>>,
|
||||
pub selection_set: Positioned<SelectionSet>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct SelectionSet {
|
||||
pub items: Vec<Positioned<Selection>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct VariableDefinition {
|
||||
pub name: Positioned<String>,
|
||||
pub name: Positioned<&'static str>,
|
||||
pub var_type: Positioned<Type>,
|
||||
pub default_value: Option<Positioned<Value>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub enum Selection {
|
||||
Field(Positioned<Field>),
|
||||
FragmentSpread(Positioned<FragmentSpread>),
|
||||
InlineFragment(Positioned<InlineFragment>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct Field {
|
||||
pub alias: Option<Positioned<String>>,
|
||||
pub name: Positioned<String>,
|
||||
pub arguments: Vec<(Positioned<String>, Positioned<Value>)>,
|
||||
pub alias: Option<Positioned<&'static str>>,
|
||||
pub name: Positioned<&'static str>,
|
||||
pub arguments: Vec<(Positioned<&'static str>, Positioned<Value>)>,
|
||||
pub directives: Vec<Positioned<Directive>>,
|
||||
pub selection_set: Positioned<SelectionSet>,
|
||||
}
|
||||
|
@ -122,18 +224,18 @@ impl Field {
|
|||
pub fn get_argument(&self, name: &str) -> Option<&Positioned<Value>> {
|
||||
self.arguments
|
||||
.iter()
|
||||
.find(|item| item.0.as_str() == name)
|
||||
.find(|item| item.0.node == name)
|
||||
.map(|item| &item.1)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct FragmentSpread {
|
||||
pub fragment_name: Positioned<String>,
|
||||
pub fragment_name: Positioned<&'static str>,
|
||||
pub directives: Vec<Positioned<Directive>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Debug)]
|
||||
pub struct InlineFragment {
|
||||
pub type_condition: Option<Positioned<TypeCondition>>,
|
||||
pub directives: Vec<Positioned<Directive>>,
|
||||
|
|
|
@ -9,5 +9,5 @@ mod query_parser;
|
|||
mod value;
|
||||
|
||||
pub use pos::{Pos, Positioned};
|
||||
pub use query_parser::{parse_query, parse_value, Error, Result};
|
||||
pub use query_parser::{parse_query, parse_value, Error, ParsedValue, Result};
|
||||
pub use value::{UploadValue, Value};
|
||||
|
|
|
@ -2,12 +2,15 @@ use crate::ast::*;
|
|||
use crate::pos::Positioned;
|
||||
use crate::value::Value;
|
||||
use crate::Pos;
|
||||
use arrayvec::ArrayVec;
|
||||
use pest::error::LineColLocation;
|
||||
use pest::iterators::Pair;
|
||||
use pest::Parser;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::iter::Peekable;
|
||||
use std::ops::Deref;
|
||||
use std::str::Chars;
|
||||
|
||||
#[derive(Parser)]
|
||||
|
@ -95,12 +98,11 @@ impl<'a> PositionCalculator<'a> {
|
|||
}
|
||||
|
||||
/// Parse a GraphQL query.
|
||||
pub fn parse_query<T: AsRef<str>>(input: T) -> Result<Document> {
|
||||
let document_pair: Pair<Rule> = QueryParser::parse(Rule::document, input.as_ref())?
|
||||
.next()
|
||||
.unwrap();
|
||||
pub fn parse_query<T: Into<String>>(input: T) -> Result<Document> {
|
||||
let source = input.into();
|
||||
let document_pair: Pair<Rule> = QueryParser::parse(Rule::document, &source)?.next().unwrap();
|
||||
let mut definitions = Vec::new();
|
||||
let mut pc = PositionCalculator::new(input.as_ref());
|
||||
let mut pc = PositionCalculator::new(&source);
|
||||
|
||||
for pair in document_pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
|
@ -117,16 +119,36 @@ pub fn parse_query<T: AsRef<str>>(input: T) -> Result<Document> {
|
|||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Ok(Document { definitions })
|
||||
|
||||
Ok(Document {
|
||||
source,
|
||||
definitions,
|
||||
fragments: Default::default(),
|
||||
current_operation: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub struct ParsedValue {
|
||||
#[allow(dead_code)]
|
||||
source: String,
|
||||
value: Value,
|
||||
}
|
||||
|
||||
impl Deref for ParsedValue {
|
||||
type Target = Value;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a graphql value
|
||||
pub fn parse_value<T: AsRef<str>>(input: T) -> Result<Value> {
|
||||
let value_pair: Pair<Rule> = QueryParser::parse(Rule::value, input.as_ref())?
|
||||
.next()
|
||||
.unwrap();
|
||||
let mut pc = PositionCalculator::new(input.as_ref());
|
||||
parse_value2(value_pair, &mut pc)
|
||||
pub fn parse_value<T: Into<String>>(input: T) -> Result<ParsedValue> {
|
||||
let source = input.into();
|
||||
let value_pair: Pair<Rule> = QueryParser::parse(Rule::value, &source)?.next().unwrap();
|
||||
let mut pc = PositionCalculator::new(&source);
|
||||
let value = parse_value2(value_pair, &mut pc)?;
|
||||
Ok(ParsedValue { source, value })
|
||||
}
|
||||
|
||||
fn parse_named_operation_definition(
|
||||
|
@ -157,7 +179,10 @@ fn parse_named_operation_definition(
|
|||
};
|
||||
}
|
||||
Rule::name => {
|
||||
name = Some(Positioned::new(pair.as_str().to_string(), pc.step(&pair)));
|
||||
name = Some(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
));
|
||||
}
|
||||
Rule::variable_definitions => {
|
||||
variable_definitions = Some(parse_variable_definitions(pair, pc)?);
|
||||
|
@ -221,7 +246,7 @@ fn parse_type(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Type> {
|
|||
match pair.as_rule() {
|
||||
Rule::nonnull_type => Ok(Type::NonNull(Box::new(parse_type(pair, pc)?))),
|
||||
Rule::list_type => Ok(Type::List(Box::new(parse_type(pair, pc)?))),
|
||||
Rule::name => Ok(Type::Named(pair.as_str().to_string())),
|
||||
Rule::name => Ok(Type::Named(to_static_str(pair.as_str()))),
|
||||
Rule::type_ => parse_type(pair, pc),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -284,7 +309,10 @@ fn parse_directive(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Posi
|
|||
match pair.as_rule() {
|
||||
Rule::name => {
|
||||
let pos = pc.step(&pair);
|
||||
name = Some(Positioned::new(pair.as_str().to_string(), pos))
|
||||
name = Some(Positioned::new(
|
||||
to_static_str(to_static_str(pair.as_str())),
|
||||
pos,
|
||||
))
|
||||
}
|
||||
Rule::arguments => arguments = Some(parse_arguments(pair, pc)?),
|
||||
_ => unreachable!(),
|
||||
|
@ -313,10 +341,16 @@ fn parse_directives(
|
|||
Ok(directives)
|
||||
}
|
||||
|
||||
fn parse_variable(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Positioned<String>> {
|
||||
fn parse_variable(
|
||||
pair: Pair<Rule>,
|
||||
pc: &mut PositionCalculator,
|
||||
) -> Result<Positioned<&'static str>> {
|
||||
for pair in pair.into_inner() {
|
||||
if let Rule::name = pair.as_rule() {
|
||||
return Ok(Positioned::new(pair.as_str().to_string(), pc.step(&pair)));
|
||||
return Ok(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
));
|
||||
}
|
||||
}
|
||||
unreachable!()
|
||||
|
@ -333,14 +367,14 @@ fn parse_value2(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Value>
|
|||
Rule::string => Value::String({
|
||||
let start_pos = pair.as_span().start_pos().line_col();
|
||||
unquote_string(
|
||||
pair.as_str(),
|
||||
to_static_str(pair.as_str()),
|
||||
Pos {
|
||||
line: start_pos.0,
|
||||
column: start_pos.1,
|
||||
},
|
||||
)?
|
||||
}),
|
||||
Rule::name => Value::Enum(pair.as_str().to_string()),
|
||||
Rule::name => Value::Enum(to_static_str(pair.as_str())),
|
||||
Rule::boolean => Value::Boolean(match pair.as_str() {
|
||||
"true" => true,
|
||||
"false" => false,
|
||||
|
@ -351,12 +385,15 @@ fn parse_value2(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Value>
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_object_pair(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<(String, Value)> {
|
||||
fn parse_object_pair(
|
||||
pair: Pair<Rule>,
|
||||
pc: &mut PositionCalculator,
|
||||
) -> Result<(Cow<'static, str>, Value)> {
|
||||
let mut name = None;
|
||||
let mut value = None;
|
||||
for pair in pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
Rule::name => name = Some(pair.as_str().to_string()),
|
||||
Rule::name => name = Some(Cow::Borrowed(to_static_str(pair.as_str()))),
|
||||
Rule::value => value = Some(parse_value2(pair, pc)?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -393,12 +430,17 @@ fn parse_array_value(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Va
|
|||
fn parse_pair(
|
||||
pair: Pair<Rule>,
|
||||
pc: &mut PositionCalculator,
|
||||
) -> Result<(Positioned<String>, Positioned<Value>)> {
|
||||
) -> Result<(Positioned<&'static str>, Positioned<Value>)> {
|
||||
let mut name = None;
|
||||
let mut value = None;
|
||||
for pair in pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
Rule::name => name = Some(Positioned::new(pair.as_str().to_string(), pc.step(&pair))),
|
||||
Rule::name => {
|
||||
name = Some(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
))
|
||||
}
|
||||
Rule::value => {
|
||||
value = {
|
||||
let pos = pc.step(&pair);
|
||||
|
@ -414,7 +456,7 @@ fn parse_pair(
|
|||
fn parse_arguments(
|
||||
pair: Pair<Rule>,
|
||||
pc: &mut PositionCalculator,
|
||||
) -> Result<Vec<(Positioned<String>, Positioned<Value>)>> {
|
||||
) -> Result<Vec<(Positioned<&'static str>, Positioned<Value>)>> {
|
||||
let mut arguments = Vec::new();
|
||||
for pair in pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
|
@ -425,10 +467,13 @@ fn parse_arguments(
|
|||
Ok(arguments)
|
||||
}
|
||||
|
||||
fn parse_alias(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Positioned<String>> {
|
||||
fn parse_alias(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Positioned<&'static str>> {
|
||||
for pair in pair.into_inner() {
|
||||
if let Rule::name = pair.as_rule() {
|
||||
return Ok(Positioned::new(pair.as_str().to_string(), pc.step(&pair)));
|
||||
return Ok(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
));
|
||||
}
|
||||
}
|
||||
unreachable!()
|
||||
|
@ -445,7 +490,12 @@ fn parse_field(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Position
|
|||
for pair in pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
Rule::alias => alias = Some(parse_alias(pair, pc)?),
|
||||
Rule::name => name = Some(Positioned::new(pair.as_str().to_string(), pc.step(&pair))),
|
||||
Rule::name => {
|
||||
name = Some(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
))
|
||||
}
|
||||
Rule::arguments => arguments = Some(parse_arguments(pair, pc)?),
|
||||
Rule::directives => directives = Some(parse_directives(pair, pc)?),
|
||||
Rule::selection_set => selection_set = Some(parse_selection_set(pair, pc)?),
|
||||
|
@ -474,7 +524,12 @@ fn parse_fragment_spread(
|
|||
let mut directives = None;
|
||||
for pair in pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
Rule::name => name = Some(Positioned::new(pair.as_str().to_string(), pc.step(&pair))),
|
||||
Rule::name => {
|
||||
name = Some(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
))
|
||||
}
|
||||
Rule::directives => directives = Some(parse_directives(pair, pc)?),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -496,7 +551,10 @@ fn parse_type_condition(
|
|||
if let Rule::name = pair.as_rule() {
|
||||
let pos = pc.step(&pair);
|
||||
return Ok(Positioned::new(
|
||||
TypeCondition::On(Positioned::new(pair.as_str().to_string(), pc.step(&pair))),
|
||||
TypeCondition::On(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
)),
|
||||
pos,
|
||||
));
|
||||
}
|
||||
|
@ -565,7 +623,12 @@ fn parse_fragment_definition(
|
|||
|
||||
for pair in pair.into_inner() {
|
||||
match pair.as_rule() {
|
||||
Rule::name => name = Some(Positioned::new(pair.as_str().to_string(), pc.step(&pair))),
|
||||
Rule::name => {
|
||||
name = Some(Positioned::new(
|
||||
to_static_str(pair.as_str()),
|
||||
pc.step(&pair),
|
||||
))
|
||||
}
|
||||
Rule::type_condition => type_condition = Some(parse_type_condition(pair, pc)?),
|
||||
Rule::directives => directives = Some(parse_directives(pair, pc)?),
|
||||
Rule::selection_set => selection_set = Some(parse_selection_set(pair, pc)?),
|
||||
|
@ -584,11 +647,23 @@ fn parse_fragment_definition(
|
|||
))
|
||||
}
|
||||
|
||||
fn unquote_string(s: &str, pos: Pos) -> Result<String> {
|
||||
let mut res = String::with_capacity(s.len());
|
||||
#[inline]
|
||||
fn to_static_str(s: &str) -> &'static str {
|
||||
unsafe { (s as *const str).as_ref().unwrap() }
|
||||
}
|
||||
|
||||
fn unquote_string(s: &'static str, pos: Pos) -> Result<Cow<'static, str>> {
|
||||
debug_assert!(s.starts_with('"') && s.ends_with('"'));
|
||||
let mut chars = s[1..s.len() - 1].chars();
|
||||
let mut temp_code_point = String::with_capacity(4);
|
||||
let s = &s[1..s.len() - 1];
|
||||
|
||||
if !s.contains('\\') {
|
||||
return Ok(Cow::Borrowed(to_static_str(s)));
|
||||
}
|
||||
|
||||
let mut chars = s.chars();
|
||||
let mut res = String::with_capacity(s.len());
|
||||
let mut temp_code_point = ArrayVec::<[u8; 4]>::new();
|
||||
|
||||
while let Some(c) = chars.next() {
|
||||
match c {
|
||||
'\\' => {
|
||||
|
@ -603,13 +678,28 @@ fn unquote_string(s: &str, pos: Pos) -> Result<String> {
|
|||
temp_code_point.clear();
|
||||
for _ in 0..4 {
|
||||
match chars.next() {
|
||||
Some(inner_c) => temp_code_point.push(inner_c),
|
||||
Some(inner_c) if inner_c.is_digit(16) => {
|
||||
temp_code_point.push(inner_c as u8)
|
||||
}
|
||||
Some(inner_c) => {
|
||||
return Err(Error {
|
||||
pos,
|
||||
message: format!(
|
||||
"{} is not a valid unicode code point",
|
||||
inner_c
|
||||
),
|
||||
});
|
||||
}
|
||||
None => {
|
||||
return Err(Error {
|
||||
pos,
|
||||
message: format!(
|
||||
"\\u must have 4 characters after it, only found '{}'",
|
||||
temp_code_point
|
||||
"{} must have 4 characters after it",
|
||||
unsafe {
|
||||
std::str::from_utf8_unchecked(
|
||||
temp_code_point.as_slice(),
|
||||
)
|
||||
}
|
||||
),
|
||||
});
|
||||
}
|
||||
|
@ -617,14 +707,23 @@ fn unquote_string(s: &str, pos: Pos) -> Result<String> {
|
|||
}
|
||||
|
||||
// convert our hex string into a u32, then convert that into a char
|
||||
match u32::from_str_radix(&temp_code_point, 16).map(std::char::from_u32) {
|
||||
match u32::from_str_radix(
|
||||
unsafe { std::str::from_utf8_unchecked(temp_code_point.as_slice()) },
|
||||
16,
|
||||
)
|
||||
.map(std::char::from_u32)
|
||||
{
|
||||
Ok(Some(unicode_char)) => res.push(unicode_char),
|
||||
_ => {
|
||||
return Err(Error {
|
||||
pos,
|
||||
message: format!(
|
||||
"{} is not a valid unicode code point",
|
||||
temp_code_point
|
||||
unsafe {
|
||||
std::str::from_utf8_unchecked(
|
||||
temp_code_point.as_slice(),
|
||||
)
|
||||
}
|
||||
),
|
||||
});
|
||||
}
|
||||
|
@ -642,7 +741,7 @@ fn unquote_string(s: &str, pos: Pos) -> Result<String> {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
Ok(Cow::Owned(res))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
|
@ -30,14 +31,14 @@ impl Clone for UploadValue {
|
|||
#[allow(missing_docs)]
|
||||
pub enum Value {
|
||||
Null,
|
||||
Variable(String),
|
||||
Variable(&'static str),
|
||||
Int(i64),
|
||||
Float(f64),
|
||||
String(String),
|
||||
String(Cow<'static, str>),
|
||||
Boolean(bool),
|
||||
Enum(String),
|
||||
Enum(&'static str),
|
||||
List(Vec<Value>),
|
||||
Object(BTreeMap<String, Value>),
|
||||
Object(BTreeMap<Cow<'static, str>, Value>),
|
||||
Upload(UploadValue),
|
||||
}
|
||||
|
||||
|
@ -160,7 +161,7 @@ impl From<Value> for serde_json::Value {
|
|||
.into(),
|
||||
Value::Object(obj) => serde_json::Value::Object(
|
||||
obj.into_iter()
|
||||
.map(|(name, value)| (name, value.into()))
|
||||
.map(|(name, value)| (name.to_string(), value.into()))
|
||||
.collect(),
|
||||
),
|
||||
Value::Upload(_) => serde_json::Value::Null,
|
||||
|
@ -175,11 +176,11 @@ impl From<serde_json::Value> for Value {
|
|||
serde_json::Value::Bool(n) => Value::Boolean(n),
|
||||
serde_json::Value::Number(n) if n.is_f64() => Value::Float(n.as_f64().unwrap()),
|
||||
serde_json::Value::Number(n) => Value::Int(n.as_i64().unwrap()),
|
||||
serde_json::Value::String(s) => Value::String(s),
|
||||
serde_json::Value::String(s) => Value::String(Cow::Owned(s)),
|
||||
serde_json::Value::Array(ls) => Value::List(ls.into_iter().map(Into::into).collect()),
|
||||
serde_json::Value::Object(obj) => Value::Object(
|
||||
obj.into_iter()
|
||||
.map(|(name, value)| (name, value.into()))
|
||||
.map(|(name, value)| (Cow::Owned(name), value.into()))
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
|
|
10
src/base.rs
10
src/base.rs
|
@ -1,8 +1,8 @@
|
|||
use crate::parser::Pos;
|
||||
use crate::registry::Registry;
|
||||
use crate::{
|
||||
registry, Context, ContextSelectionSet, FieldResult, InputValueResult, Positioned, QueryError,
|
||||
Result, Value, ID,
|
||||
registry, Context, ContextSelectionSet, FieldResult, InputValueResult, QueryError, Result,
|
||||
Value, ID,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
use std::future::Future;
|
||||
|
@ -81,19 +81,19 @@ pub trait ObjectType: OutputValueType {
|
|||
/// Collect the fields with the `name` inline object
|
||||
fn collect_inline_fields<'a>(
|
||||
&'a self,
|
||||
name: &Positioned<String>,
|
||||
name: &str,
|
||||
ctx: &ContextSelectionSet<'a>,
|
||||
futures: &mut Vec<BoxFieldFuture<'a>>,
|
||||
) -> Result<()>
|
||||
where
|
||||
Self: Send + Sync + Sized,
|
||||
{
|
||||
if name.as_str() == Self::type_name().as_ref()
|
||||
if name == Self::type_name().as_ref()
|
||||
|| ctx
|
||||
.registry
|
||||
.implements
|
||||
.get(Self::type_name().as_ref())
|
||||
.map(|ty| ty.contains(name.as_str()))
|
||||
.map(|ty| ty.contains(name))
|
||||
.unwrap_or_default()
|
||||
{
|
||||
crate::collect_fields(ctx, self, futures)
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use crate::extensions::BoxExtension;
|
||||
use crate::parser::ast::{Directive, Field, FragmentDefinition, SelectionSet, VariableDefinition};
|
||||
use crate::parser::ast::{Directive, Field, SelectionSet};
|
||||
use crate::registry::Registry;
|
||||
use crate::{InputValueType, QueryError, Result, Schema, Type};
|
||||
use crate::{Pos, Positioned, Value};
|
||||
use async_graphql_parser::ast::Document;
|
||||
use async_graphql_parser::UploadValue;
|
||||
use fnv::FnvHashMap;
|
||||
use std::any::{Any, TypeId};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::borrow::Cow;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fs::File;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
|
@ -23,7 +25,7 @@ impl Default for Variables {
|
|||
}
|
||||
|
||||
impl Deref for Variables {
|
||||
type Target = BTreeMap<String, Value>;
|
||||
type Target = BTreeMap<Cow<'static, str>, Value>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
if let Value::Object(obj) = &self.0 {
|
||||
|
@ -242,11 +244,10 @@ pub struct ContextBase<'a, T> {
|
|||
pub(crate) extensions: &'a [BoxExtension],
|
||||
pub(crate) item: T,
|
||||
pub(crate) variables: &'a Variables,
|
||||
pub(crate) variable_definitions: &'a [Positioned<VariableDefinition>],
|
||||
pub(crate) registry: &'a Registry,
|
||||
pub(crate) data: &'a Data,
|
||||
pub(crate) ctx_data: Option<&'a Data>,
|
||||
pub(crate) fragments: &'a HashMap<String, FragmentDefinition>,
|
||||
pub(crate) document: &'a Document,
|
||||
}
|
||||
|
||||
impl<'a, T> Deref for ContextBase<'a, T> {
|
||||
|
@ -260,8 +261,7 @@ impl<'a, T> Deref for ContextBase<'a, T> {
|
|||
#[doc(hidden)]
|
||||
pub struct Environment {
|
||||
pub variables: Variables,
|
||||
pub variable_definitions: Vec<Positioned<VariableDefinition>>,
|
||||
pub fragments: HashMap<String, FragmentDefinition>,
|
||||
pub document: Box<Document>,
|
||||
pub ctx_data: Arc<Data>,
|
||||
}
|
||||
|
||||
|
@ -281,11 +281,10 @@ impl Environment {
|
|||
extensions: &[],
|
||||
item,
|
||||
variables: &self.variables,
|
||||
variable_definitions: &self.variable_definitions,
|
||||
registry: &schema.0.registry,
|
||||
data: &schema.0.data,
|
||||
ctx_data: Some(&self.ctx_data),
|
||||
fragments: &self.fragments,
|
||||
document: &self.document,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -314,8 +313,8 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
field
|
||||
.alias
|
||||
.as_ref()
|
||||
.map(|alias| alias.as_str())
|
||||
.unwrap_or_else(|| field.name.as_str()),
|
||||
.map(|alias| alias.node)
|
||||
.unwrap_or_else(|| field.name.node),
|
||||
),
|
||||
}),
|
||||
extensions: self.extensions,
|
||||
|
@ -323,11 +322,10 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
resolve_id: self.get_child_resolve_id(),
|
||||
inc_resolve_id: self.inc_resolve_id,
|
||||
variables: self.variables,
|
||||
variable_definitions: self.variable_definitions,
|
||||
registry: self.registry,
|
||||
data: self.data,
|
||||
ctx_data: self.ctx_data,
|
||||
fragments: self.fragments,
|
||||
document: self.document,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,11 +341,10 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
resolve_id: self.resolve_id,
|
||||
inc_resolve_id: &self.inc_resolve_id,
|
||||
variables: self.variables,
|
||||
variable_definitions: self.variable_definitions,
|
||||
registry: self.registry,
|
||||
data: self.data,
|
||||
ctx_data: self.ctx_data,
|
||||
fragments: self.fragments,
|
||||
document: self.document,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,11 +364,13 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
|
||||
fn var_value(&self, name: &str, pos: Pos) -> Result<Value> {
|
||||
let def = self
|
||||
.document
|
||||
.current_operation()
|
||||
.variable_definitions
|
||||
.iter()
|
||||
.find(|def| def.name.as_str() == name);
|
||||
.find(|def| def.name.node == name);
|
||||
if let Some(def) = def {
|
||||
if let Some(var_value) = self.variables.get(def.name.as_str()) {
|
||||
if let Some(var_value) = self.variables.get(def.name.node) {
|
||||
return Ok(var_value.clone());
|
||||
} else if let Some(default) = &def.default_value {
|
||||
return Ok(default.clone_inner());
|
||||
|
@ -409,7 +408,7 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
#[doc(hidden)]
|
||||
pub fn is_skip(&self, directives: &[Positioned<Directive>]) -> Result<bool> {
|
||||
for directive in directives {
|
||||
if directive.name.as_str() == "skip" {
|
||||
if directive.name.node == "skip" {
|
||||
if let Some(value) = directive.get_argument("if") {
|
||||
match InputValueType::parse(
|
||||
self.resolve_input_value(value.clone_inner(), value.position())?,
|
||||
|
@ -428,7 +427,7 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
}
|
||||
.into_error(directive.position()));
|
||||
}
|
||||
} else if directive.name.as_str() == "include" {
|
||||
} else if directive.name.node == "include" {
|
||||
if let Some(value) = directive.get_argument("if") {
|
||||
match InputValueType::parse(
|
||||
self.resolve_input_value(value.clone_inner(), value.position())?,
|
||||
|
@ -449,7 +448,7 @@ impl<'a, T> ContextBase<'a, T> {
|
|||
}
|
||||
} else {
|
||||
return Err(QueryError::UnknownDirective {
|
||||
name: directive.name.clone_inner(),
|
||||
name: directive.name.to_string(),
|
||||
}
|
||||
.into_error(directive.position()));
|
||||
}
|
||||
|
@ -472,11 +471,10 @@ impl<'a> ContextBase<'a, &'a Positioned<SelectionSet>> {
|
|||
resolve_id: self.get_child_resolve_id(),
|
||||
inc_resolve_id: self.inc_resolve_id,
|
||||
variables: self.variables,
|
||||
variable_definitions: self.variable_definitions,
|
||||
registry: self.registry,
|
||||
data: self.data,
|
||||
ctx_data: self.ctx_data,
|
||||
fragments: self.fragments,
|
||||
document: self.document,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -515,7 +513,7 @@ impl<'a> ContextBase<'a, &'a Positioned<Field>> {
|
|||
self.item
|
||||
.alias
|
||||
.as_ref()
|
||||
.map(|alias| alias.as_str())
|
||||
.unwrap_or_else(|| self.item.name.as_str())
|
||||
.map(|alias| alias.node)
|
||||
.unwrap_or_else(|| self.item.name.node)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,8 @@ pub mod extensions;
|
|||
pub mod guard;
|
||||
pub mod validators;
|
||||
|
||||
use async_graphql_parser as parser;
|
||||
#[doc(hidden)]
|
||||
pub use async_graphql_parser as parser;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use anyhow;
|
||||
|
|
|
@ -39,7 +39,7 @@ fn do_resolve<'a, T: ObjectType + Send + Sync>(
|
|||
continue;
|
||||
}
|
||||
|
||||
if field.name.as_str() == "__typename" {
|
||||
if field.name.node == "__typename" {
|
||||
values.insert(
|
||||
"__typename".to_string(),
|
||||
root.introspection_type_name().to_string().into(),
|
||||
|
@ -59,7 +59,7 @@ fn do_resolve<'a, T: ObjectType + Send + Sync>(
|
|||
.registry
|
||||
.types
|
||||
.get(T::type_name().as_ref())
|
||||
.and_then(|ty| ty.field_by_name(field.name.as_str()))
|
||||
.and_then(|ty| ty.field_by_name(field.name.node))
|
||||
.map(|field| &field.ty)
|
||||
{
|
||||
Some(ty) => &ty,
|
||||
|
@ -68,7 +68,7 @@ fn do_resolve<'a, T: ObjectType + Send + Sync>(
|
|||
pos: field.position(),
|
||||
path: None,
|
||||
err: QueryError::FieldNotFound {
|
||||
field_name: field.name.clone_inner(),
|
||||
field_name: field.name.to_string(),
|
||||
object: T::type_name().to_string(),
|
||||
},
|
||||
});
|
||||
|
@ -97,8 +97,10 @@ fn do_resolve<'a, T: ObjectType + Send + Sync>(
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Some(fragment) =
|
||||
ctx.fragments.get(fragment_spread.fragment_name.as_str())
|
||||
if let Some(fragment) = ctx
|
||||
.document
|
||||
.fragments()
|
||||
.get(fragment_spread.fragment_name.node)
|
||||
{
|
||||
do_resolve(
|
||||
&ctx.with_selection_set(&fragment.selection_set),
|
||||
|
@ -111,7 +113,7 @@ fn do_resolve<'a, T: ObjectType + Send + Sync>(
|
|||
pos: fragment_spread.position(),
|
||||
path: None,
|
||||
err: QueryError::UnknownFragment {
|
||||
name: fragment_spread.fragment_name.clone_inner(),
|
||||
name: fragment_spread.fragment_name.to_string(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
106
src/query.rs
106
src/query.rs
|
@ -1,19 +1,15 @@
|
|||
use crate::context::{Data, ResolveId};
|
||||
use crate::error::ParseRequestError;
|
||||
use crate::mutation_resolver::do_mutation_resolve;
|
||||
use crate::parser::ast::{
|
||||
Definition, Document, OperationDefinition, SelectionSet, VariableDefinition,
|
||||
};
|
||||
use crate::parser::parse_query;
|
||||
use crate::registry::CacheControl;
|
||||
use crate::validation::{check_rules, CheckResult};
|
||||
use crate::{
|
||||
do_resolve, ContextBase, Error, ObjectType, Pos, Positioned, QueryError, Result, Schema,
|
||||
Variables,
|
||||
do_resolve, ContextBase, Error, ObjectType, Pos, QueryError, Result, Schema, Variables,
|
||||
};
|
||||
use async_graphql_parser::ast::OperationType;
|
||||
use itertools::Itertools;
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
|
@ -138,7 +134,7 @@ impl QueryBuilder {
|
|||
extensions
|
||||
.iter()
|
||||
.for_each(|e| e.parse_start(&self.query_source));
|
||||
let document = parse_query(&self.query_source).map_err(Into::<Error>::into)?;
|
||||
let mut document = parse_query(&self.query_source).map_err(Into::<Error>::into)?;
|
||||
extensions.iter().for_each(|e| e.parse_end());
|
||||
|
||||
// check rules
|
||||
|
@ -165,20 +161,22 @@ impl QueryBuilder {
|
|||
|
||||
// execute
|
||||
let inc_resolve_id = AtomicUsize::default();
|
||||
let mut fragments = HashMap::new();
|
||||
let (selection_set, variable_definitions, is_query) =
|
||||
current_operation(&document, self.operation_name.as_deref()).ok_or_else(|| {
|
||||
Error::Query {
|
||||
if !document.retain_operation(self.operation_name.as_deref()) {
|
||||
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,
|
||||
}
|
||||
})?;
|
||||
|
||||
for definition in &document.definitions {
|
||||
if let Definition::Fragment(fragment) = &definition.node {
|
||||
fragments.insert(fragment.name.clone_inner(), fragment.clone_inner());
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
let ctx = ContextBase {
|
||||
|
@ -186,21 +184,28 @@ impl QueryBuilder {
|
|||
resolve_id: ResolveId::root(),
|
||||
inc_resolve_id: &inc_resolve_id,
|
||||
extensions: &extensions,
|
||||
item: selection_set,
|
||||
item: &document.current_operation().selection_set,
|
||||
variables: &self.variables,
|
||||
variable_definitions,
|
||||
registry: &schema.0.registry,
|
||||
data: &schema.0.data,
|
||||
ctx_data: self.ctx_data.as_ref(),
|
||||
fragments: &fragments,
|
||||
document: &document,
|
||||
};
|
||||
|
||||
extensions.iter().for_each(|e| e.execution_start());
|
||||
let data = if is_query {
|
||||
do_resolve(&ctx, &schema.0.query).await?
|
||||
} else {
|
||||
do_mutation_resolve(&ctx, &schema.0.mutation).await?
|
||||
|
||||
let data = match document.current_operation().ty {
|
||||
OperationType::Query => do_resolve(&ctx, &schema.0.query).await?,
|
||||
OperationType::Mutation => do_mutation_resolve(&ctx, &schema.0.mutation).await?,
|
||||
OperationType::Subscription => {
|
||||
return Err(Error::Query {
|
||||
pos: Pos::default(),
|
||||
path: None,
|
||||
err: QueryError::NotSupported,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
extensions.iter().for_each(|e| e.execution_end());
|
||||
|
||||
let res = QueryResponse {
|
||||
|
@ -226,54 +231,3 @@ impl QueryBuilder {
|
|||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn current_operation<'a>(
|
||||
document: &'a Document,
|
||||
operation_name: Option<&str>,
|
||||
) -> Option<(
|
||||
&'a Positioned<SelectionSet>,
|
||||
&'a [Positioned<VariableDefinition>],
|
||||
bool,
|
||||
)> {
|
||||
for definition in &document.definitions {
|
||||
match &definition.node {
|
||||
Definition::Operation(operation_definition) => match &operation_definition.node {
|
||||
OperationDefinition::SelectionSet(s) => {
|
||||
return Some((s, &[], true));
|
||||
}
|
||||
OperationDefinition::Query(query)
|
||||
if query.name.is_none()
|
||||
|| operation_name.is_none()
|
||||
|| query.name.as_ref().map(|name| name.as_str())
|
||||
== operation_name.as_deref() =>
|
||||
{
|
||||
return Some((&query.selection_set, &query.variable_definitions, true));
|
||||
}
|
||||
OperationDefinition::Mutation(mutation)
|
||||
if mutation.name.is_none()
|
||||
|| operation_name.is_none()
|
||||
|| mutation.name.as_ref().map(|name| name.as_str())
|
||||
== operation_name.as_deref() =>
|
||||
{
|
||||
return Some((
|
||||
&mutation.selection_set,
|
||||
&mutation.variable_definitions,
|
||||
false,
|
||||
));
|
||||
}
|
||||
OperationDefinition::Subscription(subscription)
|
||||
if subscription.name.is_none()
|
||||
|| operation_name.is_none()
|
||||
|| subscription.name.as_ref().map(|name| name.as_str())
|
||||
== operation_name.as_deref() =>
|
||||
{
|
||||
return None;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
Definition::Fragment(_) => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
@ -404,7 +404,7 @@ impl Registry {
|
|||
match query_type {
|
||||
ParsedType::NonNull(ty) => self.concrete_type_by_parsed_type(ty),
|
||||
ParsedType::List(ty) => self.concrete_type_by_parsed_type(ty),
|
||||
ParsedType::Named(name) => self.types.get(name.as_str()),
|
||||
ParsedType::Named(name) => self.types.get(*name),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ pub fn collect_fields<'a, T: ObjectType + Send + Sync>(
|
|||
continue;
|
||||
}
|
||||
|
||||
if field.name.as_str() == "__typename" {
|
||||
if field.name.node == "__typename" {
|
||||
// Get the typename
|
||||
let ctx_field = ctx.with_field(field);
|
||||
let field_name = ctx_field.result_name().to_string();
|
||||
|
@ -68,7 +68,7 @@ pub fn collect_fields<'a, T: ObjectType + Send + Sync>(
|
|||
.registry
|
||||
.types
|
||||
.get(T::type_name().as_ref())
|
||||
.and_then(|ty| ty.field_by_name(field.name.as_str()))
|
||||
.and_then(|ty| ty.field_by_name(field.name.node))
|
||||
.map(|field| &field.ty)
|
||||
{
|
||||
Some(ty) => &ty,
|
||||
|
@ -77,7 +77,7 @@ pub fn collect_fields<'a, T: ObjectType + Send + Sync>(
|
|||
pos: field.position(),
|
||||
path: None,
|
||||
err: QueryError::FieldNotFound {
|
||||
field_name: field.name.clone_inner(),
|
||||
field_name: field.name.to_string(),
|
||||
object: T::type_name().to_string(),
|
||||
},
|
||||
});
|
||||
|
@ -112,7 +112,11 @@ pub fn collect_fields<'a, T: ObjectType + Send + Sync>(
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Some(fragment) = ctx.fragments.get(fragment_spread.fragment_name.as_str()) {
|
||||
if let Some(fragment) = ctx
|
||||
.document
|
||||
.fragments()
|
||||
.get(fragment_spread.fragment_name.node)
|
||||
{
|
||||
collect_fields(
|
||||
&ctx.with_selection_set(&fragment.selection_set),
|
||||
root,
|
||||
|
@ -123,7 +127,7 @@ pub fn collect_fields<'a, T: ObjectType + Send + Sync>(
|
|||
pos: fragment_spread.position(),
|
||||
path: None,
|
||||
err: QueryError::UnknownFragment {
|
||||
name: fragment_spread.fragment_name.clone_inner(),
|
||||
name: fragment_spread.fragment_name.to_string(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ impl ScalarType for ID {
|
|||
fn parse(value: Value) -> InputValueResult<Self> {
|
||||
match value {
|
||||
Value::Int(n) => Ok(ID(n.to_string())),
|
||||
Value::String(s) => Ok(ID(s)),
|
||||
Value::String(s) => Ok(ID(s.into_owned())),
|
||||
_ => Err(InputValueError::ExpectedType(value)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ impl ScalarType for String {
|
|||
|
||||
fn parse(value: Value) -> InputValueResult<Self> {
|
||||
match value {
|
||||
Value::String(s) => Ok(s),
|
||||
Value::String(s) => Ok(s.into_owned()),
|
||||
_ => Err(InputValueError::ExpectedType(value)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::context::Data;
|
||||
use crate::extensions::{BoxExtension, Extension};
|
||||
use crate::model::__DirectiveLocation;
|
||||
use crate::parser::ast::{Definition, OperationDefinition};
|
||||
use crate::parser::parse_query;
|
||||
use crate::query::QueryBuilder;
|
||||
use crate::registry::{Directive, InputValue, Registry};
|
||||
|
@ -242,49 +241,32 @@ where
|
|||
variables: Variables,
|
||||
ctx_data: Option<Arc<Data>>,
|
||||
) -> Result<impl Stream<Item = Result<serde_json::Value>> + Send> {
|
||||
let document = parse_query(source).map_err(Into::<Error>::into)?;
|
||||
let mut document = parse_query(source).map_err(Into::<Error>::into)?;
|
||||
check_rules(&self.0.registry, &document, self.0.validation_mode)?;
|
||||
|
||||
let mut fragments = HashMap::new();
|
||||
let mut subscription = None;
|
||||
|
||||
for definition in document.definitions {
|
||||
match definition.node {
|
||||
Definition::Operation(operation) => {
|
||||
if let OperationDefinition::Subscription(s) = operation.node {
|
||||
if subscription.is_none()
|
||||
&& (s.name.as_ref().map(|v| v.as_str()) == operation_name
|
||||
|| operation_name.is_none())
|
||||
{
|
||||
subscription = Some(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
Definition::Fragment(fragment) => {
|
||||
fragments.insert(fragment.name.clone_inner(), fragment.into_inner());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let subscription = subscription
|
||||
.ok_or(if let Some(name) = operation_name {
|
||||
QueryError::UnknownOperationNamed {
|
||||
if !document.retain_operation(operation_name) {
|
||||
return if let Some(name) = operation_name {
|
||||
Err(QueryError::UnknownOperationNamed {
|
||||
name: name.to_string(),
|
||||
}
|
||||
.into_error(Pos::default())
|
||||
.into_error(Pos::default()))
|
||||
} else {
|
||||
QueryError::MissingOperation.into_error(Pos::default())
|
||||
})?
|
||||
.into_inner();
|
||||
Err(QueryError::MissingOperation.into_error(Pos::default()))
|
||||
};
|
||||
}
|
||||
|
||||
let resolve_id = AtomicUsize::default();
|
||||
let environment = Arc::new(Environment {
|
||||
variables,
|
||||
variable_definitions: subscription.variable_definitions,
|
||||
fragments,
|
||||
document: Box::new(document),
|
||||
ctx_data: ctx_data.unwrap_or_default(),
|
||||
});
|
||||
let ctx = environment.create_context(self, None, &subscription.selection_set, &resolve_id);
|
||||
let ctx = environment.create_context(
|
||||
self,
|
||||
None,
|
||||
&environment.document.current_operation().selection_set,
|
||||
&resolve_id,
|
||||
);
|
||||
let mut streams = Vec::new();
|
||||
create_subscription_stream(self, environment.clone(), &ctx, &mut streams).await?;
|
||||
Ok(futures::stream::select_all(streams))
|
||||
|
|
|
@ -17,6 +17,7 @@ pub trait SubscriptionType: Type {
|
|||
#[doc(hidden)]
|
||||
async fn create_field_stream<Query, Mutation>(
|
||||
&self,
|
||||
idx: usize,
|
||||
ctx: &Context<'_>,
|
||||
schema: &Schema<Query, Mutation, Self>,
|
||||
environment: Arc<Environment>,
|
||||
|
@ -41,7 +42,7 @@ where
|
|||
Subscription: SubscriptionType + Send + Sync + 'static + Sized,
|
||||
{
|
||||
Box::pin(async move {
|
||||
for selection in &ctx.items {
|
||||
for (idx, selection) in ctx.items.iter().enumerate() {
|
||||
match &selection.node {
|
||||
Selection::Field(field) => {
|
||||
if ctx.is_skip(&field.directives)? {
|
||||
|
@ -52,6 +53,7 @@ where
|
|||
.0
|
||||
.subscription
|
||||
.create_field_stream(
|
||||
idx,
|
||||
&ctx.with_field(field),
|
||||
schema,
|
||||
environment.clone(),
|
||||
|
@ -64,8 +66,10 @@ where
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Some(fragment) =
|
||||
ctx.fragments.get(fragment_spread.fragment_name.as_str())
|
||||
if let Some(fragment) = ctx
|
||||
.document
|
||||
.fragments()
|
||||
.get(fragment_spread.fragment_name.node)
|
||||
{
|
||||
create_subscription_stream(
|
||||
schema,
|
||||
|
@ -84,7 +88,7 @@ where
|
|||
if let Some(TypeCondition::On(name)) =
|
||||
inline_fragment.type_condition.as_ref().map(|v| &v.node)
|
||||
{
|
||||
if name.as_str() == Subscription::type_name() {
|
||||
if name.node == Subscription::type_name() {
|
||||
create_subscription_stream(
|
||||
schema,
|
||||
environment.clone(),
|
||||
|
|
|
@ -177,18 +177,18 @@ impl<T: OutputValueType + Send + Sync, E: ObjectType + Sync + Send> ObjectType
|
|||
for Connection<T, E>
|
||||
{
|
||||
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value> {
|
||||
if ctx.name.as_str() == "pageInfo" {
|
||||
if ctx.name.node == "pageInfo" {
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return OutputValueType::resolve(self.page_info().await, &ctx_obj, ctx.position())
|
||||
.await;
|
||||
} else if ctx.name.as_str() == "edges" {
|
||||
} else if ctx.name.node == "edges" {
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return OutputValueType::resolve(&self.edges().await, &ctx_obj, ctx.position()).await;
|
||||
} else if ctx.name.as_str() == "totalCount" {
|
||||
} else if ctx.name.node == "totalCount" {
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return OutputValueType::resolve(&self.total_count().await, &ctx_obj, ctx.position())
|
||||
.await;
|
||||
} else if ctx.name.as_str() == T::type_name().to_plural().to_camel_case() {
|
||||
} else if ctx.name.node == T::type_name().to_plural().to_camel_case() {
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
let items = self.nodes.iter().map(|(_, _, item)| item).collect_vec();
|
||||
return OutputValueType::resolve(&items, &ctx_obj, ctx.position()).await;
|
||||
|
@ -198,7 +198,7 @@ impl<T: OutputValueType + Send + Sync, E: ObjectType + Sync + Send> ObjectType
|
|||
pos: ctx.position(),
|
||||
path: None,
|
||||
err: QueryError::FieldNotFound {
|
||||
field_name: ctx.name.clone_inner(),
|
||||
field_name: ctx.name.to_string(),
|
||||
object: Connection::<T, E>::type_name().to_string(),
|
||||
},
|
||||
})
|
||||
|
|
|
@ -46,7 +46,7 @@ impl ScalarType for Cursor {
|
|||
|
||||
fn parse(value: Value) -> InputValueResult<Self> {
|
||||
match value {
|
||||
Value::String(s) => Ok(Cursor(s)),
|
||||
Value::String(s) => Ok(Cursor(s.into_owned())),
|
||||
_ => Err(InputValueError::ExpectedType(value)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,10 +103,10 @@ where
|
|||
E: ObjectType + Sync + Send + 'a,
|
||||
{
|
||||
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value> {
|
||||
if ctx.name.as_str() == "node" {
|
||||
if ctx.name.node == "node" {
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return OutputValueType::resolve(self.node().await, &ctx_obj, ctx.position()).await;
|
||||
} else if ctx.name.as_str() == "cursor" {
|
||||
} else if ctx.name.node == "cursor" {
|
||||
return Ok(self.cursor().await.into());
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ impl SubscriptionType for EmptySubscription {
|
|||
|
||||
async fn create_field_stream<Query, Mutation>(
|
||||
&self,
|
||||
_idx: usize,
|
||||
_ctx: &Context<'_>,
|
||||
_schema: &Schema<Query, Mutation, Self>,
|
||||
_environment: Arc<Environment>,
|
||||
|
|
|
@ -12,9 +12,9 @@ pub trait EnumType: Type + Sized + Eq + Send + Copy + Sized + 'static {
|
|||
fn items() -> &'static [EnumItem<Self>];
|
||||
|
||||
fn parse_enum(value: Value) -> InputValueResult<Self> {
|
||||
let value = match value {
|
||||
let value = match &value {
|
||||
Value::Enum(s) => s,
|
||||
Value::String(s) => s,
|
||||
Value::String(s) => s.as_ref(),
|
||||
_ => return Err(InputValueError::ExpectedType(value)),
|
||||
};
|
||||
|
||||
|
|
|
@ -80,13 +80,13 @@ impl<T: Type> Type for QueryRoot<T> {
|
|||
#[async_trait::async_trait]
|
||||
impl<T: ObjectType + Send + Sync> ObjectType for QueryRoot<T> {
|
||||
async fn resolve_field(&self, ctx: &Context<'_>) -> Result<serde_json::Value> {
|
||||
if ctx.name.as_str() == "__schema" {
|
||||
if ctx.name.node == "__schema" {
|
||||
if self.disable_introspection {
|
||||
return Err(Error::Query {
|
||||
pos: ctx.position(),
|
||||
path: Some(ctx.path_node.as_ref().unwrap().to_json()),
|
||||
err: QueryError::FieldNotFound {
|
||||
field_name: ctx.name.clone_inner(),
|
||||
field_name: ctx.name.to_string(),
|
||||
object: Self::type_name().to_string(),
|
||||
},
|
||||
});
|
||||
|
@ -101,7 +101,7 @@ impl<T: ObjectType + Send + Sync> ObjectType for QueryRoot<T> {
|
|||
ctx.position(),
|
||||
)
|
||||
.await;
|
||||
} else if ctx.name.as_str() == "__type" {
|
||||
} else if ctx.name.node == "__type" {
|
||||
let type_name: String = ctx.param_value("name", || Value::Null)?;
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return OutputValueType::resolve(
|
||||
|
@ -113,14 +113,14 @@ impl<T: ObjectType + Send + Sync> ObjectType for QueryRoot<T> {
|
|||
ctx.position(),
|
||||
)
|
||||
.await;
|
||||
} else if ctx.name.as_str() == "_entities" {
|
||||
} else if ctx.name.node == "_entities" {
|
||||
let representations: Vec<Any> = ctx.param_value("representations", || Value::Null)?;
|
||||
let mut res = Vec::new();
|
||||
for item in representations {
|
||||
res.push(self.inner.find_entity(ctx, &item.0).await?);
|
||||
}
|
||||
return Ok(res.into());
|
||||
} else if ctx.name.as_str() == "_service" {
|
||||
} else if ctx.name.node == "_service" {
|
||||
let ctx_obj = ctx.with_selection_set(&ctx.selection_set);
|
||||
return OutputValueType::resolve(
|
||||
&Service {
|
||||
|
|
|
@ -20,7 +20,7 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
|
|||
self.current_args = ctx
|
||||
.registry
|
||||
.directives
|
||||
.get(directive.name.as_str())
|
||||
.get(directive.name.node)
|
||||
.map(|d| &d.args);
|
||||
}
|
||||
|
||||
|
@ -35,12 +35,12 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
|
|||
fn enter_argument(
|
||||
&mut self,
|
||||
ctx: &mut VisitorContext<'a>,
|
||||
name: &'a Positioned<String>,
|
||||
name: &'a Positioned<&str>,
|
||||
value: &'a Positioned<Value>,
|
||||
) {
|
||||
if let Some(arg) = self
|
||||
.current_args
|
||||
.and_then(|args| args.get(name.as_str()).map(|input| input))
|
||||
.and_then(|args| args.get(name.node).map(|input| input))
|
||||
{
|
||||
if let Some(validator) = &arg.validator {
|
||||
if let Some(reason) = validator.is_valid(value) {
|
||||
|
|
|
@ -12,14 +12,14 @@ impl<'a> Visitor<'a> for FieldsOnCorrectType {
|
|||
if let Some(registry::Type::Union { .. }) | Some(registry::Type::Interface { .. }) =
|
||||
ctx.parent_type()
|
||||
{
|
||||
if field.name.as_str() == "__typename" {
|
||||
if field.name.node == "__typename" {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if parent_type
|
||||
.fields()
|
||||
.and_then(|fields| fields.get(field.name.as_str()))
|
||||
.and_then(|fields| fields.get(field.name.node))
|
||||
.is_none()
|
||||
{
|
||||
ctx.report_error(
|
||||
|
|
|
@ -41,7 +41,7 @@ impl<'a> Visitor<'a> for KnownArgumentNames<'a> {
|
|||
self.current_args = ctx
|
||||
.registry
|
||||
.directives
|
||||
.get(directive.name.as_str())
|
||||
.get(directive.name.node)
|
||||
.map(|d| (&d.args, ArgsType::Directive(&directive.name)));
|
||||
}
|
||||
|
||||
|
@ -56,11 +56,11 @@ impl<'a> Visitor<'a> for KnownArgumentNames<'a> {
|
|||
fn enter_argument(
|
||||
&mut self,
|
||||
ctx: &mut VisitorContext<'a>,
|
||||
name: &'a Positioned<String>,
|
||||
name: &'a Positioned<&str>,
|
||||
_value: &'a Positioned<Value>,
|
||||
) {
|
||||
if let Some((args, arg_type)) = &self.current_args {
|
||||
if !args.contains_key(name.as_str()) {
|
||||
if !args.contains_key(name.node) {
|
||||
match arg_type {
|
||||
ArgsType::Field {
|
||||
field_name,
|
||||
|
|
|
@ -55,7 +55,7 @@ impl<'a> Visitor<'a> for KnownDirectives {
|
|||
ctx: &mut VisitorContext<'a>,
|
||||
directive: &'a Positioned<Directive>,
|
||||
) {
|
||||
if let Some(schema_directive) = ctx.registry.directives.get(directive.name.as_str()) {
|
||||
if let Some(schema_directive) = ctx.registry.directives.get(directive.name.node) {
|
||||
if let Some(current_location) = self.location_stack.last() {
|
||||
if !schema_directive.locations.contains(current_location) {
|
||||
ctx.report_error(
|
||||
|
|
|
@ -13,7 +13,7 @@ impl<'a> Visitor<'a> for KnownTypeNames {
|
|||
fragment_definition: &'a Positioned<FragmentDefinition>,
|
||||
) {
|
||||
let TypeCondition::On(name) = &fragment_definition.type_condition.node;
|
||||
validate_type(ctx, name.as_str(), fragment_definition.position());
|
||||
validate_type(ctx, name.node, fragment_definition.position());
|
||||
}
|
||||
|
||||
fn enter_variable_definition(
|
||||
|
@ -36,7 +36,7 @@ impl<'a> Visitor<'a> for KnownTypeNames {
|
|||
if let Some(TypeCondition::On(name)) =
|
||||
inline_fragment.type_condition.as_ref().map(|c| &c.node)
|
||||
{
|
||||
validate_type(ctx, name.as_str(), inline_fragment.position());
|
||||
validate_type(ctx, name.node, inline_fragment.position());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ pub struct LoneAnonymousOperation {
|
|||
impl<'a> Visitor<'a> for LoneAnonymousOperation {
|
||||
fn enter_document(&mut self, _ctx: &mut VisitorContext<'a>, doc: &'a Document) {
|
||||
self.operation_count = Some(
|
||||
doc.definitions
|
||||
doc.definitions()
|
||||
.iter()
|
||||
.filter(|d| match &d.node {
|
||||
Definition::Operation(_) => true,
|
||||
|
|
|
@ -88,7 +88,7 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> {
|
|||
_ctx: &mut VisitorContext<'a>,
|
||||
fragment_definition: &'a Positioned<FragmentDefinition>,
|
||||
) {
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.as_str()));
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.node));
|
||||
}
|
||||
|
||||
fn enter_variable_definition(
|
||||
|
@ -98,7 +98,7 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> {
|
|||
) {
|
||||
if let Some(Scope::Operation(ref name)) = self.current_scope {
|
||||
if let Some(&mut (_, ref mut vars)) = self.defined_variables.get_mut(name) {
|
||||
vars.insert(variable_definition.name.as_str());
|
||||
vars.insert(variable_definition.name.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> {
|
|||
fn enter_argument(
|
||||
&mut self,
|
||||
_ctx: &mut VisitorContext<'a>,
|
||||
name: &'a Positioned<String>,
|
||||
name: &'a Positioned<&str>,
|
||||
value: &'a Positioned<Value>,
|
||||
) {
|
||||
if let Some(ref scope) = self.current_scope {
|
||||
|
@ -130,7 +130,7 @@ impl<'a> Visitor<'a> for NoUndefinedVariables<'a> {
|
|||
self.spreads
|
||||
.entry(scope.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(fragment_spread.fragment_name.as_str());
|
||||
.push(fragment_spread.fragment_name.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ impl<'a> Visitor<'a> for NoUnusedFragments<'a> {
|
|||
fn exit_document(&mut self, ctx: &mut VisitorContext<'a>, doc: &'a Document) {
|
||||
let mut reachable = HashSet::new();
|
||||
|
||||
for def in &doc.definitions {
|
||||
for def in doc.definitions() {
|
||||
if let Definition::Operation(operation_definition) = &def.node {
|
||||
let (name, _) = operation_name(operation_definition);
|
||||
self.find_reachable_fragments(&Scope::Operation(name), &mut reachable);
|
||||
|
@ -66,9 +66,9 @@ impl<'a> Visitor<'a> for NoUnusedFragments<'a> {
|
|||
_ctx: &mut VisitorContext<'a>,
|
||||
fragment_definition: &'a Positioned<FragmentDefinition>,
|
||||
) {
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.as_str()));
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.node));
|
||||
self.defined_fragments.insert((
|
||||
fragment_definition.name.as_str(),
|
||||
fragment_definition.name.node,
|
||||
fragment_definition.position(),
|
||||
));
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ impl<'a> Visitor<'a> for NoUnusedFragments<'a> {
|
|||
self.spreads
|
||||
.entry(scope.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(fragment_spread.fragment_name.as_str());
|
||||
.push(fragment_spread.fragment_name.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> {
|
|||
_ctx: &mut VisitorContext<'a>,
|
||||
fragment_definition: &'a Positioned<FragmentDefinition>,
|
||||
) {
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.as_str()));
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.node));
|
||||
}
|
||||
|
||||
fn enter_variable_definition(
|
||||
|
@ -98,7 +98,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.name.as_str(),
|
||||
variable_definition.name.node,
|
||||
variable_definition.position(),
|
||||
));
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> {
|
|||
fn enter_argument(
|
||||
&mut self,
|
||||
_ctx: &mut VisitorContext<'a>,
|
||||
_name: &'a Positioned<String>,
|
||||
_name: &'a Positioned<&str>,
|
||||
value: &'a Positioned<Value>,
|
||||
) {
|
||||
if let Some(ref scope) = self.current_scope {
|
||||
|
@ -128,7 +128,7 @@ impl<'a> Visitor<'a> for NoUnusedVariables<'a> {
|
|||
self.spreads
|
||||
.entry(scope.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(fragment_spread.fragment_name.as_str());
|
||||
.push(fragment_spread.fragment_name.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ impl<'a, 'ctx> FindConflicts<'a, 'ctx> {
|
|||
let output_name = field
|
||||
.alias
|
||||
.as_ref()
|
||||
.map(|name| name.as_str())
|
||||
.unwrap_or_else(|| field.name.as_str());
|
||||
.map(|name| name.node)
|
||||
.unwrap_or_else(|| field.name.node);
|
||||
self.add_output(output_name, field);
|
||||
}
|
||||
Selection::InlineFragment(inline_fragment) => {
|
||||
|
@ -66,7 +66,7 @@ impl<'a, 'ctx> FindConflicts<'a, 'ctx> {
|
|||
}
|
||||
|
||||
for (name, value) in &prev_field.arguments {
|
||||
match field.get_argument(name.as_str())
|
||||
match field.get_argument(name.node)
|
||||
{
|
||||
Some(other_value) if value == other_value => {}
|
||||
_=> self.ctx.report_error(
|
||||
|
|
|
@ -10,11 +10,10 @@ pub struct PossibleFragmentSpreads<'a> {
|
|||
|
||||
impl<'a> Visitor<'a> for PossibleFragmentSpreads<'a> {
|
||||
fn enter_document(&mut self, _ctx: &mut VisitorContext<'a>, doc: &'a Document) {
|
||||
for d in &doc.definitions {
|
||||
for d in doc.definitions() {
|
||||
if let Definition::Fragment(fragment) = &d.node {
|
||||
let TypeCondition::On(type_name) = &fragment.type_condition.node;
|
||||
self.fragment_types
|
||||
.insert(fragment.name.as_str(), type_name);
|
||||
self.fragment_types.insert(fragment.name.node, type_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +23,7 @@ impl<'a> Visitor<'a> for PossibleFragmentSpreads<'a> {
|
|||
ctx: &mut VisitorContext<'a>,
|
||||
fragment_spread: &'a Positioned<FragmentSpread>,
|
||||
) {
|
||||
if let Some(fragment_type) = self
|
||||
.fragment_types
|
||||
.get(fragment_spread.fragment_name.as_str())
|
||||
{
|
||||
if let Some(fragment_type) = self.fragment_types.get(fragment_spread.fragment_name.node) {
|
||||
if let Some(current_type) = ctx.current_type() {
|
||||
if let Some(on_type) = ctx.registry.types.get(*fragment_type) {
|
||||
if !current_type.type_overlap(on_type) {
|
||||
|
@ -53,7 +49,7 @@ impl<'a> Visitor<'a> for PossibleFragmentSpreads<'a> {
|
|||
if let Some(TypeCondition::On(fragment_type)) =
|
||||
&inline_fragment.type_condition.as_ref().map(|c| &c.node)
|
||||
{
|
||||
if let Some(on_type) = ctx.registry.types.get(fragment_type.as_str()) {
|
||||
if let Some(on_type) = ctx.registry.types.get(fragment_type.node) {
|
||||
if !parent_type.type_overlap(&on_type) {
|
||||
ctx.report_error(
|
||||
vec![inline_fragment.position()],
|
||||
|
|
|
@ -12,14 +12,14 @@ impl<'a> Visitor<'a> for ProvidedNonNullArguments {
|
|||
ctx: &mut VisitorContext<'a>,
|
||||
directive: &'a Positioned<Directive>,
|
||||
) {
|
||||
if let Some(schema_directive) = ctx.registry.directives.get(directive.name.as_str()) {
|
||||
if let Some(schema_directive) = ctx.registry.directives.get(directive.name.node) {
|
||||
for arg in schema_directive.args.values() {
|
||||
if TypeName::create(&arg.ty).is_non_null()
|
||||
&& arg.default_value.is_none()
|
||||
&& directive
|
||||
.arguments
|
||||
.iter()
|
||||
.find(|(name, _)| name.as_str() == arg.name)
|
||||
.find(|(name, _)| name.node == arg.name)
|
||||
.is_none()
|
||||
{
|
||||
ctx.report_error(vec![directive.position()],
|
||||
|
@ -41,7 +41,7 @@ impl<'a> Visitor<'a> for ProvidedNonNullArguments {
|
|||
&& field
|
||||
.arguments
|
||||
.iter()
|
||||
.find(|(name, _)| name.as_str() == arg.name)
|
||||
.find(|(name, _)| name.node == arg.name)
|
||||
.is_none()
|
||||
{
|
||||
ctx.report_error(vec![field.position()],
|
||||
|
|
|
@ -20,7 +20,7 @@ impl<'a> Visitor<'a> for UniqueArgumentNames<'a> {
|
|||
fn enter_argument(
|
||||
&mut self,
|
||||
ctx: &mut VisitorContext<'a>,
|
||||
name: &'a Positioned<String>,
|
||||
name: &'a Positioned<&str>,
|
||||
_value: &'a Positioned<Value>,
|
||||
) {
|
||||
if !self.names.insert(name) {
|
||||
|
|
|
@ -31,7 +31,7 @@ impl<'a> Visitor<'a> for UniqueOperationNames<'a> {
|
|||
};
|
||||
|
||||
if let Some(name) = name {
|
||||
if !self.names.insert(name.as_str()) {
|
||||
if !self.names.insert(name.node) {
|
||||
ctx.report_error(
|
||||
vec![name.position()],
|
||||
format!("There can only be one operation named \"{}\"", name),
|
||||
|
|
|
@ -22,7 +22,7 @@ impl<'a> Visitor<'a> for UniqueVariableNames<'a> {
|
|||
ctx: &mut VisitorContext<'a>,
|
||||
variable_definition: &'a Positioned<VariableDefinition>,
|
||||
) {
|
||||
if !self.names.insert(variable_definition.name.as_str()) {
|
||||
if !self.names.insert(variable_definition.name.node) {
|
||||
ctx.report_error(
|
||||
vec![variable_definition.position()],
|
||||
format!(
|
||||
|
|
|
@ -31,7 +31,7 @@ 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.name.as_str() == *var_name) {
|
||||
if let Some(def) = var_defs.iter().find(|def| def.name.node == *var_name) {
|
||||
let expected_type = match (&def.default_value, &def.var_type.node) {
|
||||
(Some(_), Type::List(_)) => def.var_type.to_string() + "!",
|
||||
(Some(_), Type::Named(_)) => def.var_type.to_string() + "!",
|
||||
|
@ -80,7 +80,7 @@ impl<'a> Visitor<'a> for VariableInAllowedPosition<'a> {
|
|||
_ctx: &mut VisitorContext<'a>,
|
||||
fragment_definition: &'a Positioned<FragmentDefinition>,
|
||||
) {
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.as_str()));
|
||||
self.current_scope = Some(Scope::Fragment(fragment_definition.name.node));
|
||||
}
|
||||
|
||||
fn enter_variable_definition(
|
||||
|
@ -105,7 +105,7 @@ impl<'a> Visitor<'a> for VariableInAllowedPosition<'a> {
|
|||
self.spreads
|
||||
.entry(scope.clone())
|
||||
.or_insert_with(HashSet::new)
|
||||
.insert(fragment_spread.fragment_name.as_str());
|
||||
.insert(fragment_spread.fragment_name.node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ impl<'a> Visitor<'a> for VariableInAllowedPosition<'a> {
|
|||
self.variable_usages
|
||||
.entry(scope.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push((name.as_str(), pos, *expected_type));
|
||||
.push((name, pos, *expected_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ pub fn referenced_variables(value: &Value) -> Vec<&str> {
|
|||
fn referenced_variables_to_vec<'a>(value: &'a Value, vars: &mut Vec<&'a str>) {
|
||||
match value {
|
||||
Value::Variable(name) => {
|
||||
vars.push(name.as_str());
|
||||
vars.push(name);
|
||||
}
|
||||
Value::List(values) => values
|
||||
.iter()
|
||||
|
@ -38,14 +38,13 @@ pub fn operation_name(operation_definition: &OperationDefinition) -> (Option<&st
|
|||
match operation_definition {
|
||||
OperationDefinition::SelectionSet(selection_set) => (None, selection_set.position()),
|
||||
OperationDefinition::Query(query) => {
|
||||
(query.name.as_ref().map(|n| n.as_str()), query.position())
|
||||
(query.name.as_ref().map(|n| n.node), query.position())
|
||||
}
|
||||
OperationDefinition::Mutation(mutation) => {
|
||||
(mutation.name.as_ref().map(|n| n.node), mutation.position())
|
||||
}
|
||||
OperationDefinition::Mutation(mutation) => (
|
||||
mutation.name.as_ref().map(|n| n.as_str()),
|
||||
mutation.position(),
|
||||
),
|
||||
OperationDefinition::Subscription(subscription) => (
|
||||
subscription.name.as_ref().map(|n| n.as_str()),
|
||||
subscription.name.as_ref().map(|n| n.node),
|
||||
subscription.position(),
|
||||
),
|
||||
}
|
||||
|
@ -107,7 +106,7 @@ pub fn is_valid_input_value(
|
|||
}
|
||||
registry::Type::Enum { enum_values, .. } => match value {
|
||||
Value::Enum(name) => {
|
||||
if !enum_values.contains_key(name.as_str()) {
|
||||
if !enum_values.contains_key(name) {
|
||||
Some(valid_error(
|
||||
&path_node,
|
||||
format!(
|
||||
|
@ -129,7 +128,7 @@ pub fn is_valid_input_value(
|
|||
Value::Object(values) => {
|
||||
let mut input_names = values
|
||||
.keys()
|
||||
.map(|name| name.as_str())
|
||||
.map(|name| name.as_ref())
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
for field in input_fields.values() {
|
||||
|
|
|
@ -23,10 +23,10 @@ impl<'a> VisitorContext<'a> {
|
|||
type_stack: Default::default(),
|
||||
input_type: Default::default(),
|
||||
fragments: doc
|
||||
.definitions
|
||||
.definitions()
|
||||
.iter()
|
||||
.filter_map(|d| match &d.node {
|
||||
Definition::Fragment(fragment) => Some((fragment.name.as_str(), fragment)),
|
||||
Definition::Fragment(fragment) => Some((fragment.name.node, fragment)),
|
||||
_ => None,
|
||||
})
|
||||
.collect(),
|
||||
|
@ -147,14 +147,14 @@ pub trait Visitor<'a> {
|
|||
fn enter_argument(
|
||||
&mut self,
|
||||
_ctx: &mut VisitorContext<'a>,
|
||||
_name: &'a Positioned<String>,
|
||||
_name: &'a Positioned<&str>,
|
||||
_value: &'a Positioned<Value>,
|
||||
) {
|
||||
}
|
||||
fn exit_argument(
|
||||
&mut self,
|
||||
_ctx: &mut VisitorContext<'a>,
|
||||
_name: &'a Positioned<String>,
|
||||
_name: &'a Positioned<&str>,
|
||||
_value: &'a Positioned<Value>,
|
||||
) {
|
||||
}
|
||||
|
@ -340,7 +340,7 @@ where
|
|||
fn enter_argument(
|
||||
&mut self,
|
||||
ctx: &mut VisitorContext<'a>,
|
||||
name: &'a Positioned<String>,
|
||||
name: &'a Positioned<&str>,
|
||||
value: &'a Positioned<Value>,
|
||||
) {
|
||||
self.0.enter_argument(ctx, name, value);
|
||||
|
@ -350,7 +350,7 @@ where
|
|||
fn exit_argument(
|
||||
&mut self,
|
||||
ctx: &mut VisitorContext<'a>,
|
||||
name: &'a Positioned<String>,
|
||||
name: &'a Positioned<&str>,
|
||||
value: &'a Positioned<Value>,
|
||||
) {
|
||||
self.0.exit_argument(ctx, name, value);
|
||||
|
@ -451,14 +451,14 @@ fn visit_definitions<'a, V: Visitor<'a>>(
|
|||
ctx: &mut VisitorContext<'a>,
|
||||
doc: &'a Document,
|
||||
) {
|
||||
for d in &doc.definitions {
|
||||
for d in doc.definitions() {
|
||||
match &d.node {
|
||||
Definition::Operation(operation) => {
|
||||
visit_operation_definition(v, ctx, operation);
|
||||
}
|
||||
Definition::Fragment(fragment) => {
|
||||
let TypeCondition::On(name) = &fragment.type_condition.node;
|
||||
ctx.with_type(ctx.registry.types.get(name.as_str()), |ctx| {
|
||||
ctx.with_type(ctx.registry.types.get(name.node), |ctx| {
|
||||
visit_fragment_definition(v, ctx, fragment)
|
||||
});
|
||||
}
|
||||
|
@ -539,7 +539,7 @@ fn visit_selection<'a, V: Visitor<'a>>(
|
|||
v.enter_selection(ctx, selection);
|
||||
match &selection.node {
|
||||
Selection::Field(field) => {
|
||||
if field.name.as_str() != "__typename" {
|
||||
if field.name.node != "__typename" {
|
||||
ctx.with_type(
|
||||
ctx.current_type()
|
||||
.and_then(|ty| ty.field_by_name(&field.name))
|
||||
|
@ -559,7 +559,7 @@ fn visit_selection<'a, V: Visitor<'a>>(
|
|||
if let Some(TypeCondition::On(name)) =
|
||||
&inline_fragment.type_condition.as_ref().map(|c| &c.node)
|
||||
{
|
||||
ctx.with_type(ctx.registry.types.get(name.as_str()), |ctx| {
|
||||
ctx.with_type(ctx.registry.types.get(name.node), |ctx| {
|
||||
visit_inline_fragment(v, ctx, inline_fragment)
|
||||
});
|
||||
}
|
||||
|
@ -580,7 +580,7 @@ fn visit_field<'a, V: Visitor<'a>>(
|
|||
let expected_ty = ctx
|
||||
.parent_type()
|
||||
.and_then(|ty| ty.field_by_name(&field.name))
|
||||
.and_then(|schema_field| schema_field.args.get(name.as_str()))
|
||||
.and_then(|schema_field| schema_field.args.get(name.node))
|
||||
.map(|input_ty| TypeName::create(&input_ty.ty));
|
||||
ctx.with_input_type(expected_ty, |ctx| {
|
||||
visit_input_value(v, ctx, field.position(), expected_ty, value)
|
||||
|
@ -624,7 +624,7 @@ fn visit_input_value<'a, V: Visitor<'a>>(
|
|||
{
|
||||
if let Type::InputObject { input_fields, .. } = ty {
|
||||
for (item_key, item_value) in values {
|
||||
if let Some(input_value) = input_fields.get(item_key) {
|
||||
if let Some(input_value) = input_fields.get(item_key.as_ref()) {
|
||||
visit_input_value(
|
||||
v,
|
||||
ctx,
|
||||
|
@ -664,12 +664,12 @@ fn visit_directives<'a, V: Visitor<'a>>(
|
|||
for d in directives {
|
||||
v.enter_directive(ctx, d);
|
||||
|
||||
let schema_directive = ctx.registry.directives.get(d.name.as_str());
|
||||
let schema_directive = ctx.registry.directives.get(d.name.node);
|
||||
|
||||
for (name, value) in &d.arguments {
|
||||
v.enter_argument(ctx, name, value);
|
||||
let expected_ty = schema_directive
|
||||
.and_then(|schema_directive| schema_directive.args.get(name.as_str()))
|
||||
.and_then(|schema_directive| schema_directive.args.get(name.node))
|
||||
.map(|input_ty| TypeName::create(&input_ty.ty));
|
||||
ctx.with_input_type(expected_ty, |ctx| {
|
||||
visit_input_value(v, ctx, d.position(), expected_ty, value)
|
||||
|
|
Loading…
Reference in New Issue
Block a user