pub fn collect_fields<'a, R>(
    ctx: ExecutionContext<'a, R>,
    object_type: &s::ObjectType,
    selection_set: &'a q::SelectionSet,
    visited_fragments: Option<HashSet<&'a q::Name>>,
) -> IndexMap<&'a String, Vec<&'a q::Field>>
where
    R: Resolver,
{
    let mut visited_fragments = visited_fragments.unwrap_or_default();
    let mut grouped_fields: IndexMap<_, Vec<_>> = IndexMap::new();

    // Only consider selections that are not skipped and should be included
    let selections: Vec<_> = selection_set
        .items
        .iter()
        .filter(|selection| !qast::skip_selection(selection, ctx.variable_values.deref()))
        .filter(|selection| qast::include_selection(selection, ctx.variable_values.deref()))
        .collect();

    for selection in selections {
        match selection {
            q::Selection::Field(ref field) => {
                // Obtain the response key for the field
                let response_key = qast::get_response_key(field);

                // Create a field group for this response key on demand and
                // append the selection field to this group.
                grouped_fields.entry(response_key).or_default().push(field);
            }

            q::Selection::FragmentSpread(spread) => {
                // Only consider the fragment if it hasn't already been included,
                // as would be the case if the same fragment spread ...Foo appeared
                // twice in the same selection set
                if !visited_fragments.contains(&spread.fragment_name) {
                    visited_fragments.insert(&spread.fragment_name);

                    // Resolve the fragment using its name and, if it applies, collect
                    // fields for the fragment and group them
                    qast::get_fragment(&ctx.document, &spread.fragment_name)
                        .and_then(|fragment| {
                            // We have a fragment, only pass it on if it applies to the
                            // current object type
                            if does_fragment_type_apply(
                                ctx.clone(),
                                object_type,
                                &fragment.type_condition,
                            ) {
                                Some(fragment)
                            } else {
                                None
                            }
                        })
                        .map(|fragment| {
                            // We have a fragment that applies to the current object type,
                            // collect its fields into response key groups
                            let fragment_grouped_field_set = collect_fields(
                                ctx.clone(),
                                object_type,
                                &fragment.selection_set,
                                Some(visited_fragments.clone()),
                            );

                            // Add all items from each fragments group to the field group
                            // with the corresponding response key
                            for (response_key, mut fragment_group) in fragment_grouped_field_set {
                                grouped_fields
                                    .entry(response_key)
                                    .or_default()
                                    .append(&mut fragment_group);
                            }
                        });
                }
            }

            q::Selection::InlineFragment(fragment) => {
                let applies = match &fragment.type_condition {
                    Some(cond) => does_fragment_type_apply(ctx.clone(), object_type, &cond),
                    None => true,
                };

                if applies {
                    let fragment_grouped_field_set = collect_fields(
                        ctx.clone(),
                        object_type,
                        &fragment.selection_set,
                        Some(visited_fragments.clone()),
                    );

                    for (response_key, mut fragment_group) in fragment_grouped_field_set {
                        grouped_fields
                            .entry(response_key)
                            .or_default()
                            .append(&mut fragment_group);
                    }
                }
            }
        };
    }

    grouped_fields
}
/// Collects fields of a selection set.
Collects fields of a selection set.
Collects fields of a selection set .
pub fn collect_fields<'a, R>(
    ctx: ExecutionContext<'a, R>,
    object_type: &s::ObjectType,
    selection_set: &'a q::SelectionSet,
    visited_fragments: Option<HashSet<&'a q::Name>>,
) -> IndexMap<&'a String, Vec<&'a q::Field>>
where
    R: Resolver,
{
    let mut visited_fragments = visited_fragments.unwrap_or_default();
    let mut grouped_fields: IndexMap<_, Vec<_>> = IndexMap::new();
    // Only consider selections that are not skipped and should be included
    let selections: Vec<_> = selection_set
        .items
        .iter()
        .filter(|selection| !qast::skip_selection(selection, ctx.variable_values.deref()))
        .filter(|selection| qast::include_selection(selection, ctx.variable_values.deref()))
        .collect();
    for selection in selections {
        match selection {
            q::Selection::Field(ref field) => {
                // Obtain the response key for the field
                let response_key = qast::get_response_key(field);
                // Create a field group for this response key on demand and
                // append the selection field to this group.
                grouped_fields.entry(response_key).or_default().push(field);
            }
            q::Selection::FragmentSpread(spread) => {
                // Only consider the fragment if it hasn't already been included,
                // as would be the case if the same fragment spread ...Foo appeared
                // twice in the same selection set
                if !visited_fragments.contains(&spread.fragment_name) {
                    visited_fragments.insert(&spread.fragment_name);
                    // Resolve the fragment using its name and, if it applies, collect
                    // fields for the fragment and group them
                    qast::get_fragment(&ctx.document, &spread.fragment_name)
                        .and_then(|fragment| {
                            // We have a fragment, only pass it on if it applies to the
                            // current object type
                            if does_fragment_type_apply(
                                ctx.clone(),
                                object_type,
                                &fragment.type_condition,
                            ) {
                                Some(fragment)
                            } else {
                                None
                            }
                        })
                        .map(|fragment| {
                            // We have a fragment that applies to the current object type,
                            // collect its fields into response key groups
                            let fragment_grouped_field_set = collect_fields(
                                ctx.clone(),
                                object_type,
                                &fragment.selection_set,
                                Some(visited_fragments.clone()),
                            );
                            // Add all items from each fragments group to the field group
                            // with the corresponding response key
                            for (response_key, mut fragment_group) in fragment_grouped_field_set {
                                grouped_fields
                                    .entry(response_key)
                                    .or_default()
                                    .append(&mut fragment_group);
                            }
                        });
                }
            }
            q::Selection::InlineFragment(fragment) => {
                let applies = match &fragment.type_condition {
                    Some(cond) => does_fragment_type_apply(ctx.clone(), object_type, &cond),
                    None => true,
                };
                if applies {
                    let fragment_grouped_field_set = collect_fields(
                        ctx.clone(),
                        object_type,
                        &fragment.selection_set,
                        Some(visited_fragments.clone()),
                    );
                    for (response_key, mut fragment_group) in fragment_grouped_field_set {
                        grouped_fields
                            .entry(response_key)
                            .or_default()
                            .append(&mut fragment_group);
                    }
                }
            }
        };
    }
    grouped_fields
}
pub fn collect_fields < ' a , R > ( ctx : ExecutionContext < ' a , R > , object_type : & s :: ObjectType , selection_set : & ' a q :: SelectionSet , visited_fragments : Option < HashSet < & ' a q :: Name > > , ) -> IndexMap < & ' a String , Vec < & ' a q :: Field > > where R : Resolver , { let mut visited_fragments = visited_fragments . unwrap_or_default ( ) ; let mut grouped_fields : IndexMap < _ , Vec < _ > > = IndexMap :: new ( ) ; // Only consider selections that are not skipped and should be included let selections : Vec < _ > = selection_set . items . iter ( ) . filter ( | selection | ! qast :: skip_selection ( selection , ctx . variable_values . deref ( ) ) ) . filter ( | selection | qast :: include_selection ( selection , ctx . variable_values . deref ( ) ) ) . collect ( ) ; for selection in selections { match selection { q :: Selection :: Field ( ref field ) => { // Obtain the response key for the field let response_key = qast :: get_response_key ( field ) ; // Create a field group for this response key on demand and // append the selection field to this group. grouped_fields . entry ( response_key ) . or_default ( ) . push ( field ) ; } q :: Selection :: FragmentSpread ( spread ) => { // Only consider the fragment if it hasn't already been included, // as would be the case if the same fragment spread ...Foo appeared // twice in the same selection set if ! visited_fragments . contains ( & spread . fragment_name ) { visited_fragments . insert ( & spread . fragment_name ) ; // Resolve the fragment using its name and, if it applies, collect // fields for the fragment and group them qast :: get_fragment ( & ctx . document , & spread . fragment_name ) . and_then ( | fragment | { // We have a fragment, only pass it on if it applies to the // current object type if does_fragment_type_apply ( ctx . clone ( ) , object_type , & fragment . type_condition , ) { Some ( fragment ) } else { None } } ) . map ( | fragment | { // We have a fragment that applies to the current object type, // collect its fields into response key groups let fragment_grouped_field_set = collect_fields ( ctx . clone ( ) , object_type , & fragment . selection_set , Some ( visited_fragments . clone ( ) ) , ) ; // Add all items from each fragments group to the field group // with the corresponding response key for ( response_key , mut fragment_group ) in fragment_grouped_field_set { grouped_fields . entry ( response_key ) . or_default ( ) . append ( & mut fragment_group ) ; } } ) ; } } q :: Selection :: InlineFragment ( fragment ) => { let applies = match & fragment . type_condition { Some ( cond ) => does_fragment_type_apply ( ctx . clone ( ) , object_type , & cond ) , None => true , } ; if applies { let fragment_grouped_field_set = collect_fields ( ctx . clone ( ) , object_type , & fragment . selection_set , Some ( visited_fragments . clone ( ) ) , ) ; for ( response_key , mut fragment_group ) in fragment_grouped_field_set { grouped_fields . entry ( response_key ) . or_default ( ) . append ( & mut fragment_group ) ; } } } } ; } grouped_fields }
Collects fields of a selection set.
Collects fields of a selection set .
ctx
ExecutionContext<'a, R>
object_type
&s::ObjectType
selection_set
&'a q::SelectionSet
visited_fragments
Option<HashSet<&'a q::Name>>
ctx
ExecutionContext<'a, R>
object_type
&s::ObjectType
selection_set
&'a q::SelectionSet
visited_fragments
Option<HashSet<&'a q::Name>>