コード例 #1
0
        public static TypeReferenceBuilder ToTypeReference(
            this ITypeDescriptor typeReferenceDescriptor,
            TypeReferenceBuilder?builder = null)
        {
            TypeReferenceBuilder actualBuilder = builder ?? TypeReferenceBuilder.New();

            if (typeReferenceDescriptor is NonNullTypeDescriptor n)
            {
                typeReferenceDescriptor = n.InnerType;
            }
            else
            {
                actualBuilder.SetIsNullable(true);
            }

            return(typeReferenceDescriptor switch
            {
                ListTypeDescriptor list =>
                ToTypeReference(list.InnerType, actualBuilder.SetListType()),

                EnumTypeDescriptor @enum =>
                actualBuilder.SetName(@enum.RuntimeType.ToString()),

                ILeafTypeDescriptor leaf =>
                actualBuilder.SetName(leaf.RuntimeType.ToString()),

                INamedTypeDescriptor named =>
                actualBuilder.SetName(named.RuntimeType.ToString()),

                _ => throw new ArgumentOutOfRangeException(nameof(typeReferenceDescriptor))
            });
コード例 #2
0
        public static TypeReferenceBuilder ToEntityIdBuilder(
            this ITypeDescriptor typeDescriptor,
            TypeReferenceBuilder?builder = null,
            bool isNonNull = false)
        {
            TypeReferenceBuilder actualBuilder = builder ?? TypeReferenceBuilder.New();

            switch (typeDescriptor)
            {
            case ListTypeDescriptor listTypeDescriptor:
                actualBuilder.SetIsNullable(!isNonNull);
                actualBuilder.SetListType();
                ToEntityIdBuilder(
                    listTypeDescriptor.InnerType,
                    actualBuilder);
                break;

            case NamedTypeDescriptor namedTypeDescriptor:
                actualBuilder.SetIsNullable(!isNonNull);
                if (namedTypeDescriptor.IsLeafType() && !namedTypeDescriptor.IsEnum)
                {
                    actualBuilder.SetName(
                        $"{namedTypeDescriptor.Namespace}.{namedTypeDescriptor.Name}");
                }
                else if (namedTypeDescriptor.IsDataType())
                {
                    actualBuilder.SetName(
                        namedTypeDescriptor.Kind == TypeKind.ComplexDataType
                                ? $"global::{namedTypeDescriptor.Namespace}.State.I" +
                        DataTypeNameFromTypeName(
                            namedTypeDescriptor.ComplexDataTypeParent !)
                                : $"global::{namedTypeDescriptor.Namespace}.State." +
                        DataTypeNameFromTypeName(
                            namedTypeDescriptor.GraphQLTypeName !));
                }
                else if (namedTypeDescriptor.IsEntityType())
                {
                    actualBuilder.SetName(TypeNames.EntityId);
                }
                else
                {
                    actualBuilder.SetName(typeDescriptor.Name);
                }
                break;

            case NonNullTypeDescriptor nonNullTypeDescriptor:
                ToEntityIdBuilder(
                    nonNullTypeDescriptor.InnerType,
                    actualBuilder,
                    true);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(typeDescriptor));
            }

            return(actualBuilder);
        }
コード例 #3
0
        private void AddBuildMethod(
            InterfaceTypeDescriptor resultNamedType,
            ClassBuilder classBuilder)
        {
            var responseParameterName = "response";

            var buildMethod = MethodBuilder
                              .New()
                              .SetAccessModifier(AccessModifier.Public)
                              .SetName("Build")
                              .SetReturnType(
                TypeReferenceBuilder.New()
                .SetName(TypeNames.IOperationResult)
                .AddGeneric(resultNamedType.RuntimeType.Name))
                              .AddParameter(
                ParameterBuilder.New()
                .SetType(
                    TypeReferenceBuilder.New()
                    .SetName(TypeNames.Response)
                    .AddGeneric(TypeNames.JsonDocument)
                    .SetName(TypeNames.Response))
                .SetName(responseParameterName));

            var concreteResultType =
                CreateResultInfoName(resultNamedType.ImplementedBy.First().RuntimeType.Name);

            buildMethod.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide(
                    $"({resultNamedType.RuntimeType.Name} Result, {concreteResultType} " +
                    "Info)? data")
                .SetRighthandSide("null"));

            buildMethod.AddEmptyLine();
            buildMethod.AddCode(
                IfBuilder.New()
                .SetCondition(
                    ConditionBuilder.New()
                    .Set("response.Body is not null")
                    .And("response.Body.RootElement.TryGetProperty(\"data\"," +
                         $" out {TypeNames.JsonElement} obj)"))
                .AddCode("data = BuildData(obj);"));

            buildMethod.AddEmptyLine();
            buildMethod.AddCode(
                MethodCallBuilder.New()
                .SetPrefix("return new ")
                .SetMethodName(
                    TypeNames.OperationResult.WithGeneric(resultNamedType.RuntimeType.Name))
                .AddArgument("data?.Result")
                .AddArgument("data?.Info")
                .AddArgument(_resultDataFactoryFieldName)
                .AddArgument("null"));

            classBuilder.AddMethod(buildMethod);
        }
