private void GetFieldsAndFragmentNames(
            GraphQLSelectionSet node,
            Dictionary <string, ICollection <NodeAndDefinitions> > nodeDefinitions,
            ICollection <string> fragmentNames,
            GraphQLBaseType parentType,
            string presumedParentName = null)
        {
            foreach (var selection in node.Selections)
            {
                switch (selection.Kind)
                {
                case ASTNodeKind.Field:
                    var fieldSelection = selection as GraphQLFieldSelection;
                    var fieldName      = fieldSelection.Name.Value;
                    GraphQLObjectTypeFieldInfo fieldDefinition = null;

                    if (parentType is GraphQLComplexType)
                    {
                        fieldDefinition = ((GraphQLComplexType)parentType).GetFieldInfo(fieldName);
                    }

                    var responseName = fieldSelection.Alias != null
                            ? fieldSelection.Alias.Value
                            : fieldName;

                    if (!nodeDefinitions.ContainsKey(responseName))
                    {
                        nodeDefinitions.Add(responseName, new List <NodeAndDefinitions>());
                    }

                    nodeDefinitions[responseName].Add(new NodeAndDefinitions()
                    {
                        PresumedParentName = presumedParentName,
                        ParentType         = parentType,
                        Selection          = fieldSelection,
                        FieldDefinition    = fieldDefinition
                    });
                    break;

                case ASTNodeKind.FragmentSpread:
                    fragmentNames.Add(((GraphQLFragmentSpread)selection).Name.Value);
                    break;

                case ASTNodeKind.InlineFragment:
                    var inlineFragment     = selection as GraphQLInlineFragment;
                    var typeCondition      = inlineFragment.TypeCondition;
                    var inlineFragmentType = typeCondition != null
                            ? this.SchemaRepository.GetSchemaOutputTypeByName(typeCondition.Name.Value)
                            : parentType;

                    this.GetFieldsAndFragmentNames(
                        inlineFragment.SelectionSet,
                        nodeDefinitions,
                        fragmentNames,
                        inlineFragmentType,
                        typeCondition?.Name?.Value);
                    break;
                }
            }
        }
コード例 #2
0
        private string ComposeBadValueForDefaultArgMessage(string varName, GraphQLBaseType type, string value, string[] verboseErrors = null)
        {
            var message = verboseErrors.Length > 0 ? "\n" + string.Join("\n", verboseErrors) : string.Empty;

            return($"Variable \"${varName}\" of type \"{type}\" has invalid " +
                   $"default value {value}.{message}");
        }
コード例 #3
0
        internal IEnumerable <GraphQLException> IsValid(GraphQLBaseType type, GraphQLValue astValue)
        {
            if (astValue is GraphQLVariable)
            {
                return new GraphQLException[] { }
            }
            ;

            if (astValue is GraphQLNullValue || astValue == null)
            {
                return(this.ValidateNullType(type, astValue));
            }

            if (type is GraphQLNonNull)
            {
                return(this.IsValid(((GraphQLNonNull)type).UnderlyingNullableType, astValue));
            }

            if (type is GraphQLList)
            {
                return(this.ValidateListType(type, astValue));
            }

            if (type is GraphQLInputType)
            {
                return(this.ValidateInputType(type, astValue));
            }

            return(new GraphQLException[] { });
        }
コード例 #4
0
        private string PrintType(GraphQLBaseType type)
        {
            if (type is GraphQLEnumType)
            {
                return(PrintEnum((GraphQLEnumType)type));
            }
            if (type is GraphQLScalarType)
            {
                return(PrintScalar((GraphQLScalarType)type));
            }
            if (type is GraphQLObjectType)
            {
                return(this.PrintObject((GraphQLObjectType)type));
            }
            if (type is GraphQLInterfaceType)
            {
                return(this.PrintInterface((GraphQLInterfaceType)type));
            }
            if (type is GraphQLUnionType)
            {
                return(this.PrintUnion((GraphQLUnionType)type));
            }
            if (type is GraphQLInputObjectType)
            {
                return(this.PrintInputObject((GraphQLInputObjectType)type));
            }

            throw new GraphQLException($"Type {type.Name} can't be printed.");
        }
