Пример #1
0
        private void AddArrayHandler(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            ListTypeDescriptor listTypeDescriptor,
            HashSet <string> processed)
        {
            var listVarName = listTypeDescriptor.Name.WithLowerFirstChar() + "s";

            methodBuilder.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide($"var {listVarName}")
                .SetRighthandSide(
                    CodeBlockBuilder.New()
                    .AddCode("new ")
                    .AddCode(TypeNames.List)
                    .AddCode("<")
                    .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder()
                             .SkipTrailingSpace())
                    .AddCode(">")
                    .AddCode("()")
                    ));
            methodBuilder.AddEmptyLine();

            methodBuilder.AddCode(
                ForEachBuilder.New()
                .SetLoopHeader(
                    $"{TypeNames.JsonElement} child in {_objParamName}.Value.EnumerateArray()")
                .AddCode(
                    MethodCallBuilder.New()
                    .SetPrefix($"{listVarName}.")
                    .SetMethodName("Add")
                    .AddArgument(
                        BuildUpdateMethodCall(listTypeDescriptor.InnerType, "child"))));

            methodBuilder.AddEmptyLine();
            methodBuilder.AddCode($"return {listVarName};");

            AddDeserializeMethod(listTypeDescriptor.InnerType, classBuilder, processed);
        }
