コード例 #1
0
        private List <SelectionItem> BuildSelectionItemsList(Node selSetNode, NamedRequestObject parentItem)
        {
            var selItems = new List <SelectionItem>();

            foreach (var selNode in selSetNode.ChildNodes)
            {
                SelectionItem selItem = null;
                switch (selNode.Term.Name)
                {
                case TermNames.SelField:
                    selItem = BuildSelectionField(selNode, parentItem);
                    break;

                case TermNames.FragmSpread:
                    var name = selNode.ChildNodes[1].GetText();
                    selItem = new FragmentSpread()
                    {
                        Name = name, SourceLocation = selNode.GetLocation()
                    };
                    var dirListNode = selNode.FindChild(TermNames.DirListOpt);
                    selItem.Directives = BuildDirectives(dirListNode, DirectiveLocation.Field, selItem);
                    break;

                case TermNames.InlineFragm:
                    selItem = BuildInlineFragment(selNode);
                    break;
                }
                if (selItem != null)
                {
                    selItems.Add(selItem);
                }
            }
            return(selItems);
        }
コード例 #2
0
        private string PrintFragmentSpread(FragmentSpread node)
        {
            var name       = PrintName(node.FragmentName);
            var directives = node.Directives?.Select(PrintDirective) ?? Array.Empty <string>();

            return($"...{name}{Wrap(string.Empty, Join(directives, " "))}");
        }
コード例 #3
0
        public void MergeFieldAndFragment()
        {
            var fragment = new FragmentDefinition(new NameNode("fragment"));
            var fragmentSelection = new SelectionSet();
            fragmentSelection.Add(FirstTestField);
            fragment.SelectionSet = fragmentSelection;
            fragment.Type = new GraphQL.Language.AST.NamedType(
                new NameNode("Person"));

            var fragments = new Fragments { fragment };

            var schema = new Schema();
            schema.RegisterType(new PersonType());

            var context = new ExecutionContext
            {
                Fragments = fragments,
                Schema = schema
            };

            var fragSpread = new FragmentSpread(new NameNode("fragment"));
            var outerSelection = new SelectionSet();
            outerSelection.Add(fragSpread);
            outerSelection.Add(SecondTestField);

            var fields = ExecutionHelper.CollectFields(
                context,
                new PersonType(),
                outerSelection);

            fields.ShouldHaveSingleItem();
            fields["test"].SelectionSet.Selections.ShouldContain(x => x.IsEqualTo(FirstInnerField));
            fields["test"].SelectionSet.Selections.ShouldContain(x => x.IsEqualTo(SecondInnerField));
        }
コード例 #4
0
        } //method

        private bool Fragments_CheckFragmentSpreadCompatible(FragmentSpread fragmentSpread, TypeDefBase parentType)
        {
            var fragmOnTypeDef = fragmentSpread.Fragment.OnTypeRef.TypeDef;

            if (parentType == fragmOnTypeDef)
            {
                return(true); //trivial case
            }
            var fragmName = fragmentSpread.Name;

            switch (parentType)
            {
            case ObjectTypeDef parObjType:
                // parent type is object type; the only allowed (non-trivial) case is fragment on interface
                if (!parObjType.Implements.Contains(fragmOnTypeDef))
                {
                    AddError($"Fragment ref '{fragmName}': fragment is defined on type '{fragmOnTypeDef.Name}'" +
                             $" which is not compatible with type '{parentType.Name}'.",
                             fragmentSpread);
                    return(false);
                }
                break;

            case InterfaceTypeDef parIntfType:
                // parent type is interface; fragment's type must be object implementing interface
                if (!parIntfType.PossibleTypes.Contains(fragmOnTypeDef))
                {
                    AddError($"Fragment ref {fragmName}: fragment is defined on type '{fragmOnTypeDef.Name}'" +
                             $" which is not compatible with type '{parentType.Name}'.",
                             fragmentSpread);
                    return(false);
                }
                break;

            case UnionTypeDef parUnionType:
                // fragment's on-type must be one of the unioned types; of if fragm is on interface, implemented by at least one of the types
                if (fragmOnTypeDef is InterfaceTypeDef fragmIntType)
                {
                    if (!parUnionType.PossibleTypes.Any(t => t.Implements.Contains(fragmIntType)))
                    {
                        AddError($"Fragment ref {fragmName}: fragment is defined on interface '{fragmIntType.Name}' which is " +
                                 $"not implemented by any of the unioned types in '{parentType.Name}'.", fragmentSpread);
                        return(false);
                    }
                }
                else
                {
                    // fragm is on object type
                    if (!parUnionType.PossibleTypes.Contains(fragmOnTypeDef))
                    {
                        AddError($"Fragment ref {fragmName}: fragment is defined on type '{fragmOnTypeDef.Name}' which is not " +
                                 $"one of the unioned types in '{parentType.Name}'.", fragmentSpread);
                        return(false);
                    }
                }
                break;
            }
            return(true);
        }
