Ignore items flagged @skip in SelectionField and Lookahead
This commit is contained in:
parent
f2e7c1a80c
commit
7dcea3c721
|
@ -603,7 +603,7 @@ impl<'a> ContextBase<'a, &'a Positioned<Field>> {
|
|||
/// }
|
||||
/// ```
|
||||
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.
|
||||
|
@ -653,7 +653,7 @@ impl<'a> ContextBase<'a, &'a Positioned<Field>> {
|
|||
pub struct SelectionField<'a> {
|
||||
pub(crate) fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||
pub(crate) field: &'a Field,
|
||||
context: &'a Context<'a>,
|
||||
pub(crate) context: &'a Context<'a>,
|
||||
}
|
||||
|
||||
impl<'a> SelectionField<'a> {
|
||||
|
@ -727,7 +727,20 @@ impl<'a> Iterator for SelectionFieldsIter<'a> {
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
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 {
|
||||
Selection::Field(field) => {
|
||||
return Some(SelectionField {
|
||||
|
|
|
@ -2,22 +2,26 @@ use std::collections::HashMap;
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use crate::parser::types::{Field, FragmentDefinition, Selection, SelectionSet};
|
||||
use crate::Context;
|
||||
use crate::{Name, Positioned, SelectionField};
|
||||
|
||||
/// A selection performed by a query.
|
||||
pub struct Lookahead<'a> {
|
||||
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||
fields: Vec<&'a Field>,
|
||||
context: &'a Context<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Lookahead<'a> {
|
||||
pub(crate) fn new(
|
||||
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||
field: &'a Field,
|
||||
context: &'a Context<'a>,
|
||||
) -> Self {
|
||||
Self {
|
||||
fragments,
|
||||
fields: vec![field],
|
||||
context,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,12 +33,19 @@ impl<'a> Lookahead<'a> {
|
|||
pub fn field(&self, name: &str) -> Self {
|
||||
let mut fields = Vec::new();
|
||||
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 {
|
||||
fragments: self.fragments,
|
||||
fields,
|
||||
context: self.context,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +61,7 @@ impl<'a> From<SelectionField<'a>> for Lookahead<'a> {
|
|||
Lookahead {
|
||||
fragments: selection_field.fragments,
|
||||
fields: vec![selection_field.field],
|
||||
context: selection_field.context,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +83,7 @@ impl<'a> TryFrom<&[SelectionField<'a>]> for Lookahead<'a> {
|
|||
.iter()
|
||||
.map(|selection_field| selection_field.field)
|
||||
.collect(),
|
||||
context: selection_fields[0].context,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -81,22 +94,40 @@ fn filter<'a>(
|
|||
fragments: &'a HashMap<Name, Positioned<FragmentDefinition>>,
|
||||
selection_set: &'a SelectionSet,
|
||||
name: &str,
|
||||
context: &'a Context<'a>,
|
||||
) {
|
||||
for item in &selection_set.items {
|
||||
// doing this imperatively is a bit nasty, but using iterators would
|
||||
// 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 {
|
||||
Selection::Field(field) => {
|
||||
if field.node.name.node == name {
|
||||
fields.push(&field.node)
|
||||
}
|
||||
}
|
||||
Selection::InlineFragment(fragment) => {
|
||||
filter(fields, fragments, &fragment.node.selection_set.node, name)
|
||||
}
|
||||
Selection::InlineFragment(fragment) => filter(
|
||||
fields,
|
||||
fragments,
|
||||
&fragment.node.selection_set.node,
|
||||
name,
|
||||
context,
|
||||
),
|
||||
Selection::FragmentSpread(spread) => {
|
||||
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