Пример #2
0
        private void AddComplexDataHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            if (complexTypeDescriptor.ParentRuntimeType is null)
            {
                throw new InvalidOperationException();
            }

            method.AddParameter(
                ParameterBuilder.New()
                .SetType(complexTypeDescriptor.ParentRuntimeType.ToString())
                .SetName(_dataParameterName));

            if (!isNonNullable)
            {
                method.AddCode(
                    EnsureProperNullability(
                        _dataParameterName,
                        isNonNullable));
            }

            var variableName = "returnValue";

            method.AddCode($"{complexTypeDescriptor.RuntimeType.Name} {variableName} = default!;");
            method.AddEmptyLine();

            GenerateIfForEachImplementedBy(
                method,
                complexTypeDescriptor,
                o => GenerateComplexDataInterfaceIfClause(o, variableName));

            method.AddCode($"return {variableName};");

            AddRequiredMapMethods(
                _dataParameterName,
                complexTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
        private void AddDataHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            method.AddParameter(
                ParameterBuilder.New()
                .SetType(
                    $"global::{namedTypeDescriptor.Namespace}.State." +
                    DataTypeNameFromTypeName(namedTypeDescriptor.GraphQLTypeName))
                .SetName(DataParamName));

            if (!isNonNullable)
            {
                method.AddCode(
                    EnsureProperNullability(
                        DataParamName,
                        isNonNullable));
            }

            var variableName = "returnValue";

            method.AddCode($"{namedTypeDescriptor.Name} {variableName} = default!;");
            method.AddEmptyLine();

            if (namedTypeDescriptor.ImplementedBy.Any())
            {
                var ifChain = InterfaceImplementeeIf(namedTypeDescriptor.ImplementedBy[0]);

                foreach (NamedTypeDescriptor interfaceImplementee in
                         namedTypeDescriptor.ImplementedBy.Skip(1))
                {
                    var singleIf = InterfaceImplementeeIf(interfaceImplementee).SkipIndents();
                    ifChain.AddIfElse(singleIf);
                }

                ifChain.AddElse(
                    CodeInlineBuilder.New()
                    .SetText($"throw new {TypeNames.NotSupportedException}();"));

                method.AddCode(ifChain);
            }

            IfBuilder InterfaceImplementeeIf(NamedTypeDescriptor interfaceImplementee)
            {
                var ifCorrectType = IfBuilder.New();

                if (isNonNullable)
                {
                    ifCorrectType.SetCondition(
                        $"{DataParamName}.__typename.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson})");
                }
                else
                {
                    ifCorrectType.SetCondition(
                        $"{DataParamName}?.__typename.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson}) ?? false");
                }


                var constructorCall = MethodCallBuilder.New()
                                      .SetPrefix($"{variableName} = new ")
                                      .SetMethodName(interfaceImplementee.Name);

                foreach (PropertyDescriptor prop in interfaceImplementee.Properties)
                {
                    var propAccess = $"{DataParamName}.{prop.Name}";
                    if (prop.Type.IsEntityType())
                    {
                        constructorCall.AddArgument(
                            BuildMapMethodCall(
                                DataParamName,
                                prop,
                                true));
                    }
                    else
                    {
                        constructorCall.AddArgument(
                            $"{propAccess} ?? throw new {TypeNames.ArgumentNullException}()");
                    }
                }

                ifCorrectType.AddCode(constructorCall);
                return(ifCorrectType);
            }

            method.AddCode($"return {variableName};");

            AddRequiredMapMethods(
                DataParamName,
                namedTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
        private void AddBuildDataMethod(
            InterfaceTypeDescriptor resultNamedType,
            ClassBuilder classBuilder)
        {
            var concreteType =
                CreateResultInfoName(resultNamedType.ImplementedBy.First().RuntimeType.Name);

            MethodBuilder buildDataMethod = classBuilder
                                            .AddMethod()
                                            .SetPrivate()
                                            .SetName("BuildData")
                                            .SetReturnType($"({resultNamedType.RuntimeType.Name}, {concreteType})")
                                            .AddParameter(_obj, x => x.SetType(TypeNames.JsonElement))
                                            .AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"using {TypeNames.IEntityUpdateSession} {_session}")
                .SetRighthandSide(
                    MethodCallBuilder
                    .Inline()
                    .SetMethodName(_entityStore, nameof(IEntityStore.BeginUpdate))))
                                            .AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {_entityIds}")
                .SetRighthandSide(MethodCallBuilder
                                  .Inline()
                                  .SetNew()
                                  .SetMethodName(TypeNames.HashSet)
                                  .AddGeneric(TypeNames.EntityId)))
                                            .AddEmptyLine();

            foreach (PropertyDescriptor property in
                     resultNamedType.Properties.Where(prop => prop.Type.IsEntityType()))
            {
                buildDataMethod.AddCode(
                    AssignmentBuilder
                    .New()
                    .SetLefthandSide(CodeBlockBuilder
                                     .New()
                                     .AddCode(property.Type.ToEntityIdBuilder())
                                     .AddCode($"{GetParameterName(property.Name)}Id"))
                    .SetRighthandSide(BuildUpdateMethodCall(property)));
            }

            buildDataMethod
            .AddEmptyLine()
            .AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {_resultInfo}")
                .SetRighthandSide(
                    CreateResultInfoMethodCall(resultNamedType, concreteType)))
            .AddEmptyLine()
            .AddCode(
                TupleBuilder
                .Inline()
                .SetDetermineStatement(true)
                .SetReturn()
                .AddMember(MethodCallBuilder
                           .Inline()
                           .SetMethodName(
                               _resultDataFactory,
                               nameof(IOperationResultDataFactory <object> .Create))
                           .AddArgument(_resultInfo))
                .AddMember(_resultInfo));
        }
        private void AddArrayHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder methodBuilder,
            ListTypeDescriptor listTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            methodBuilder
            .AddParameter(_list)
            .SetType(listTypeDescriptor.ToEntityIdBuilder());

            var listVarName = GetParameterName(listTypeDescriptor.Name) + "s";

            if (!isNonNullable)
            {
                methodBuilder.AddCode(EnsureProperNullability(_list, isNonNullable));
            }

            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {listVarName}")
                .SetRighthandSide(
                    CodeBlockBuilder
                    .New()
                    .AddCode("new ")
                    .AddCode(TypeNames.List)
                    .AddCode("<")
                    .AddCode(listTypeDescriptor.InnerType.ToBuilder().SkipTrailingSpace())
                    .AddCode(">")
                    .AddCode("()")));
            methodBuilder.AddEmptyLine();

            ForEachBuilder forEachBuilder = ForEachBuilder
                                            .New()
                                            .SetLoopHeader(
                CodeBlockBuilder
                .New()
                .AddCode(listTypeDescriptor.InnerType.ToEntityIdBuilder())
                .AddCode($"{_child} in {_list}"))
                                            .AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(listVarName, nameof(List <object> .Add))
                .AddArgument(MethodCallBuilder
                             .Inline()
                             .SetMethodName(MapMethodNameFromTypeName(listTypeDescriptor.InnerType))
                             .AddArgument(_child)));

            methodBuilder
            .AddCode(forEachBuilder)
            .AddEmptyLine()
            .AddCode($"return {listVarName};");

            AddMapMethod(
                listVarName,
                listTypeDescriptor.InnerType,
                classBuilder,
                constructorBuilder,
                processed);
        }
        private void AddEntityHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            var nullabilityAdditive = "?";

            if (isNonNullable)
            {
                nullabilityAdditive = "";
            }

            method.AddParameter(
                ParameterBuilder.New()
                .SetType(TypeNames.EntityId + nullabilityAdditive)
                .SetName(EntityIdParamName));

            if (!isNonNullable)
            {
                method.AddCode(
                    EnsureProperNullability(
                        EntityIdParamName,
                        isNonNullable));
            }


            foreach (NamedTypeDescriptor implementee in namedTypeDescriptor.ImplementedBy)
            {
                var dataMapperName =
                    EntityMapperNameFromGraphQLTypeName(
                        implementee.Name,
                        implementee.GraphQLTypeName);

                if (processed.Add(dataMapperName))
                {
                    var dataMapperType =
                        $"{TypeNames.IEntityMapper}<" +
                        $"{EntityTypeNameFromGraphQLTypeName(implementee.GraphQLTypeName)}, " +
                        $"{implementee.Name}>";

                    AddConstructorAssignedField(
                        dataMapperType,
                        dataMapperName.ToFieldName(),
                        classBuilder,
                        constructorBuilder);
                }
            }

            foreach (NamedTypeDescriptor interfaceImplementee in namedTypeDescriptor.ImplementedBy)
            {
                method.AddCode(InterfaceImplementeeIf(interfaceImplementee));
            }

            method.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));

            IfBuilder InterfaceImplementeeIf(NamedTypeDescriptor interfaceImplementee)
            {
                var dataMapperName =
                    EntityMapperNameFromGraphQLTypeName(
                        interfaceImplementee.Name,
                        interfaceImplementee.GraphQLTypeName)
                    .ToFieldName();

                var ifCorrectType = IfBuilder.New();

                if (isNonNullable)
                {
                    ifCorrectType.SetCondition(
                        $"{EntityIdParamName}.Name.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson})");
                }
                else
                {
                    ifCorrectType.SetCondition(
                        $"{EntityIdParamName}.Value.Name.Equals(\"" +
                        $"{interfaceImplementee.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson})");
                }

                MethodCallBuilder constructorCall = MethodCallBuilder.New()
                                                    .SetPrefix($"return {dataMapperName}.")
                                                    .SetWrapArguments()
                                                    .SetMethodName(nameof(IEntityMapper <object, object> .Map));

                MethodCallBuilder argument = MethodCallBuilder.New()
                                             .SetMethodName($"{StoreFieldName}.{nameof(IEntityStore.GetEntity)}")
                                             .SetDetermineStatement(false)
                                             .AddGeneric(
                    EntityTypeNameFromGraphQLTypeName(interfaceImplementee.GraphQLTypeName))
                                             .AddArgument(isNonNullable ? EntityIdParamName : $"{EntityIdParamName}.Value");

                constructorCall.AddArgument(
                    NullCheckBuilder.New()
                    .SetDetermineStatement(false)
                    .SetCondition(argument)
                    .SetCode(ExceptionBuilder
                             .New(TypeNames.GraphQLClientException)
                             .SetDetermineStatement(false)));

                method.AddEmptyLine();
                ifCorrectType.AddCode(constructorCall);
                return(ifCorrectType);
            }
        }