コード例 #4
0
        protected override void Generate(
            CodeWriter writer,
            OperationDescriptor operationDescriptor,
            out string fileName)
        {
            var(classBuilder, constructorBuilder) = CreateClassBuilder();

            fileName = operationDescriptor.Name;
            classBuilder.SetName(fileName);
            constructorBuilder.SetTypeName(fileName);

            var resultTypeReference =
                (INamedTypeDescriptor)operationDescriptor.ResultTypeReference.NamedType();

            AddConstructorAssignedField(
                TypeReferenceBuilder.New()
                .SetName(TypeNames.IOperationExecutor)
                .AddGeneric(resultTypeReference.RuntimeType.Name),
                OperationExecutorFieldName,
                classBuilder,
                constructorBuilder);

            var neededSerializers = operationDescriptor.Arguments
                                    .ToLookup(x => x.Type.Name)
                                    .Select(x => x.First())
                                    .ToDictionary(x => x.Type.Name);

            if (neededSerializers.Any())
            {
                constructorBuilder
                .AddParameter(
                    "serializerResolver",
                    x => x.SetType(TypeNames.ISerializerResolver));

                foreach (var property in neededSerializers.Values)
                {
                    if (property.Type.GetName().Value is { } name)
                    {
                        MethodCallBuilder call = MethodCallBuilder.New()
                                                 .SetMethodName("serializerResolver." +
                                                                nameof(ISerializerResolver.GetInputValueFormatter))
                                                 .AddArgument(name.AsStringToken() ?? "")
                                                 .SetPrefix($"{GetFieldName(name)}Formatter = ");

                        constructorBuilder.AddCode(call);
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  $"Serialized for property {operationDescriptor.Name}.{property.Name} " +
                                  $"could not be created. GraphQLTypeName was empty");
                    }
                }
コード例 #5
0
 protected void AddConstructorAssignedField(
     string typename,
     string fieldName,
     ClassBuilder classBuilder,
     ConstructorBuilder constructorBuilder,
     bool skipNullCheck = false)
 {
     AddConstructorAssignedField(
         TypeReferenceBuilder.New().SetName(typename),
         fieldName,
         classBuilder,
         constructorBuilder,
         skipNullCheck);
 }
コード例 #6
0
        public static TypeReferenceBuilder ToBuilder(
            this ITypeDescriptor typeReferenceDescriptor,
            string?nameOverride          = null,
            TypeReferenceBuilder?builder = null,
            bool isNonNull = false)
        {
            var actualBuilder = builder ?? TypeReferenceBuilder.New();

            switch (typeReferenceDescriptor)
            {
            case ListTypeDescriptor listTypeDescriptor:
                actualBuilder.SetIsNullable(!isNonNull);
                actualBuilder.SetListType();
                ToBuilder(
                    listTypeDescriptor.InnerType,
                    nameOverride,
                    actualBuilder);
                break;

            case NamedTypeDescriptor namedTypeDescriptor:
                actualBuilder.SetIsNullable(!isNonNull);
                if (namedTypeDescriptor.IsLeafType() && !namedTypeDescriptor.IsEnum)
                {
                    actualBuilder.SetName(
                        $"{namedTypeDescriptor.Namespace}." +
                        (nameOverride ?? namedTypeDescriptor.Name));
                }
                else
                {
                    actualBuilder.SetName(nameOverride ?? namedTypeDescriptor.Name);
                }
                break;

            case NonNullTypeDescriptor nonNullTypeDescriptor:
                ToBuilder(
                    nonNullTypeDescriptor.InnerType,
                    nameOverride,
                    actualBuilder,
                    true);
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(typeReferenceDescriptor));
            }

            return(actualBuilder);
        }