コード例 #5
0
        public object TranslatePerDefinition(object inputObject, GraphQLBaseType typeDefinition)
        {
            if (typeDefinition is GraphQLNonNull)
            {
                return(this.TranslatePerDefinition(inputObject, ((GraphQLNonNull)typeDefinition).UnderlyingNullableType));
            }

            if (typeDefinition is GraphQLInputObjectType)
            {
                return(this.CreateObjectFromDynamic((GraphQLInputObjectType)typeDefinition, (ExpandoObject)inputObject));
            }

            if (typeDefinition is GraphQLList)
            {
                if (inputObject == null)
                {
                    return(null);
                }

                if (ReflectionUtilities.IsCollection(inputObject.GetType()))
                {
                    return(ReflectionUtilities.ChangeValueType(this.CreateList((IEnumerable)inputObject, (GraphQLList)typeDefinition), this.schemaRepository.GetInputSystemTypeFor(typeDefinition)));
                }

                return(this.CreateSingleValueList(inputObject, (GraphQLList)typeDefinition));
            }

            return(inputObject);
        }
コード例 #6
0
 public static bool IsPossibleType(
     GraphQLBaseType parent, GraphQLBaseType child, ISchemaRepository schemaRepository)
 {
     return(parent
            .Introspect(schemaRepository)
            .Value
            .Interfaces.Any(e => e.Value.Name == child.Name));
 }
コード例 #7
0
 private void AddOutputType(GraphQLBaseType type)
 {
     if (type is ISystemTypeBound)
     {
         this.outputBindings.Add(((ISystemTypeBound)type).SystemType, type);
     }
     else
     {
         this.outputBindings.Add(type.GetType(), type);
     }
 }
コード例 #8
0
        private Type GetNonNullInputSystemTypeFor(GraphQLBaseType type)
        {
            var systemType = this.GetSystemTypeFor(type);

            if (!ReflectionUtilities.IsValueType(systemType))
            {
                return(ReflectionUtilities.CreateNonNullableType(systemType));
            }

            return(systemType);
        }
コード例 #9
0
        private IEnumerable <GraphQLException> ValidateListType(GraphQLBaseType type, GraphQLValue astValue)
        {
            var itemType = ((GraphQLList)type).MemberType;

            if (astValue.Kind == ASTNodeKind.ListValue)
            {
                return(this.ValidateListMembers(itemType, (GraphQLListValue)astValue));
            }

            return(this.IsValid(itemType, astValue));
        }
コード例 #10
0
        public Type GetInputSystemTypeFor(GraphQLBaseType type)
        {
            if (type is GraphQLNonNull)
            {
                return(this.GetNonNullInputSystemTypeFor(((GraphQLNonNull)type).UnderlyingNullableType));
            }

            var inputType = ReflectionUtilities.CreateNullableType(
                this.GetSystemTypeFor(type));

            return(inputType);
        }
コード例 #11
0
        private IEnumerable <string> GetSuggestedFieldNames(IGraphQLSchema schema, GraphQLBaseType type, string fieldName)
        {
            if (type is GraphQLObjectType || type is GraphQLInterfaceType)
            {
                var introspectedType   = type.Introspect(schema.SchemaRepository);
                var possibleFieldNames = introspectedType.Value.Fields.Select(e => e.Value.Name.Value);

                return(StringUtils.SuggestionList(fieldName, possibleFieldNames));
            }

            return(Enumerable.Empty <string>());
        }
コード例 #12
0
        public void AddKnownType(GraphQLBaseType type)
        {
            if (type is GraphQLInputType)
            {
                this.AddInputType((GraphQLInputType)type);
            }

            if (!(type is GraphQLInputType) || type is GraphQLScalarType)
            {
                this.AddOutputType(type);
            }
        }
