Merge pull request #605 from oeed/master
Ignored items flagged @skip in SelectionField and Lookahead
This commit is contained in:
commit
19bcc87154
@ -603,7 +603,7 @@ impl<'a> ContextBase<'a, &'a Positioned<Field>> {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn look_ahead(&self) -> Lookahead {
|
pub fn look_ahead(&self) -> Lookahead {
|
||||||
Lookahead::new(&self.query_env.fragments, &self.item.node)
|
Lookahead::new(&self.query_env.fragments, &self.item.node, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current field.
|
/// Get the current field.
|
||||||
@ -653,7 +653,7 @@ impl<'a> ContextBase<'a, &'a Positioned<Field>> {
|
|||||||
pub struct SelectionField<'a> {
|
pub struct SelectionField<'a> {
|
||||||
pub(crate) fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
pub(crate) fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||||
pub(crate) field: &'a Field,
|
pub(crate) field: &'a Field,
|
||||||
context: &'a Context<'a>,
|
pub(crate) context: &'a Context<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SelectionField<'a> {
|
impl<'a> SelectionField<'a> {
|
||||||
@ -727,7 +727,20 @@ impl<'a> Iterator for SelectionFieldsIter<'a> {
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
loop {
|
loop {
|
||||||
let it = self.iter.last_mut()?;
|
let it = self.iter.last_mut()?;
|
||||||
match it.next() {
|
let item = it.next();
|
||||||
|
if let Some(item) = item {
|
||||||
|
// ignore any items that are skipped (i.e. @skip/@include)
|
||||||
|
if self
|
||||||
|
.context
|
||||||
|
.is_skip(&item.node.directives())
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
// TODO: should we throw errors here? they will be caught later in execution and it'd cause major backwards compatibility issues
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match item {
|
||||||
Some(selection) => match &selection.node {
|
Some(selection) => match &selection.node {
|
||||||
Selection::Field(field) => {
|
Selection::Field(field) => {
|
||||||
return Some(SelectionField {
|
return Some(SelectionField {
|
||||||
|
@ -2,22 +2,26 @@ use std::collections::HashMap;
|
|||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use crate::parser::types::{Field, FragmentDefinition, Selection, SelectionSet};
|
use crate::parser::types::{Field, FragmentDefinition, Selection, SelectionSet};
|
||||||
|
use crate::Context;
|
||||||
use crate::{Name, Positioned, SelectionField};
|
use crate::{Name, Positioned, SelectionField};
|
||||||
|
|
||||||
/// A selection performed by a query.
|
/// A selection performed by a query.
|
||||||
pub struct Lookahead<'a> {
|
pub struct Lookahead<'a> {
|
||||||
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||||
fields: Vec<&'a Field>,
|
fields: Vec<&'a Field>,
|
||||||
|
context: &'a Context<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Lookahead<'a> {
|
impl<'a> Lookahead<'a> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||||
field: &'a Field,
|
field: &'a Field,
|
||||||
|
context: &'a Context<'a>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
fragments,
|
fragments,
|
||||||
fields: vec![field],
|
fields: vec![field],
|
||||||
|
context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,12 +33,19 @@ impl<'a> Lookahead<'a> {
|
|||||||
pub fn field(&self, name: &str) -> Self {
|
pub fn field(&self, name: &str) -> Self {
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
for field in &self.fields {
|
for field in &self.fields {
|
||||||
filter(&mut fields, self.fragments, &field.selection_set.node, name)
|
filter(
|
||||||
|
&mut fields,
|
||||||
|
self.fragments,
|
||||||
|
&field.selection_set.node,
|
||||||
|
name,
|
||||||
|
self.context,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
fragments: self.fragments,
|
fragments: self.fragments,
|
||||||
fields,
|
fields,
|
||||||
|
context: self.context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +61,7 @@ impl<'a> From<SelectionField<'a>> for Lookahead<'a> {
|
|||||||
Lookahead {
|
Lookahead {
|
||||||
fragments: selection_field.fragments,
|
fragments: selection_field.fragments,
|
||||||
fields: vec![selection_field.field],
|
fields: vec![selection_field.field],
|
||||||
|
context: selection_field.context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,6 +83,7 @@ impl<'a> TryFrom<&[SelectionField<'a>]> for Lookahead<'a> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|selection_field| selection_field.field)
|
.map(|selection_field| selection_field.field)
|
||||||
.collect(),
|
.collect(),
|
||||||
|
context: selection_fields[0].context,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,22 +94,40 @@ fn filter<'a>(
|
|||||||
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||||
selection_set: &'a SelectionSet,
|
selection_set: &'a SelectionSet,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
context: &'a Context<'a>,
|
||||||
) {
|
) {
|
||||||
for item in &selection_set.items {
|
for item in &selection_set.items {
|
||||||
// doing this imperatively is a bit nasty, but using iterators would
|
// doing this imperatively is a bit nasty, but using iterators would
|
||||||
// require a boxed return type (I believe) as its recusive
|
// require a boxed return type (I believe) as its recusive
|
||||||
|
|
||||||
|
// ignore any items that are skipped (i.e. @skip/@include)
|
||||||
|
if context.is_skip(&item.node.directives()).unwrap_or(false) {
|
||||||
|
// TODO: should we throw errors here? they will be caught later in execution and it'd cause major backwards compatibility issues
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
match &item.node {
|
match &item.node {
|
||||||
Selection::Field(field) => {
|
Selection::Field(field) => {
|
||||||
if field.node.name.node == name {
|
if field.node.name.node == name {
|
||||||
fields.push(&field.node)
|
fields.push(&field.node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Selection::InlineFragment(fragment) => {
|
Selection::InlineFragment(fragment) => filter(
|
||||||
filter(fields, fragments, &fragment.node.selection_set.node, name)
|
fields,
|
||||||
}
|
fragments,
|
||||||
|
&fragment.node.selection_set.node,
|
||||||
|
name,
|
||||||
|
context,
|
||||||
|
),
|
||||||
Selection::FragmentSpread(spread) => {
|
Selection::FragmentSpread(spread) => {
|
||||||
if let Some(fragment) = fragments.get(&spread.node.fragment_name.node) {
|
if let Some(fragment) = fragments.get(&spread.node.fragment_name.node) {
|
||||||
filter(fields, fragments, &fragment.node.selection_set.node, name)
|
filter(
|
||||||
|
fields,
|
||||||
|
fragments,
|
||||||
|
&fragment.node.selection_set.node,
|
||||||
|
name,
|
||||||
|
context,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user