コード例 #7
0
        private void AddBuildMethod(
            InterfaceTypeDescriptor resultNamedType,
            ClassBuilder classBuilder)
        {
            var buildMethod = classBuilder
                              .AddMethod()
                              .SetAccessModifier(AccessModifier.Public)
                              .SetName("Build")
                              .SetReturnType(
                TypeReferenceBuilder
                .New()
                .SetName(TypeNames.IOperationResult)
                .AddGeneric(resultNamedType.RuntimeType.Name));

            buildMethod
            .AddParameter(_response)
            .SetType(TypeNames.Response.WithGeneric(TypeNames.JsonDocument));

            var concreteResultType =
                CreateResultInfoName(resultNamedType.ImplementedBy.First().RuntimeType.Name);

            buildMethod.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide(
                    $"({resultNamedType.RuntimeType.Name} Result, {concreteResultType} " +
                    "Info)? data")
                .SetRighthandSide("null"));
            buildMethod.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide(
                    TypeNames.IReadOnlyList
                    .WithGeneric(TypeNames.IClientError)
                    .MakeNullable() + " errors")
                .SetRighthandSide("null"));

            buildMethod.AddEmptyLine();
            buildMethod.AddCode(
                TryCatchBuilder
                .New()
                .AddTryCode(
                    IfBuilder
                    .New()
                    .SetCondition(
                        ConditionBuilder
                        .New()
                        .Set("response.Body != null"))
                    .AddCode(
                        IfBuilder
                        .New()
                        .SetCondition(
                            ConditionBuilder
                            .New()
                            .Set("response.Body.RootElement.TryGetProperty(" +
                                 $"\"data\", out {TypeNames.JsonElement} " +
                                 "dataElement) && dataElement.ValueKind == " +
                                 $"{TypeNames.JsonValueKind}.Object"))
                        .AddCode("data = BuildData(dataElement);"))
                    .AddCode(
                        IfBuilder
                        .New()
                        .SetCondition(
                            ConditionBuilder
                            .New()
                            .Set(
                                "response.Body.RootElement.TryGetProperty(" +
                                $"\"errors\", out {TypeNames.JsonElement} " +
                                "errorsElement)"))
                        .AddCode($"errors = {TypeNames.ParseError}(errorsElement);")))
                .AddCatchBlock(
                    CatchBlockBuilder
                    .New()
                    .SetExceptionVariable("ex")
                    .AddCode(
                        AssignmentBuilder.New()
                        .SetLefthandSide("errors")
                        .SetRighthandSide(
                            ArrayBuilder.New()
                            .SetDetermineStatement(false)
                            .SetType(TypeNames.IClientError)
                            .AddAssigment(
                                MethodCallBuilder
                                .Inline()
                                .SetNew()
                                .SetMethodName(TypeNames.ClientError)
                                .AddArgument("ex.Message")
                                .AddArgument("exception: ex"))))));

            buildMethod.AddEmptyLine();
            buildMethod.AddCode(
                MethodCallBuilder
                .New()
                .SetReturn()
                .SetNew()
                .SetMethodName(TypeNames.OperationResult)
                .AddGeneric(resultNamedType.RuntimeType.Name)
                .AddArgument("data?.Result")
                .AddArgument("data?.Info")
                .AddArgument(_resultDataFactory)
                .AddArgument("errors"));
        }