コード例 #13
0
        private IEnumerable <GraphQLException> ValidateNullType(GraphQLBaseType type, GraphQLValue astValue)
        {
            if (type is GraphQLNonNull)
            {
                return(new GraphQLException[]
                {
                    new GraphQLException($"Expected type \"{type}\", found null.")
                });
            }

            return(new GraphQLException[] { });
        }
コード例 #14
0
        private IEnumerable <GraphQLException> ValidateListMembers(GraphQLBaseType itemType, GraphQLListValue astValue)
        {
            var values = astValue.Values;

            for (int i = 0; i < values.Count(); i++)
            {
                foreach (var error in this.IsValid(itemType, values.ElementAt(i)))
                {
                    yield return(new GraphQLException($"In element #{i}: {error.Message}"));
                }
            }
        }
        private IEnumerable <Conflict> FindConflictsBetweenSubSelectionSets(
            GraphQLBaseType type1,
            GraphQLBaseType type2,
            GraphQLSelectionSet selectionSet1,
            GraphQLSelectionSet selectionSet2,
            bool areMutuallyExclusive)
        {
            var conflicts = new List <Conflict>();

            var fieldMap1      = new Dictionary <string, ICollection <NodeAndDefinitions> >();
            var fragmentNames1 = new List <string>();

            this.GetFieldsAndFragmentNames(
                selectionSet1, fieldMap1, fragmentNames1, type1);

            var fieldMap2      = new Dictionary <string, ICollection <NodeAndDefinitions> >();
            var fragmentNames2 = new List <string>();

            this.GetFieldsAndFragmentNames(
                selectionSet2, fieldMap2, fragmentNames2, type2);

            conflicts.AddRange(this.CollectConflictsBetween(areMutuallyExclusive, fieldMap1, fieldMap2));

            foreach (var frag in fragmentNames2)
            {
                conflicts.AddRange(this.CollectConflictsBetweenFieldsAndFragment(
                                       fieldMap1,
                                       frag,
                                       areMutuallyExclusive));
            }

            foreach (var frag in fragmentNames1)
            {
                conflicts.AddRange(this.CollectConflictsBetweenFieldsAndFragment(
                                       fieldMap2,
                                       frag,
                                       areMutuallyExclusive));
            }

            foreach (var frag1 in fragmentNames1)
            {
                foreach (var frag2 in fragmentNames2)
                {
                    conflicts.AddRange(this.CollectConflictsBetweenFragments(
                                           frag1,
                                           frag2,
                                           areMutuallyExclusive));
                }
            }

            return(conflicts);
        }
コード例 #16
0
        public GraphQLBaseType GetUnderlyingType(GraphQLBaseType type)
        {
            if (type is GraphQLList)
            {
                return(this.GetUnderlyingType(((GraphQLList)type).MemberType));
            }
            if (type is GraphQLNonNull)
            {
                return(this.GetUnderlyingType(((GraphQLNonNull)type).UnderlyingNullableType));
            }

            return(type);
        }
