private void CompleteSelectionSet(CompilerContext context) { foreach (Selection selection in context.Fields.Values) { // we now mark the selection read-only and add it to the final selection-set. selection.MakeReadOnly(); context.Selections.Add(selection); // if one selection of a selection-set is conditional, // then the whole set is conditional and has to be post processed during execution. if (!context.IsConditional && (selection.IsConditional || selection.IsInternal)) { context.IsConditional = true; } // if the field of the selection returns a composite type we will traverse // the child selection-sets as well. INamedType fieldType = selection.Field.Type.NamedType(); if (fieldType.IsCompositeType()) { if (selection.SelectionSet is null) { // composite fields always have to have a selection-set // otherwise we need to throw. throw QueryCompiler_CompositeTypeSelectionSet(selection.SyntaxNode); } IReadOnlyList <ObjectType> possibleTypes = _schema.GetPossibleTypes(fieldType); for (var i = possibleTypes.Count - 1; i >= 0; i--) { // we branch the context which will enqueue the new context // to the work backlog. context.TryBranch(possibleTypes[i], selection); } } } context.Complete(); }
private void Visit( SelectionSetNode selectionSet, ObjectType typeContext, Stack <IObjectField> fieldContext, PSS current, Action <PSS> register, IDictionary <ISelectionNode, SelectionIncludeCondition> includeConditionLookup, List <ISelectionSetOptimizer> optimizers, bool internalSelection = false) { // we first collect the fields that we find in the selection set ... IDictionary <string, PreparedSelection> fields = CollectFields(typeContext, selectionSet, includeConditionLookup, internalSelection); // ... after that is done we will check if there are query optimizer that want // to provide additional fields. OptimizeSelectionSet(fieldContext, typeContext, selectionSet, fields, optimizers); var selections = new List <PreparedSelection>(); var isConditional = false; foreach (PreparedSelection selection in fields.Values) { // we now make the selection read-only and add it to the final selection-set. selection.MakeReadOnly(); selections.Add(selection); // if one selection of a selection-set is conditional, // then the whole set is conditional. if (!isConditional && (selection.IsConditional || selection.IsInternal)) { isConditional = true; } // if the field of the selection returns a composite type we will traverse // the child selection-sets as well. INamedType fieldType = selection.Field.Type.NamedType(); if (fieldType.IsCompositeType()) { if (selection.SelectionSet is null) { // composite fields always have to have a selection-set // otherwise we need to throw. throw QueryCompiler_CompositeTypeSelectionSet(selection.Selection); } var next = new PSS(selection.SelectionSet); register(next); IReadOnlyList <ObjectType> possibleTypes = _schema.GetPossibleTypes(fieldType); for (var i = 0; i < possibleTypes.Count; i++) { // we prepare the field context and check if there are field specific // optimizers that we might want to include. fieldContext.Push(selection.Field); var initialCount = optimizers.Count; var registered = RegisterOptimizers(optimizers, selection.Field); Visit( selection.SelectionSet, possibleTypes[i], fieldContext, next, register, includeConditionLookup, optimizers, selection.IsInternal); // lets clean up the context again and move on to the next. UnregisterOptimizers(optimizers, initialCount, registered); fieldContext.Pop(); } } } current.AddSelections( typeContext, new PreparedSelectionList(selections, isConditional)); }