コード例 #8
0
        private void AddBuildMethod(
            InterfaceTypeDescriptor resultNamedType,
            ClassBuilder classBuilder)
        {
            var buildMethod = classBuilder
                              .AddMethod()
                              .SetAccessModifier(AccessModifier.Public)
                              .SetName("Build")
                              .SetReturnType(
                TypeReferenceBuilder
                .New()
                .SetName(TypeNames.IOperationResult)
                .AddGeneric(resultNamedType.RuntimeType.Name));

            buildMethod
            .AddParameter(_response)
            .SetType(TypeNames.Response.WithGeneric(TypeNames.JsonDocument));

            var concreteResultType =
                CreateResultInfoName(resultNamedType.ImplementedBy.First().RuntimeType.Name);

            // (IGetFooResult Result, GetFooResultInfo Info)? data = null;
            buildMethod.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide(
                    $"({resultNamedType.RuntimeType.Name} Result, {concreteResultType} " +
                    "Info)? data")
                .SetRighthandSide("null"));

            // IReadOnlyList<IClientError>? errors = null;
            buildMethod.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide(
                    TypeNames.IReadOnlyList
                    .WithGeneric(TypeNames.IClientError)
                    .MakeNullable() + " errors")
                .SetRighthandSide("null"));

            buildMethod.AddEmptyLine();



            buildMethod.AddEmptyLine();
            buildMethod.AddCode(
                IfBuilder.New()
                .SetCondition("response.Exception is null")
                .AddCode(CreateBuildDataSerialization())
                .AddElse(CreateDataError("response.Exception"))
                );

            buildMethod.AddEmptyLine();
            buildMethod.AddCode(
                MethodCallBuilder
                .New()
                .SetReturn()
                .SetNew()
                .SetMethodName(TypeNames.OperationResult)
                .AddGeneric(resultNamedType.RuntimeType.Name)
                .AddArgument("data?.Result")
                .AddArgument("data?.Info")
                .AddArgument(_resultDataFactory)
                .AddArgument("errors"));
        }
コード例 #9
0
        protected override void Generate(
            CodeWriter writer,
            ResultBuilderDescriptor resultBuilderDescriptor, out string fileName)
        {
            var processed            = new HashSet <string>();
            var resultTypeDescriptor = resultBuilderDescriptor.ResultNamedType;

            var(classBuilder, constructorBuilder) = CreateClassBuilder();

            fileName = resultBuilderDescriptor.Name;
            classBuilder.SetName(fileName);

            constructorBuilder.SetTypeName(fileName);

            classBuilder.AddImplements(
                $"{TypeNames.IOperationResultBuilder}<{TypeNames.JsonDocument}," +
                $" {resultTypeDescriptor.Name}>");

            AddConstructorAssignedField(
                TypeNames.IEntityStore,
                _entityStoreFieldName,
                classBuilder,
                constructorBuilder);

            AddConstructorAssignedField(
                TypeReferenceBuilder.New()
                .SetName(TypeNames.Func)
                .AddGeneric(TypeNames.JsonElement)
                .AddGeneric(TypeNames.EntityId),
                _extractIdFieldName,
                classBuilder,
                constructorBuilder);

            AddConstructorAssignedField(
                TypeReferenceBuilder.New()
                .SetName(TypeNames.IOperationResultDataFactory)
                .AddGeneric(resultTypeDescriptor.Name),
                _resultDataFactoryFieldName,
                classBuilder,
                constructorBuilder);

            constructorBuilder.AddParameter(
                ParameterBuilder.New()
                .SetName(_serializerResolverParamName)
                .SetType(TypeNames.ISerializerResolver));

            IEnumerable <ValueParserDescriptor> neededSerializers = resultBuilderDescriptor
                                                                    .ValueParsers
                                                                    .ToLookup(x => x.RuntimeType)
                                                                    .Select(x => x.First());

            foreach (ValueParserDescriptor valueParser in neededSerializers)
            {
                var parserFieldName =
                    $"_{valueParser.RuntimeType.Split('.').Last().WithLowerFirstChar()}Parser";
                classBuilder.AddField(
                    FieldBuilder.New().SetName(parserFieldName).SetType(
                        TypeReferenceBuilder.New()
                        .SetName(TypeNames.ILeafValueParser)
                        .AddGeneric(valueParser.SerializedType)
                        .AddGeneric(valueParser.RuntimeType)));

                constructorBuilder.AddCode(
                    AssignmentBuilder.New()
                    .AssertNonNull(parserFieldName)
                    .SetLefthandSide(parserFieldName)
                    .SetRighthandSide(
                        MethodCallBuilder.New()
                        .SetPrefix(_serializerResolverParamName + ".")
                        .SetDetermineStatement(false)
                        .SetMethodName(
                            $"GetLeafValueParser<{valueParser.SerializedType}, " +
                            $"{valueParser.RuntimeType}>")
                        .AddArgument($"\"{valueParser.GraphQLTypeName}\"")));
            }

            AddBuildMethod(
                resultTypeDescriptor,
                classBuilder);

            AddBuildDataMethod(
                resultTypeDescriptor,
                classBuilder);

            AddRequiredDeserializeMethods(
                resultBuilderDescriptor.ResultNamedType,
                classBuilder,
                processed);

            CodeFileBuilder.New()
            .SetNamespace(resultBuilderDescriptor.ResultNamedType.Namespace)
            .AddType(classBuilder)
            .Build(writer);
        }