コード例 #17
0
        private Type GetSystemTypeFor(GraphQLBaseType type)
        {
            if (type is GraphQLList)
            {
                return(ReflectionUtilities.CreateListTypeOf(
                           this.GetInputSystemTypeFor(((GraphQLList)type).MemberType)));
            }

            var reflectedType = this.inputBindings
                                .Where(e => e.Value.Name == type.Name)
                                .Select(e => e.Key)
                                .FirstOrDefault();

            return(reflectedType);
        }
        private bool DoTypesConflict(
            GraphQLBaseType type1,
            GraphQLBaseType type2)
        {
            if (type1 is GraphQLList)
            {
                return(type2 is GraphQLList
                    ? this.DoTypesConflict(
                           ((GraphQLList)type1).MemberType,
                           ((GraphQLList)type2).MemberType)
                    : true);
            }

            if (type2 is GraphQLList)
            {
                return(type1 is GraphQLList
                    ? this.DoTypesConflict(
                           ((GraphQLList)type1).MemberType,
                           ((GraphQLList)type2).MemberType)
                    : true);
            }

            if (type1 is GraphQLNonNull)
            {
                return(type2 is GraphQLNonNull
                    ? this.DoTypesConflict(
                           ((GraphQLNonNull)type1).UnderlyingNullableType,
                           ((GraphQLNonNull)type2).UnderlyingNullableType)
                    : true);
            }

            if (type2 is GraphQLNonNull)
            {
                return(type1 is GraphQLNonNull
                    ? this.DoTypesConflict(
                           ((GraphQLNonNull)type1).UnderlyingNullableType,
                           ((GraphQLNonNull)type2).UnderlyingNullableType)
                    : true);
            }

            if (type1.IsLeafType || type2.IsLeafType)
            {
                return(type1.Name != type2.Name);
            }

            return(false);
        }
コード例 #19
0
        private void ValidateInlineFragmentTypes(GraphQLInlineFragment node, GraphQLBaseType fragmentType, GraphQLBaseType parentType)
        {
            if (parentType is GraphQLList)
            {
                parentType = ((GraphQLList)parentType).MemberType;

                this.ValidateInlineFragmentTypes(node, fragmentType, parentType);
            }
            else if (fragmentType != null &&
                     parentType != null &&
                     !this.DoTypesOverlap(fragmentType, parentType))
            {
                this.Errors.Add(
                    new GraphQLException(
                        this.GetIncompatibleTypeInAnonymousFragmentMessage(fragmentType, parentType),
                        new[] { node }));
            }
        }
コード例 #20
0
        private IEnumerable <GraphQLException> ValidateInputType(GraphQLBaseType type, GraphQLValue astValue)
        {
            var result = ((GraphQLInputType)type).GetFromAst(astValue, this.schemaRepository);

            if (type is GraphQLInputObjectType)
            {
                return(this.ValidateObjectFields((GraphQLInputObjectType)type, (GraphQLObjectValue)astValue));
            }

            if (!result.IsValid)
            {
                return(new GraphQLException[]
                {
                    new GraphQLException($"Expected type \"{type}\", found {astValue}.")
                });
            }

            return(new GraphQLException[] { });
        }
コード例 #21
0
        private bool DoTypesOverlap(GraphQLBaseType fragmentType, GraphQLBaseType parentType)
        {
            if (fragmentType == parentType)
            {
                return(true);
            }

            var parentImplementsFragmentType = fragmentType
                                               .Introspect(this.SchemaRepository).Value
                                               .Interfaces?.Any(e => e.Value.Name == parentType.Name) ?? false;

            var fragmentTypeImplementsParent = parentType
                                               .Introspect(this.SchemaRepository).Value
                                               .Interfaces?.Any(e => e.Value.Name == fragmentType.Name) ?? false;

            var fragmentTypeIsWithinPossibleTypes = parentType
                                                    .Introspect(this.SchemaRepository).Value
                                                    .PossibleTypes?.Any(e => e.Value.Name == fragmentType.Name) ?? false;

            return(parentImplementsFragmentType || fragmentTypeImplementsParent || fragmentTypeIsWithinPossibleTypes);
        }
