<commit_before>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using GraphQL.Builders;
using GraphQL.Relay.Types;
using GraphQL.Types;
using GraphQL.Types.Relay;
using Snowflake.Framework.Remoting.GraphQl.Attributes;

namespace Snowflake.Framework.Remoting.GraphQl.Query
{
    public abstract partial class QueryBuilder
    {
        private static MethodInfo ConnectionMaker { get; }
        static QueryBuilder()
        {
            MethodInfo GetMethod<T>(Expression<Func<ResolveConnectionContext<T>, IEnumerable<T>, T>> expression)
            {
                MethodCallExpression methodCall = (MethodCallExpression)expression.Body;
                return methodCall.Method;
            }

            QueryBuilder.ConnectionMaker = GetMethod<object>((context, items) =>
                                               ConnectionUtils.ToConnection(items, context)).GetGenericMethodDefinition();
        }

        private IEnumerable<(MethodInfo fieldMethod, TAttribute attr, IEnumerable<ParameterAttribute> paramAttr)>
            EnumerateQueries<TAttribute>()
            where TAttribute : Attribute
        {
            var endpoints = from m in this.GetType().GetRuntimeMethods()
                             let queryAttr = m.GetCustomAttribute<TAttribute>()
                             where queryAttr != null
                             let endpointParamsAttrs = m.GetCustomAttributes<ParameterAttribute>()
                             select (methodInfo: m, queryAttr: queryAttr, paramAttrs: endpointParamsAttrs);
            foreach (var endpoint in endpoints)
            {
                this.VerifyParameters(endpoint.methodInfo, endpoint.paramAttrs);
            }

            return endpoints;
        }

        private IEnumerable<(MethodInfo fieldMethod, FieldAttribute fieldAttr, IEnumerable<ParameterAttribute> paramAttr)>
            EnumerateFieldQueries() => this.EnumerateQueries<FieldAttribute>();

        private IEnumerable<(MethodInfo fieldMethod, ConnectionAttribute connectionAttr,
                    IEnumerable<ParameterAttribute> paramAttr)> EnumerateConnectionQueries()
            => this.EnumerateQueries<ConnectionAttribute>();

        private IEnumerable<(MethodInfo fieldMethod, MutationAttribute fieldAttr,
                   IEnumerable<ParameterAttribute> paramAttr)> EnumerateMutationQueries()
           => this.EnumerateQueries<MutationAttribute>();

        private FieldQuery MakeFieldQuery(MethodInfo fieldMethod, FieldAttribute fieldAttr, IEnumerable<ParameterAttribute> paramAttr)
        {
            var invoker = this.CreateInvoker(fieldMethod);
            var resolver = this.CreateResolver(invoker, fieldMethod);
            var methodParams = fieldMethod.GetParameters();
            IList<QueryArgument> arguments = (from param in paramAttr
                                              select new QueryArgument(param.GraphQlType)
                                              {
                                                  Name = param.Key,
                                                  Description = param.Description,
                                                  DefaultValue = methodParams.FirstOrDefault(p => p.Name == param.Key)?.DefaultValue,
                                              }).ToList();
            return new FieldQuery()
            {
                Description = fieldAttr.Description,
                Name = fieldAttr.FieldName,
                GraphType = fieldAttr.GraphType,
                Arguments = arguments.Count != 0 ? new QueryArguments(arguments) : null,
                Resolver = resolver,
            };
        }

        private FieldQuery MakeMutationQuery(MethodInfo fieldMethod, MutationAttribute fieldAttr, IEnumerable<ParameterAttribute> paramAttr)
        {
            var invoker = this.CreateInvoker(fieldMethod);
            var resolver = this.CreateResolver(invoker, fieldMethod);
            var methodParams = fieldMethod.GetParameters();
            IList<QueryArgument> arguments = (from param in paramAttr
                                              select new QueryArgument(param.GraphQlType)
                                              {
                                                  Name = param.Key,
                                                  Description = param.Description,
                                                  DefaultValue = methodParams.FirstOrDefault(p => p.Name == param.Key)?.DefaultValue,
                                              }).ToList();
            return new FieldQuery()
            {
                Description = fieldAttr.Description,
                Name = fieldAttr.FieldName,
                GraphType = fieldAttr.GraphType,
                Arguments = arguments.Count != 0 ? new QueryArguments(arguments) : null,
                Resolver = resolver,
            };
        }