コード例 #10
0
        protected override void Generate(
            CodeWriter writer,
            ResultBuilderDescriptor resultBuilderDescriptor,
            out string fileName)
        {
            var processed            = new HashSet <string>();
            var resultTypeDescriptor =
                resultBuilderDescriptor.ResultNamedType as InterfaceTypeDescriptor
                ?? throw new InvalidOperationException(
                          "A result type can only be generated for complex types");

            var(classBuilder, constructorBuilder) = CreateClassBuilder();

            fileName = resultBuilderDescriptor.RuntimeType.Name;
            classBuilder.SetName(fileName);

            constructorBuilder.SetTypeName(fileName);

            classBuilder.AddImplements(
                $"{TypeNames.IOperationResultBuilder}<{TypeNames.JsonDocument}," +
                $" {resultTypeDescriptor.RuntimeType.Name}>");

            AddConstructorAssignedField(
                TypeNames.IEntityStore,
                _entityStoreFieldName,
                classBuilder,
                constructorBuilder);

            AddConstructorAssignedField(
                TypeReferenceBuilder.New()
                .SetName(TypeNames.Func)
                .AddGeneric(TypeNames.JsonElement)
                .AddGeneric(TypeNames.EntityId),
                _extractIdFieldName,
                classBuilder,
                constructorBuilder);

            AddConstructorAssignedField(
                TypeReferenceBuilder.New()
                .SetName(TypeNames.IOperationResultDataFactory)
                .AddGeneric(resultTypeDescriptor.RuntimeType.Name),
                _resultDataFactoryFieldName,
                classBuilder,
                constructorBuilder);

            constructorBuilder.AddParameter(
                ParameterBuilder.New()
                .SetName(_serializerResolverParamName)
                .SetType(TypeNames.ISerializerResolver));

            IEnumerable <ValueParserDescriptor> valueParsers = resultBuilderDescriptor
                                                               .ValueParsers
                                                               .GroupBy(t => t.Name)
                                                               .Select(t => t.First());

            foreach (ValueParserDescriptor valueParser in valueParsers)
            {
                var parserFieldName = $"{GetFieldName(valueParser.Name)}Parser";

                classBuilder.AddField(
                    FieldBuilder.New()
                    .SetReadOnly()
                    .SetName(parserFieldName)
                    .SetType(
                        TypeReferenceBuilder.New()
                        .SetName(TypeNames.ILeafValueParser)
                        .AddGeneric(valueParser.SerializedType.ToString())
                        .AddGeneric(valueParser.RuntimeType.ToString())));

                constructorBuilder.AddCode(
                    AssignmentBuilder.New()
                    .SetAssertNonNull()
                    .SetAssertException(
                        TypeNames.ArgumentException +
                        $"(\"No serializer for type `{valueParser.Name}` found.\")")
                    .SetLefthandSide(parserFieldName)
                    .SetRighthandSide(
                        MethodCallBuilder.New()
                        .SetPrefix(_serializerResolverParamName + ".")
                        .SetDetermineStatement(false)
                        .SetMethodName(
                            $"GetLeafValueParser<{valueParser.SerializedType}, " +
                            $"{valueParser.RuntimeType}>")
                        .AddArgument($"\"{valueParser.Name}\"")));
            }

            AddBuildMethod(
                resultTypeDescriptor,
                classBuilder);

            AddBuildDataMethod(
                resultTypeDescriptor,
                classBuilder);

            AddRequiredDeserializeMethods(
                resultBuilderDescriptor.ResultNamedType,
                classBuilder,
                processed);

            CodeFileBuilder.New()
            .SetNamespace(
                resultBuilderDescriptor.ResultNamedType.RuntimeType.NamespaceWithoutGlobal)
            .AddType(classBuilder)
            .Build(writer);
        }