コード例 #5
0
    private void VisitFragmentSpread(FragmentSpread node)
    {
        EnterNode(node);

        Visit(node.Directives);

        ExitNode(node);
    }
コード例 #6
0
ファイル: RulesWalker.cs プロジェクト: digvand/tanka-graphql
        public override FragmentSpread BeginVisitFragmentSpread(
            FragmentSpread fragmentSpread)
        {
            {
                Tracker.EnterFragmentSpread?.Invoke(fragmentSpread);
            }

            return(base.BeginVisitFragmentSpread(fragmentSpread));
        }
コード例 #7
0
        private FragmentSpread BuildInlineFragment(Node selNode)
        {
            // Create fragment def and fragment spread
            var fragmDefs = _requestContext.ParsedRequest.Fragments;
            var fragmDef  = new FragmentDef()
            {
                IsInline = true, Name = "_inline_" + fragmDefs.Count
            };

            fragmDefs.Add(fragmDef);

            // note: On-type is optional, spec mentions this: https://spec.graphql.org/June2018/#sec-Inline-Fragments
            var typeNameNode = selNode.FindChild(TermNames.TypeCondOpt)?.FindChild(TermNames.Name);

            if (typeNameNode != null)
            {
                var onTypeName = typeNameNode.GetText();
                fragmDef.OnTypeRef = new OnTypeRef()
                {
                    Name = onTypeName, SourceLocation = typeNameNode.GetLocation(), Parent = fragmDef
                };
            } //if
            // Selection set
            var selSetNode = selNode.FindChild(TermNames.SelSet);
            var items      = BuildSelectionItemsList(selSetNode, fragmDef);

            fragmDef.SelectionSubset = new SelectionSubset(fragmDef, items, selSetNode.GetLocation());
            // fragment spread
            var fragm = new FragmentSpread()
            {
                Fragment = fragmDef, Name = fragmDef.Name, IsInline = true, SourceLocation = selNode.GetLocation()
            };
            //Directives
            var dirListNode = selNode.FindChild(TermNames.DirListOpt);

            fragm.Directives = BuildDirectives(dirListNode, DirectiveLocation.InlineFragment, fragm);
            return(fragm);
        }
コード例 #8
0
ファイル: RequestMapper.cs プロジェクト: weiplanet/ngraphql
        private MappedFragmentSpread MapFragmentSpread(FragmentSpread fs, ObjectTypeDef objectTypeDef, bool isForUnion)
        {
            // if it is not inline fragment, it might need to map to FragmentDef; inline fragments are auto-mapped at construction
            if (fs.Fragment == null)
            {
                fs.Fragment = GetFragmentDef(fs.Name);
            }
            if (fs.Fragment == null)
            {
                AddError($"Fragment {fs.Name} not defined.", fs);
                return(null);
            }
            // inline fragments are mapped in-place, here.
            // we need to map them here, once we know the target type
            if (fs.IsInline)
            {
                var onTypeRef = fs.Fragment.OnTypeRef;
                var skip      = onTypeRef != null && onTypeRef.TypeDef != objectTypeDef;
                if (skip)
                {
                    return(null);
                }
                MapObjectSelectionSubset(fs.Fragment.SelectionSubset, objectTypeDef, fs.Directives, isForUnion);
            }
            // there must be mapped field set now
            var mappedFragmItemSet = fs.Fragment.SelectionSubset.MappedItemSets.FirstOrDefault(fset => fset.ObjectTypeDef == objectTypeDef);

            if (mappedFragmItemSet == null)
            {
                AddError($"FATAL: Could not retrieve mapped item list for fragment spread {fs.Name}", fs, ErrorCodes.ServerError);
                return(null);
            }
            var mappedSpread = new MappedFragmentSpread(fs, mappedFragmItemSet.Items);

            return(mappedSpread);
        }