コード例 #22
0
        private IEnumerable <string> GetSuggestedTypeNames(IGraphQLSchema schema, GraphQLBaseType type, string fieldName)
        {
            var introspectedType     = type.Introspect(schema.SchemaRepository);
            var suggestedObjectTypes = new List <string>();
            var interfaceUsageCount  = new Dictionary <string, int>();

            if (introspectedType.Value.PossibleTypes == null)
            {
                return(suggestedObjectTypes);
            }

            foreach (var possibleType in introspectedType.Value.PossibleTypes)
            {
                if (possibleType.Value.Fields.Any(e => e.Value.Name == fieldName))
                {
                    suggestedObjectTypes.Add(possibleType.Value.Name);

                    foreach (var possibleInterface in possibleType.Value.Interfaces)
                    {
                        if (possibleInterface.Value.Fields.Any(e => e.Value.Name == fieldName))
                        {
                            if (!interfaceUsageCount.ContainsKey(possibleInterface.Value.Name))
                            {
                                interfaceUsageCount.Add(possibleInterface.Value.Name, 1);
                            }
                            else
                            {
                                interfaceUsageCount[possibleInterface.Value.Name]++;
                            }
                        }
                    }
                }
            }

            var suggestedInterfaceTypes = interfaceUsageCount.OrderByDescending(e => e.Value).Select(e => e.Key);

            return(suggestedInterfaceTypes.Concat(suggestedObjectTypes));
        }
コード例 #23
0
        protected GraphQLFieldInfo GetField(GraphQLBaseType type, string fieldName)
        {
            if (this.IsQueryRootType(type))
            {
                if (fieldName == "__schema")
                {
                    return(this.GetIntrospectedSchemaField());
                }

                if (fieldName == "__type")
                {
                    return(this.GetIntrospectedTypeField());
                }
            }

            if (type is GraphQLNonNull)
            {
                return(this.GetField(((GraphQLNonNull)type).UnderlyingNullableType, fieldName));
            }

            if (type is GraphQLInputObjectType)
            {
                return(((GraphQLInputObjectType)type).GetFieldInfo(fieldName));
            }

            if (type is GraphQLComplexType)
            {
                return(((GraphQLComplexType)type).GetFieldInfo(fieldName));
            }

            if (type is GraphQLList)
            {
                return(this.GetField(((GraphQLList)type).MemberType, fieldName));
            }

            return(null);
        }
コード例 #24
0
 private string GetIncompatibleTypeInFragmentMessage(
     GraphQLBaseType fragmentType, GraphQLBaseType parentType, string fragmentName)
 {
     return($"Fragment {fragmentName} cannot be spread here as objects of " +
            $"type \"{parentType}\" can never be of type \"{fragmentType}\".");
 }
コード例 #25
0
 private string ComposeDefaultForNonNullArgMessage(string varName, GraphQLBaseType type, GraphQLBaseType guessType)
 {
     return($"Variable \"${varName}\" of type \"{type}\" is required and " +
            "will not use the default value. " +
            $"Perhaps you meant to use type \"{guessType}\".");
 }
コード例 #26
0
 private string RequiredSubselectionMessage(string fieldName, GraphQLBaseType type)
 {
     return($"Field \"{fieldName}\" of type \"{type}\" must have a " +
            $"selection of subfields. Did you mean \"{fieldName} " + "{ ... }\"?");
 }
コード例 #27
0
 private string NoScalarSubselection(string fieldName, GraphQLBaseType type)
 {
     return($"Field \"{fieldName}\" must not have a selection since " +
            $"type \"{type}\" has no subfields.");
 }
コード例 #28
0
 private GraphQLBaseType GetEffectiveType(GraphQLBaseType type, GraphQLVariableDefinition definition)
 {
     return(definition.DefaultValue == null || type is GraphQLNonNull
         ? type
         : new GraphQLNonNull(type));
 }
コード例 #29
0
 private static string PrintDescription(GraphQLBaseType type, string indentation = "", bool firstInBlock = true)
 {
     return(PrintDescription(type.Description, indentation, firstInBlock));
 }
コード例 #30
0
        private string ComposeUnknownArgumentMessage(string argName, string fieldName, GraphQLBaseType type, IEnumerable <string> suggestedArgs)
        {
            var message = $"Unknown argument \"{argName}\" on field \"{fieldName}\" of type \"{type}\".";

            if (suggestedArgs.Any())
            {
                message += $" Did you mean {StringUtils.QuotedOrList(suggestedArgs)}?";
            }

            return(message);
        }