        private ConnectionQuery MakeConnectionQuery(MethodInfo fieldMethod, ConnectionAttribute
            fieldAttr, IEnumerable<ParameterAttribute> paramAttr)
        {
            var invoker = this.CreateInvoker(fieldMethod);
            var resolver = this.CreateResolver(invoker, fieldMethod);
            var methodParams = fieldMethod.GetParameters();
            IList<QueryArgument> arguments = (from param in paramAttr
                                                    select new QueryArgument(param.GraphQlType)
                                                    {
                                                        Name = param.Key,
                                                        Description = param.Description,
                                                        DefaultValue = methodParams.FirstOrDefault(p => p.Name == param.Key)?.DefaultValue,
                                                    }).ToList();
            if (!fieldMethod.ReturnType.GetInterfaces().Contains(typeof(IEnumerable)) ||
                !fieldMethod.ReturnType.IsConstructedGenericType)
            {
                throw new ArgumentOutOfRangeException("Connections must be of generic type IEnumerable!");<commit_msg>QueryBuilder: Fix errors in introspection query (#282)<commit_after>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using GraphQL.Builders;
using GraphQL.Relay.Types;
using GraphQL.Types;
using GraphQL.Types.Relay;
using Snowflake.Framework.Remoting.GraphQl.Attributes;

namespace Snowflake.Framework.Remoting.GraphQl.Query
{
    public abstract partial class QueryBuilder
    {
        private static MethodInfo ConnectionMaker { get; }
        static QueryBuilder()
        {
            MethodInfo GetMethod<T>(Expression<Func<ResolveConnectionContext<T>, IEnumerable<T>, T>> expression)
            {
                MethodCallExpression methodCall = (MethodCallExpression)expression.Body;
                return methodCall.Method;
            }

            QueryBuilder.ConnectionMaker = GetMethod<object>((context, items) =>
                                               ConnectionUtils.ToConnection(items, context)).GetGenericMethodDefinition();
        }

        private IEnumerable<(MethodInfo fieldMethod, TAttribute attr, IEnumerable<ParameterAttribute> paramAttr)>
            EnumerateQueries<TAttribute>()
            where TAttribute : Attribute
        {
            var endpoints = from m in this.GetType().GetRuntimeMethods()
                             let queryAttr = m.GetCustomAttribute<TAttribute>()
                             where queryAttr != null
                             let endpointParamsAttrs = m.GetCustomAttributes<ParameterAttribute>()
                             select (methodInfo: m, queryAttr: queryAttr, paramAttrs: endpointParamsAttrs);
            foreach (var endpoint in endpoints)
            {
                this.VerifyParameters(endpoint.methodInfo, endpoint.paramAttrs);
            }

            return endpoints;
        }

        private IEnumerable<(MethodInfo fieldMethod, FieldAttribute fieldAttr, IEnumerable<ParameterAttribute> paramAttr)>
            EnumerateFieldQueries() => this.EnumerateQueries<FieldAttribute>();

        private IEnumerable<(MethodInfo fieldMethod, ConnectionAttribute connectionAttr,
                    IEnumerable<ParameterAttribute> paramAttr)> EnumerateConnectionQueries()
            => this.EnumerateQueries<ConnectionAttribute>();

        private IEnumerable<(MethodInfo fieldMethod, MutationAttribute fieldAttr,
                   IEnumerable<ParameterAttribute> paramAttr)> EnumerateMutationQueries()
           => this.EnumerateQueries<MutationAttribute>();

        private IList<QueryArgument> GetArguments(ParameterInfo[] methodParams, IEnumerable<ParameterAttribute> paramAttr)
        {
            return (from param in paramAttr
             let parameterValue = methodParams.FirstOrDefault(p => p.Name == param.Key)
             select parameterValue?.HasDefaultValue == true ?
             new QueryArgument(param.GraphQlType)
             {
                 Name = param.Key,
                 Description = param.Description,
                 DefaultValue = parameterValue.DefaultValue,
             } : new QueryArgument(param.GraphQlType)
             {
                 Name = param.Key,
                 Description = param.Description,
             }).ToList();
        }

        private FieldQuery MakeFieldQuery(MethodInfo fieldMethod, FieldAttribute fieldAttr, IEnumerable<ParameterAttribute> paramAttr)
        {
            var invoker = this.CreateInvoker(fieldMethod);
            var resolver = this.CreateResolver(invoker, fieldMethod);
            var methodParams = fieldMethod.GetParameters();
            IList<QueryArgument> arguments = this.GetArguments(methodParams, paramAttr);
            return new FieldQuery()
            {
                Description = fieldAttr.Description,
                Name = fieldAttr.FieldName,
                GraphType = fieldAttr.GraphType,
                Arguments = arguments.Count != 0 ? new QueryArguments(arguments) : null,
                Resolver = resolver,
            };
        }

        private FieldQuery MakeMutationQuery(MethodInfo fieldMethod, MutationAttribute fieldAttr, IEnumerable<ParameterAttribute> paramAttr)
        {
            var invoker = this.CreateInvoker(fieldMethod);
            var resolver = this.CreateResolver(invoker, fieldMethod);
            var methodParams = fieldMethod.GetParameters();
            IList<QueryArgument> arguments = this.GetArguments(methodParams, paramAttr);

            return new FieldQuery()
            {
                Description = fieldAttr.Description,
                Name = fieldAttr.FieldName,
                GraphType = fieldAttr.GraphType,
                Arguments = arguments.Count != 0 ? new QueryArguments(arguments) : null,
                Resolver = resolver,
            };
        }

        private ConnectionQuery MakeConnectionQuery(MethodInfo fieldMethod, ConnectionAttribute
            fieldAttr, IEnumerable<ParameterAttribute> paramAttr)
        {
            var invoker = this.CreateInvoker(fieldMethod);
            var resolver = this.CreateResolver(invoker, fieldMethod);
            var methodParams = fieldMethod.GetParameters();
            IList<QueryArgument> arguments = this.GetArguments(methodParams, paramAttr);

            if (!fieldMethod.ReturnType.GetInterfaces().Contains(typeof(IEnumerable)) ||
                !fieldMethod.ReturnType.IsConstructedGenericType)
            {
                throw new ArgumentOutOfRangeException("Connections must be of generic type IEnumerable!");
{'fraction_non_alphanumeric': 0.07377672610496071, 'fraction_numerical': 0.0005915659596044959, 'mean_word_length': 1.9401242236024845, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1117754', 'n_tokens_mistral': 2537, 'n_tokens_neox': 2467, 'n_words': 549}