Improve lookahead
This commit is contained in:
parent
55753983a9
commit
42c3cfc17c
|
@ -517,9 +517,6 @@ impl<'a> ContextBase<'a, &'a Positioned<Field>> {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn look_ahead(&self) -> Lookahead {
|
pub fn look_ahead(&self) -> Lookahead {
|
||||||
Lookahead {
|
Lookahead::new(&self.query_env.document, &self.item.node)
|
||||||
document: &self.query_env.document,
|
|
||||||
field: Some(&self.item.node),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,24 @@
|
||||||
use crate::parser::types::{ExecutableDocumentData, Field, Selection, SelectionSet};
|
use crate::parser::types::{ExecutableDocumentData, Field, Selection, SelectionSet};
|
||||||
|
|
||||||
/// A selection performed by a query
|
/// A selection performed by a query.
|
||||||
pub struct Lookahead<'a> {
|
pub struct Lookahead<'a> {
|
||||||
pub(crate) document: &'a ExecutableDocumentData,
|
document: &'a ExecutableDocumentData,
|
||||||
pub(crate) field: Option<&'a Field>,
|
field: Option<&'a Field>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Lookahead<'a> {
|
impl<'a> Lookahead<'a> {
|
||||||
/// Check if the specified field exists in the current selection.
|
pub(crate) fn new(document: &'a ExecutableDocumentData, field: &'a Field) -> Self {
|
||||||
|
Self {
|
||||||
|
document,
|
||||||
|
field: Some(field),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the first subfield of the selection set with the specified name. This will ignore
|
||||||
|
/// aliases.
|
||||||
|
///
|
||||||
|
/// For example, calling `.field("a")` on `{ a { b } }` will return a lookahead that
|
||||||
|
/// represents `{ b }`.
|
||||||
pub fn field(&self, name: &str) -> Self {
|
pub fn field(&self, name: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
document: self.document,
|
document: self.document,
|
||||||
|
@ -29,32 +40,25 @@ fn find<'a>(
|
||||||
selection_set: &'a SelectionSet,
|
selection_set: &'a SelectionSet,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Option<&'a Field> {
|
) -> Option<&'a Field> {
|
||||||
for item in &selection_set.items {
|
selection_set
|
||||||
match &item.node {
|
.items
|
||||||
|
.iter()
|
||||||
|
.find_map(|item| match &item.node {
|
||||||
Selection::Field(field) => {
|
Selection::Field(field) => {
|
||||||
if field.node.name.node == name {
|
if field.node.name.node == name {
|
||||||
return Some(&field.node);
|
Some(&field.node)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Selection::InlineFragment(inline_fragment) => {
|
Selection::InlineFragment(fragment) => {
|
||||||
if let Some(field) = find(document, &inline_fragment.node.selection_set.node, name)
|
find(document, &fragment.node.selection_set.node, name)
|
||||||
{
|
|
||||||
return Some(field);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Selection::FragmentSpread(fragment_spread) => {
|
Selection::FragmentSpread(spread) => document
|
||||||
if let Some(fragment) = document
|
.fragments
|
||||||
.fragments
|
.get(&spread.node.fragment_name.node)
|
||||||
.get(&fragment_spread.node.fragment_name.node)
|
.and_then(|fragment| find(document, &fragment.node.selection_set.node, name)),
|
||||||
{
|
})
|
||||||
if let Some(field) = find(document, &fragment.node.selection_set.node, name) {
|
|
||||||
return Some(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user