Пример #7
0
        private void AddDataTypeDeserializerMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            if (namedTypeDescriptor.IsInterface)
            {
                methodBuilder.AddCode(
                    "var typename = obj.Value.GetProperty(\"__typename\").GetString();");

                // If the type is an interface
                foreach (NamedTypeDescriptor concreteType in namedTypeDescriptor.ImplementedBy)
                {
                    methodBuilder.AddEmptyLine();
                    var ifStatement = IfBuilder.New()
                                      .SetCondition(
                        $"typename?.Equals(\"{concreteType.GraphQLTypeName}\", " +
                        $"{TypeNames.OrdinalStringComparisson}) ?? false");

                    var dataTypeName = $"global::{concreteType.Namespace}.State."
                                       + DataTypeNameFromTypeName(concreteType.GraphQLTypeName);

                    var returnStatement = MethodCallBuilder.New()
                                          .SetPrefix("return new ")
                                          .SetMethodName(dataTypeName);

                    returnStatement.AddArgument("typename");
                    foreach (PropertyDescriptor property in concreteType.Properties)
                    {
                        returnStatement.AddArgument(
                            CodeBlockBuilder.New()
                            .AddCode($"{property.Name.WithLowerFirstChar()}: ")
                            .AddCode(BuildUpdateMethodCall(property)));
                    }

                    ifStatement.AddCode(returnStatement);
                    methodBuilder.AddCode(ifStatement);
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();");
            }
            else
            {
                var returnStatement = MethodCallBuilder.New()
                                      .SetPrefix("return new ")
                                      .SetMethodName(namedTypeDescriptor.Name);

                foreach (PropertyDescriptor property in namedTypeDescriptor.Properties)
                {
                    returnStatement.AddArgument(BuildUpdateMethodCall(property));
                }

                methodBuilder.AddCode(returnStatement);
            }

            AddRequiredDeserializeMethods(
                namedTypeDescriptor,
                classBuilder,
                processed);
        }