コード例 #9
0
ファイル: VisitAllBase.cs プロジェクト: pekkah/tanka-graphql
 public virtual void Leave(FragmentSpread selection)
 {
 }
コード例 #10
0
ファイル: VisitAllBase.cs プロジェクト: pekkah/tanka-graphql
 public virtual void Enter(FragmentSpread selection)
 {
 }
コード例 #11
0
 private void Serialize(FragmentSpread fragmentSpread, StringBuilder builder)
 {
     builder.Append("...");
     builder.Append(fragmentSpread.Name);
 }
コード例 #12
0
ファイル: Visitor.cs プロジェクト: digvand/tanka-graphql
 public virtual FragmentSpread BeginVisitFragmentSpread(
     FragmentSpread fragmentSpread)
 {
     return(fragmentSpread);
 }
コード例 #13
0
 /// <summary>
 /// Initializes a new instance with the specified properties.
 /// </summary>
 public PossibleFragmentSpreadsError(ValidationContext context, FragmentSpread node, IGraphType parentType, IGraphType fragType)
     : base(context.OriginalQuery, NUMBER, TypeIncompatibleSpreadMessage(node.Name, context.Print(parentType), context.Print(fragType)), node)
 {
 }
コード例 #14
0
 /// <summary>
 /// Initializes a new instance with the specified properties.
 /// </summary>
 public KnownFragmentNamesError(ValidationContext context, FragmentSpread node, string fragmentName)
     : base(context.Document.OriginalQuery !, NUMBER, UnknownFragmentMessage(fragmentName), node)
コード例 #15
0
 protected override void EnterFragmentSpread(PrinterContext context, FragmentSpread fragmentSpread)
 {
     context.Append("...");
     context.Append(fragmentSpread.FragmentName);
 }
コード例 #16
0
        public ExecutionDocumentWalkerOptions Add(object visitor)
        {
            if (visitor is IVisit <ExecutableDocument> ed)
            {
                ExecutableDocument.Add(ed);
            }

            if (visitor is IVisit <FragmentDefinition> fd)
            {
                FragmentDefinition.Add(fd);
            }

            if (visitor is IVisit <OperationDefinition> od)
            {
                OperationDefinition.Add(od);
            }

            if (visitor is IVisit <SelectionSet> ss)
            {
                SelectionSet.Add(ss);
            }


            if (visitor is IVisit <ISelection> s)
            {
                Selection.Add(s);
            }

            if (visitor is IVisit <FieldSelection> fs)
            {
                FieldSelection.Add(fs);
            }

            if (visitor is IVisit <InlineFragment> ift)
            {
                InlineFragment.Add(ift);
            }

            if (visitor is IVisit <FragmentSpread> fgs)
            {
                FragmentSpread.Add(fgs);
            }

            if (visitor is IVisit <Argument> arg)
            {
                Argument.Add(arg);
            }

            if (visitor is IVisit <NamedType> nt)
            {
                NamedType.Add(nt);
            }

            if (visitor is IVisit <VariableDefinition> vd)
            {
                VariableDefinition.Add(vd);
            }

            if (visitor is IVisit <DefaultValue> dv)
            {
                DefaultValue.Add(dv);
            }

            if (visitor is IVisit <Value> v)
            {
                Value.Add(v);
            }

            if (visitor is IVisit <Directive> d)
            {
                Directive.Add(d);
            }

            if (visitor is IVisit <TypeBase> t)
            {
                Type.Add(t);
            }

            return(this);
        }
コード例 #17
0
 protected virtual void ExitFragmentSpread(TContext context, FragmentSpread fragmentSpread)
 {
 }