Пример #8
0
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            var entityIdVarName = "entityId";

            methodBuilder.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide(
                    CodeBlockBuilder.New()
                    .AddCode(TypeNames.EntityId)
                    .AddCode($" {entityIdVarName}"))
                .SetRighthandSide($"{_extractIdFieldName}({_objParamName}.Value)"));

            methodBuilder.AddCode($"{_entityIdsParam}.Add({entityIdVarName});");
            methodBuilder.AddEmptyLine();

            var entityVarName = "entity";

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    methodBuilder.AddEmptyLine();
                    var ifStatement = IfBuilder.New()
                                      .SetCondition(
                        $"entityId.Name.Equals(\"{concreteType.Name}\", " +
                        $"{TypeNames.OrdinalStringComparison})");

                    var entityTypeName = CreateEntityTypeName(concreteType.Name);

                    WriteEntityLoader(
                        ifStatement,
                        entityTypeName,
                        entityVarName,
                        entityIdVarName);

                    WritePropertyAssignments(
                        ifStatement,
                        concreteType.Properties,
                        entityVarName);

                    ifStatement.AddEmptyLine();
                    ifStatement.AddCode($"return {entityIdVarName};");
                    methodBuilder.AddCode(ifStatement);
                }

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();");
            }
            else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                WriteEntityLoader(
                    methodBuilder,
                    CreateEntityTypeName(namedTypeDescriptor.Name),
                    entityVarName,
                    entityIdVarName);

                WritePropertyAssignments(
                    methodBuilder,
                    complexTypeDescriptor.Properties,
                    entityVarName);

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"return {entityIdVarName};");
            }

            AddRequiredDeserializeMethods(
                namedTypeDescriptor,
                classBuilder,
                processed);
        }