Exemplo n.º 1
0
        private static MethodBuilder BuildEqualsMethod(
            string typeName,
            IReadOnlyList <PropertyDescriptor> properties)
        {
            const string other = nameof(other);

            ConditionBuilder equalCondition =
                ConditionBuilder
                .New()
                .SetReturn()
                .SetDetermineStatement();

            if (properties.Count == 0)
            {
                equalCondition.And("true");
            }
            else
            {
                foreach (PropertyDescriptor property in properties)
                {
                    equalCondition.And(ConditionBuilder
                                       .New()
                                       .Set(BuildPropertyComparison(property.Type, property.Name)));
                }
            }

            return(MethodBuilder
                   .New()
                   .SetName(nameof(IEquatable <object> .Equals))
                   .SetPublic()
                   .SetInheritance(Inheritance.Virtual)
                   .SetReturnType(TypeNames.Boolean)
                   .AddParameter(other, x => x.SetType(typeName.MakeNullable()))
                   .AddCode(CodeBlockBuilder
                            .New()
                            .AddCode(IfBuilder
                                     .New()
                                     .SetCondition(MethodCallBuilder
                                                   .Inline()
                                                   .SetMethodName(nameof(ReferenceEquals))
                                                   .AddArgument("null")
                                                   .AddArgument(other))
                                     .AddCode("return false;"))
                            .AddEmptyLine()
                            .AddCode(IfBuilder
                                     .New()
                                     .SetCondition(MethodCallBuilder
                                                   .Inline()
                                                   .SetMethodName(nameof(ReferenceEquals))
                                                   .AddArgument("this")
                                                   .AddArgument(other))
                                     .AddCode("return true;"))
                            .AddEmptyLine()
                            .AddCode(IfBuilder
                                     .New()
                                     .SetCondition($"{other}.GetType() != GetType()")
                                     .AddCode("return false;"))
                            .AddEmptyLine()
                            .AddCode(equalCondition)));
        }
        private void AddInterfaceDataTypeDeserializerToMethod(
            MethodBuilder methodBuilder,
            InterfaceTypeDescriptor interfaceTypeDescriptor)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {_typename}")
                .SetRighthandSide(MethodCallBuilder
                                  .Inline()
                                  .SetMethodName(
                                      _obj,
                                      "Value",
                                      nameof(JsonElement.GetProperty))
                                  .AddArgument(WellKnownNames.TypeName.AsStringToken())
                                  .Chain(x => x.SetMethodName(nameof(JsonElement.GetString)))));

            // If the type is an interface
            foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
            {
                MethodCallBuilder returnStatement = MethodCallBuilder
                                                    .New()
                                                    .SetReturn()
                                                    .SetNew()
                                                    .SetMethodName(
                    $"{concreteType.RuntimeType.Namespace}.State." +
                    CreateDataTypeName(concreteType.Name))
                                                    .AddArgument("typename");

                foreach (PropertyDescriptor property in concreteType.Properties)
                {
                    if (property.Name.Value.EqualsOrdinal(WellKnownNames.TypeName))
                    {
                        continue;
                    }

                    returnStatement.AddArgument(
                        CodeBlockBuilder
                        .New()
                        .AddCode($"{GetParameterName(property.Name)}: ")
                        .AddCode(BuildUpdateMethodCall(property)));
                }

                IfBuilder ifStatement = IfBuilder
                                        .New()
                                        .SetCondition(
                    $"typename?.Equals(\"{concreteType.Name}\", " +
                    $"{TypeNames.OrdinalStringComparison}) ?? false")
                                        .AddCode(returnStatement);

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

            methodBuilder
            .AddEmptyLine()
            .AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
        }
Exemplo n.º 3
0
        private IfBuilder GenerateDataInterfaceIfClause(
            ObjectTypeDescriptor objectTypeDescriptor,
            bool isNonNullable,
            string variableName)
        {
            ICode ifCondition = MethodCallBuilder
                                .Inline()
                                .SetMethodName(
                _dataParameterName.MakeNullable(!isNonNullable),
                WellKnownNames.TypeName,
                nameof(string.Equals))
                                .AddArgument(objectTypeDescriptor.Name.AsStringToken())
                                .AddArgument(TypeNames.OrdinalStringComparison);

            if (!isNonNullable)
            {
                ifCondition = NullCheckBuilder
                              .New()
                              .SetCondition(ifCondition)
                              .SetSingleLine()
                              .SetDetermineStatement(false)
                              .SetCode("false");
            }

            MethodCallBuilder constructorCall = MethodCallBuilder
                                                .Inline()
                                                .SetNew()
                                                .SetMethodName(objectTypeDescriptor.RuntimeType.Name);

            foreach (PropertyDescriptor prop in objectTypeDescriptor.Properties)
            {
                var propAccess = $"{_dataParameterName}.{prop.Name}";
                if (prop.Type.IsEntityType() || prop.Type.IsDataType())
                {
                    constructorCall.AddArgument(BuildMapMethodCall(_dataParameterName, prop, true));
                }
                else if (prop.Type.IsNullableType())
                {
                    constructorCall.AddArgument(propAccess);
                }
                else
                {
                    constructorCall
                    .AddArgument(
                        NullCheckBuilder
                        .Inline()
                        .SetCondition(propAccess)
                        .SetCode(ExceptionBuilder.Inline(TypeNames.ArgumentNullException)));
                }
            }

            return(IfBuilder
                   .New()
                   .SetCondition(ifCondition)
                   .AddCode(AssignmentBuilder
                            .New()
                            .SetLefthandSide(variableName)
                            .SetRighthandSide(constructorCall)));
        }
        private static ICode GenerateEntityHandlerIfClause(
            ObjectTypeDescriptor objectTypeDescriptor,
            bool isNonNullable)
        {
            var dataMapperName =
                GetFieldName(
                    CreateEntityMapperName(
                        objectTypeDescriptor.RuntimeType.Name,
                        objectTypeDescriptor.Name));

            MethodCallBuilder constructorCall = MethodCallBuilder
                                                .New()
                                                .SetReturn()
                                                .SetWrapArguments()
                                                .SetMethodName(dataMapperName, nameof(IEntityMapper <object, object> .Map));

            MethodCallBuilder argument = MethodCallBuilder
                                         .Inline()
                                         .SetMethodName(StoreFieldName, nameof(IEntityStore.GetEntity))
                                         .AddGeneric(CreateEntityTypeName(objectTypeDescriptor.Name))
                                         .AddArgument(isNonNullable ? _entityId : $"{_entityId}.Value");

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


            IfBuilder ifCorrectType = IfBuilder
                                      .New()
                                      .AddCode(constructorCall)
                                      .SetCondition(
                MethodCallBuilder
                .Inline()
                .SetMethodName(
                    isNonNullable
                                ? new[]
            {
                _entityId,
                nameof(EntityId.Name),
                nameof(string.Equals)
            }
                                : new[]
            {
                _entityId,
                nameof(Nullable <EntityId> .Value),
                nameof(EntityId.Name),
                nameof(string.Equals)
            })
                .AddArgument(objectTypeDescriptor.Name.AsStringToken())
                .AddArgument(TypeNames.OrdinalStringComparison));

            return(CodeBlockBuilder
                   .New()
                   .AddEmptyLine()
                   .AddCode(ifCorrectType));
        }
Exemplo n.º 5
0
        public static CodeBlockBuilder AddIf(
            this CodeBlockBuilder builder,
            Action <IfBuilder> configure)
        {
            var ifBuilder = IfBuilder.New();

            configure(ifBuilder);
            return(builder.AddCode(ifBuilder));
        }
Exemplo n.º 6
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);
        }
 private IfBuilder BuildTryGetEntityIf(RuntimeTypeInfo entityType)
 {
     return(IfBuilder
            .New()
            .SetCondition(MethodCallBuilder
                          .Inline()
                          .SetMethodName(_session, "CurrentSnapshot", "TryGetEntity")
                          .AddArgument(_entityId)
                          .AddOutArgument(_entity, entityType.ToString())));
 }
Exemplo n.º 8
0
        private static ICode GenerateEntityHandlerIfClause(
            ObjectTypeDescriptor objectTypeDescriptor,
            bool isNonNullable)
        {
            var dataMapperName =
                GetFieldName(
                    CreateEntityMapperName(
                        objectTypeDescriptor.RuntimeType.Name,
                        objectTypeDescriptor.Name));

            var ifCorrectType = IfBuilder.New();

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

            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(CreateEntityTypeName(objectTypeDescriptor.Name))
                                         .AddArgument(isNonNullable ? EntityIdParamName : $"{EntityIdParamName}.Value");

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

            ifCorrectType.AddCode(constructorCall);

            return(CodeBlockBuilder.New()
                   .AddEmptyLine()
                   .AddCode(ifCorrectType));
        }
        private void AddDeserializeMethod(
            ITypeDescriptor typeReference,
            ClassBuilder classBuilder,
            HashSet <string> processed)
        {
            string methodName = DeserializerMethodNameFromTypeName(typeReference);

            if (processed.Add(methodName))
            {
                MethodBuilder methodBuilder = classBuilder
                                              .AddMethod()
                                              .SetPrivate()
                                              .SetReturnType(typeReference.ToStateTypeReference())
                                              .SetName(methodName);


                if (typeReference.IsOrContainsEntityType())
                {
                    methodBuilder
                    .AddParameter(_session, x => x.SetType(TypeNames.IEntityStoreUpdateSession))
                    .AddParameter(_obj, x => x.SetType(TypeNames.JsonElement.MakeNullable()))
                    .AddParameter(
                        _entityIds,
                        x => x.SetType(TypeNames.ISet.WithGeneric(TypeNames.EntityId)));
                }
                else
                {
                    methodBuilder
                    .AddParameter(_obj)
                    .SetType(TypeNames.JsonElement.MakeNullable());
                }

                IfBuilder jsonElementNullCheck = IfBuilder
                                                 .New()
                                                 .SetCondition($"!{_obj}.HasValue")
                                                 .AddCode(
                    typeReference.IsNonNullableType()
                            ? ExceptionBuilder.New(TypeNames.ArgumentNullException)
                            : CodeLineBuilder.From("return null;"));

                methodBuilder
                .AddCode(jsonElementNullCheck)
                .AddEmptyLine();

                AddDeserializeMethodBody(classBuilder, methodBuilder, typeReference, processed);
            }
        }
Exemplo n.º 10
0
        private IfBuilder GenerateDataInterfaceIfClause(
            ObjectTypeDescriptor objectTypeDescriptor,
            bool isNonNullable,
            string variableName)
        {
            var ifCorrectType = IfBuilder.New();

            if (isNonNullable)
            {
                ifCorrectType.SetCondition(
                    $"{_dataParameterName}.__typename.Equals(\"" +
                    $"{objectTypeDescriptor.Name}\", " +
                    $"{TypeNames.OrdinalStringComparison})");
            }
            else
            {
                ifCorrectType.SetCondition(
                    $"{_dataParameterName}?.__typename.Equals(\"" +
                    $"{objectTypeDescriptor.Name}\", " +
                    $"{TypeNames.OrdinalStringComparison}) ?? false");
            }


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

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

            ifCorrectType.AddCode(constructorCall);
            return(ifCorrectType);
        }
Exemplo n.º 11
0
        private static ICode BuildProperty(
            ITypeDescriptor type,
            string propertyName)
        {
            return(BuildPropertyInternal(type, propertyName, true));

            ICode BuildPropertyInternal(
                ITypeDescriptor currentType,
                string variableName,
                bool isNullable)
            {
                ICode check = currentType switch
                {
                    NonNullTypeDescriptor d =>
                    BuildPropertyInternal(d.InnerType, variableName, false),
                    INamedTypeDescriptor => AssignmentBuilder
                    .New()
                    .SetLefthandSide(HashCodeBuilder.VariableName)
                    .SetOperator("^=")
                    .SetRighthandSide(MethodCallBuilder
                                      .Inline()
                                      .SetPrefix($"{HashCodeBuilder.Prime} * ")
                                      .SetMethodName(variableName, nameof(GetHashCode))),
                    ListTypeDescriptor d => ForEachBuilder
                    .New()
                    .SetLoopHeader($"var {variableName}_elm in {variableName}")
                    .AddCode(BuildPropertyInternal(d.InnerType, variableName + "_elm", true)),
                    _ => throw new ArgumentOutOfRangeException()
                };

                if (isNullable && currentType is not NonNullTypeDescriptor)
                {
                    return(IfBuilder
                           .New()
                           .SetCondition($"!({variableName} is null)")
                           .AddCode(check));
                }

                return(check);
            }
        }
    }
        private CodeBlockBuilder EnsureProperNullability(
            string propertyName = _objParamName,
            bool isNonNullType  = false)
        {
            var ifBuilder = IfBuilder
                            .New()
                            .SetCondition(
                ConditionBuilder.New()
                .Set($"!{propertyName}.HasValue"));

            ifBuilder.AddCode(
                isNonNullType
                    ? $"throw new {TypeNames.ArgumentNullException}();"
                    : "return null;");

            var codeBuilder = CodeBlockBuilder.New()
                              .AddCode(ifBuilder)
                              .AddEmptyLine();

            return(codeBuilder);
        }
Exemplo n.º 13
0
        private void AddInterfaceDataTypeDeserializerToMethod(
            MethodBuilder methodBuilder,
            InterfaceTypeDescriptor interfaceTypeDescriptor)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"var {_typename}")
                .SetRighthandSide(MethodCallBuilder
                                  .Inline()
                                  .SetMethodName(
                                      _obj,
                                      "Value",
                                      nameof(JsonElement.GetProperty))
                                  .AddArgument(WellKnownNames.TypeName.AsStringToken())
                                  .Chain(x => x.SetMethodName(nameof(JsonElement.GetString)))));

            // If the type is an interface
            foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
            {
                MethodCallBuilder returnStatement = CreateBuildDataStatement(concreteType)
                                                    .SetReturn();

                IfBuilder ifStatement = IfBuilder
                                        .New()
                                        .SetCondition(
                    $"typename?.Equals(\"{concreteType.Name}\", " +
                    $"{TypeNames.OrdinalStringComparison}) ?? false")
                                        .AddCode(returnStatement);

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

            methodBuilder
            .AddEmptyLine()
            .AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
        }
Exemplo n.º 14
0
        private IfBuilder GenerateComplexDataInterfaceIfClause(
            ObjectTypeDescriptor objectTypeDescriptor,
            string variableName)
        {
            var ifCorrectType   = IfBuilder.New();
            var matchedTypeName = GetParameterName(objectTypeDescriptor.Name);

            // since we want to create the data name we will need to craft the type name
            // by hand by using the GraphQL type name and the state namespace.
            // TODO : state namespace should be available here!
            var dataTypeName = new RuntimeTypeInfo(
                CreateDataTypeName(objectTypeDescriptor.Name),
                $"{objectTypeDescriptor.RuntimeType.Namespace}.State");

            ifCorrectType.SetCondition(
                $"{_dataParameterName} is {dataTypeName} {matchedTypeName}");

            var constructorCall = MethodCallBuilder.New()
                                  .SetPrefix($"{variableName} = new ")
                                  .SetMethodName(objectTypeDescriptor.RuntimeType.ToString());

            foreach (PropertyDescriptor prop in objectTypeDescriptor.Properties)
            {
                var propAccess = $"{matchedTypeName}.{prop.Name}";
                if (prop.Type.IsEntityType())
                {
                    constructorCall.AddArgument(
                        BuildMapMethodCall(
                            matchedTypeName,
                            prop));
                }
                else
                {
                    constructorCall.AddArgument(propAccess);
                }
            }

            return(ifCorrectType.AddCode(constructorCall));
        }
 private TryCatchBuilder CreateBuildDataSerialization()
 {
     return(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(CreateDataError())));
 }
        private IfBuilder GenerateComplexDataInterfaceIfClause(
            ObjectTypeDescriptor objectTypeDescriptor,
            string variableName)
        {
            var matchedTypeName = GetParameterName(objectTypeDescriptor.Name);

            // since we want to create the data name we will need to craft the type name
            // by hand by using the GraphQL type name and the state namespace.
            var dataTypeName = new RuntimeTypeInfo(
                CreateDataTypeName(objectTypeDescriptor.Name),
                $"{objectTypeDescriptor.RuntimeType.Namespace}.State");

            MethodCallBuilder constructorCall = MethodCallBuilder
                                                .Inline()
                                                .SetNew()
                                                .SetMethodName(objectTypeDescriptor.RuntimeType.ToString());

            foreach (PropertyDescriptor prop in objectTypeDescriptor.Properties)
            {
                if (prop.Type.IsEntityType())
                {
                    constructorCall.AddArgument(BuildMapMethodCall(matchedTypeName, prop));
                }
                else
                {
                    constructorCall.AddArgument($"{matchedTypeName}.{prop.Name}");
                }
            }

            return(IfBuilder
                   .New()
                   .SetCondition($"{_dataParameterName} is {dataTypeName} {matchedTypeName}")
                   .AddCode(
                       AssignmentBuilder
                       .New()
                       .SetLefthandSide(variableName)
                       .SetRighthandSide(constructorCall)));
        }
Exemplo n.º 17
0
        private static MethodBuilder BuildObjectEqualsMethod(string typeName)
        {
            const string obj = nameof(obj);

            return(MethodBuilder
                   .New()
                   .SetName(nameof(IEquatable <object> .Equals))
                   .SetPublic()
                   .SetOverride()
                   .SetReturnType(TypeNames.Boolean)
                   .AddParameter(obj, x => x.SetType(TypeNames.Object.MakeNullable()))
                   .AddCode(CodeBlockBuilder
                            .New()
                            .AddCode(IfBuilder
                                     .New()
                                     .SetCondition(MethodCallBuilder
                                                   .Inline()
                                                   .SetMethodName(nameof(ReferenceEquals))
                                                   .AddArgument("null")
                                                   .AddArgument(obj))
                                     .AddCode("return false;"))
                            .AddEmptyLine()
                            .AddCode(IfBuilder
                                     .New()
                                     .SetCondition(MethodCallBuilder
                                                   .Inline()
                                                   .SetMethodName(nameof(ReferenceEquals))
                                                   .AddArgument("this")
                                                   .AddArgument(obj))
                                     .AddCode("return true;"))
                            .AddEmptyLine()
                            .AddCode(IfBuilder
                                     .New()
                                     .SetCondition($"{obj}.GetType() != GetType()")
                                     .AddCode("return false;"))
                            .AddEmptyLine()
                            .AddLine($"return Equals(({typeName}){obj});")));
        }
        private IfBuilder CreateUpdateEntityStatement(
            ObjectTypeDescriptor concreteType)
        {
            IfBuilder ifStatement = IfBuilder
                                    .New()
                                    .SetCondition(
                MethodCallBuilder
                .Inline()
                .SetMethodName(_entityId, "Name", nameof(string.Equals))
                .AddArgument(concreteType.Name.AsStringToken())
                .AddArgument(TypeNames.OrdinalStringComparison));

            RuntimeTypeInfo entityTypeName = CreateEntityType(
                concreteType.Name,
                concreteType.RuntimeType.NamespaceWithoutGlobal);

            IfBuilder ifBuilder = BuildTryGetEntityIf(entityTypeName)
                                  .AddCode(CreateEntityConstructorCall(concreteType, false))
                                  .AddElse(CreateEntityConstructorCall(concreteType, true));

            return(ifStatement
                   .AddCode(ifBuilder)
                   .AddEmptyLine());
        }
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"{TypeNames.EntityId} {_entityId}")
                .SetRighthandSide(
                    MethodCallBuilder
                    .Inline()
                    .SetMethodName(_idSerializer, "Parse")
                    .AddArgument($"{_obj}.Value")));

            methodBuilder.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(_entityIds, nameof(List <object> .Add))
                .AddArgument(_entityId));

            methodBuilder.AddEmptyLine();

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    IfBuilder ifStatement = IfBuilder
                                            .New()
                                            .SetCondition(
                        MethodCallBuilder
                        .Inline()
                        .SetMethodName(_entityId, "Name", nameof(string.Equals))
                        .AddArgument(concreteType.Name.AsStringToken())
                        .AddArgument(TypeNames.OrdinalStringComparison));

                    var entityTypeName = CreateEntityType(
                        concreteType.Name,
                        concreteType.RuntimeType.NamespaceWithoutGlobal);

                    IfBuilder ifBuilder = BuildTryGetEntityIf(entityTypeName)
                                          .AddCode(CreateEntityConstructorCall(concreteType, false))
                                          .AddElse(CreateEntityConstructorCall(concreteType, true));

                    ifStatement
                    .AddCode(ifBuilder)
                    .AddEmptyLine()
                    .AddCode($"return {_entityId};");

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

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
            }
            else if (namedTypeDescriptor is ObjectTypeDescriptor objectTypeDescriptor)
            {
                BuildTryGetEntityIf(
                    CreateEntityType(
                        objectTypeDescriptor.Name,
                        objectTypeDescriptor.RuntimeType.NamespaceWithoutGlobal))
                .AddCode(CreateEntityConstructorCall(objectTypeDescriptor, false))
                .AddElse(CreateEntityConstructorCall(objectTypeDescriptor, true));

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

            AddRequiredDeserializeMethods(namedTypeDescriptor, classBuilder, 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 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"));
        }
Exemplo n.º 22
0
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            ComplexTypeDescriptor descriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result data factory can only be generated for complex types");

            var(classBuilder, constructorBuilder) = CreateClassBuilder();

            fileName = CreateResultFactoryName(descriptor.RuntimeType.Name);
            classBuilder
            .SetName(fileName)
            .AddImplements(     // TODO: This should be descriptor.RuntimeType!
                $"{TypeNames.IOperationResultDataFactory}<{descriptor.RuntimeType.Name}>");

            constructorBuilder
            .SetTypeName(descriptor.Name)
            .SetAccessModifier(AccessModifier.Public);

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

            var createMethod = MethodBuilder.New()
                               .SetAccessModifier(AccessModifier.Public)
                               .SetName("Create")
                               .SetReturnType(descriptor.RuntimeType.Name)
                               .AddParameter("dataInfo", b => b.SetType(TypeNames.IOperationResultDataInfo));

            var returnStatement = MethodCallBuilder.New()
                                  .SetPrefix("return new ")
                                  .SetMethodName(descriptor.RuntimeType.Name);

            var ifHasCorrectType = IfBuilder.New()
                                   .SetCondition(
                $"dataInfo is {CreateResultInfoName(descriptor.RuntimeType.Name)} info");

            foreach (PropertyDescriptor property in descriptor.Properties)
            {
                returnStatement.AddArgument(
                    BuildMapMethodCall(
                        "info",
                        property));
            }

            ifHasCorrectType.AddCode(returnStatement);
            createMethod.AddCode(ifHasCorrectType);
            createMethod.AddEmptyLine();
            createMethod.AddCode(
                $"throw new {TypeNames.ArgumentException}(\"" +
                $"{CreateResultInfoName(descriptor.RuntimeType.Name)} expected.\");");

            classBuilder.AddMethod(createMethod);

            var processed = new HashSet <string>();

            AddRequiredMapMethods(
                "info",
                descriptor,
                classBuilder,
                constructorBuilder,
                processed,
                true);

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal)
            .AddType(classBuilder)
            .Build(writer);
        }
        protected override void Generate(ITypeDescriptor typeDescriptor,
                                         CSharpSyntaxGeneratorSettings settings,
                                         CodeWriter writer,
                                         out string fileName,
                                         out string?path,
                                         out string ns)
        {
            ComplexTypeDescriptor descriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result data factory can only be generated for complex types");

            fileName = CreateResultFactoryName(descriptor.RuntimeType.Name);
            path     = State;
            ns       = CreateStateNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal);

            ClassBuilder classBuilder =
                ClassBuilder
                .New()
                .SetName(fileName)
                .AddImplements(
                    TypeNames.IOperationResultDataFactory.WithGeneric(descriptor.RuntimeType));

            ConstructorBuilder constructorBuilder = classBuilder
                                                    .AddConstructor()
                                                    .SetTypeName(descriptor.Name);

            if (settings.IsStoreEnabled())
            {
                AddConstructorAssignedField(
                    TypeNames.IEntityStore,
                    _entityStore,
                    entityStore,
                    classBuilder,
                    constructorBuilder);
            }

            MethodCallBuilder returnStatement = MethodCallBuilder
                                                .New()
                                                .SetReturn()
                                                .SetNew()
                                                .SetMethodName(descriptor.RuntimeType.Name);

            foreach (PropertyDescriptor property in descriptor.Properties)
            {
                returnStatement
                .AddArgument(BuildMapMethodCall(settings, _info, property));
            }

            IfBuilder ifHasCorrectType = IfBuilder
                                         .New()
                                         .SetCondition(
                $"{_dataInfo} is {CreateResultInfoName(descriptor.RuntimeType.Name)} {_info}")
                                         .AddCode(returnStatement);

            MethodBuilder createMethod = classBuilder
                                         .AddMethod("Create")
                                         .SetAccessModifier(AccessModifier.Public)
                                         .SetReturnType(descriptor.RuntimeType.Name)
                                         .AddParameter(_dataInfo, b => b.SetType(TypeNames.IOperationResultDataInfo))
                                         .AddParameter(
                _snapshot,
                b => b.SetDefault("null")
                .SetType(TypeNames.IEntityStoreSnapshot.MakeNullable()));

            if (settings.IsStoreEnabled())
            {
                createMethod
                .AddCode(
                    IfBuilder.New()
                    .SetCondition($"{_snapshot} is null")
                    .AddCode(
                        AssignmentBuilder
                        .New()
                        .SetLefthandSide(_snapshot)
                        .SetRighthandSide($"{_entityStore}.CurrentSnapshot")))
                .AddEmptyLine();
            }

            createMethod.AddCode(ifHasCorrectType)
            .AddEmptyLine()
            .AddCode(
                ExceptionBuilder
                .New(TypeNames.ArgumentException)
                .AddArgument(
                    $"\"{CreateResultInfoName(descriptor.RuntimeType.Name)} expected.\""));

            var processed = new HashSet <string>();

            AddRequiredMapMethods(
                settings,
                _info,
                descriptor,
                classBuilder,
                constructorBuilder,
                processed,
                true);

            classBuilder
            .AddProperty("ResultType")
            .SetType(TypeNames.Type)
            .AsLambda($"typeof({descriptor.RuntimeType.Namespace}.{descriptor.Implements[0]})")
            .SetInterface(TypeNames.IOperationResultDataFactory);

            classBuilder
            .AddMethod("Create")
            .SetInterface(TypeNames.IOperationResultDataFactory)
            .SetReturnType(TypeNames.Object)
            .AddParameter(_dataInfo, b => b.SetType(TypeNames.IOperationResultDataInfo))
            .AddParameter(
                _snapshot,
                b => b.SetType(TypeNames.IEntityStoreSnapshot.MakeNullable()))
            .AddCode(
                MethodCallBuilder
                .New()
                .SetReturn()
                .SetMethodName("Create")
                .AddArgument(_dataInfo)
                .AddArgument(_snapshot));

            classBuilder.Build(writer);
        }
        protected override void Generate(ITypeDescriptor typeDescriptor,
                                         CSharpSyntaxGeneratorSettings settings,
                                         CodeWriter writer,
                                         out string fileName,
                                         out string?path,
                                         out string ns)
        {
            // Setup class
            ComplexTypeDescriptor descriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result entity mapper can only be generated for complex types");

            fileName = descriptor.ExtractMapperName();
            path     = State;
            ns       = CreateStateNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal);

            ClassBuilder classBuilder = ClassBuilder
                                        .New()
                                        .AddImplements(
                TypeNames.IEntityMapper
                .WithGeneric(
                    descriptor.ExtractType().ToString(),
                    descriptor.RuntimeType.Name))
                                        .SetName(fileName);

            ConstructorBuilder constructorBuilder = ConstructorBuilder
                                                    .New()
                                                    .SetTypeName(descriptor.Name);

            AddConstructorAssignedField(
                TypeNames.IEntityStore,
                _entityStore,
                entityStore,
                classBuilder,
                constructorBuilder);

            // Define map method
            MethodBuilder mapMethod = MethodBuilder
                                      .New()
                                      .SetName(_map)
                                      .SetAccessModifier(AccessModifier.Public)
                                      .SetReturnType(descriptor.RuntimeType.Name)
                                      .AddParameter(
                ParameterBuilder
                .New()
                .SetType(
                    descriptor.Kind == TypeKind.Entity
                                ? CreateEntityType(
                        descriptor.Name,
                        descriptor.RuntimeType.NamespaceWithoutGlobal)
                    .ToString()
                                : descriptor.Name)
                .SetName(_entity))
                                      .AddParameter(
                _snapshot,
                b => b.SetDefault("null")
                .SetType(TypeNames.IEntityStoreSnapshot.MakeNullable()));

            mapMethod
            .AddCode(IfBuilder
                     .New()
                     .SetCondition($"{_snapshot} is null")
                     .AddCode(AssignmentBuilder
                              .New()
                              .SetLefthandSide(_snapshot)
                              .SetRighthandSide($"{_entityStore}.CurrentSnapshot")))
            .AddEmptyLine();

            MethodCallBuilder constructorCall =
                MethodCallBuilder
                .New()
                .SetReturn()
                .SetNew()
                .SetMethodName(descriptor.RuntimeType.Name);

            if (typeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                foreach (PropertyDescriptor property in complexTypeDescriptor.Properties)
                {
                    constructorCall.AddArgument(BuildMapMethodCall(settings, _entity, property));
                }
            }

            mapMethod.AddCode(constructorCall);

            if (constructorBuilder.HasParameters())
            {
                classBuilder.AddConstructor(constructorBuilder);
            }

            classBuilder.AddMethod(mapMethod);

            AddRequiredMapMethods(
                settings,
                _entity,
                descriptor,
                classBuilder,
                constructorBuilder,
                new HashSet <string>());

            classBuilder.Build(writer);
        }
Exemplo n.º 25
0
        private static ICode GenerateClientServiceProviderFactory(
            DependencyInjectionDescriptor descriptor)
        {
            CodeBlockBuilder codeBuilder = CodeBlockBuilder.New();

            if (descriptor.TransportProfiles.Count == 1)
            {
                return(codeBuilder
                       .AddCode(
                           MethodCallBuilder
                           .New()
                           .SetMethodName("ConfigureClient" + descriptor.TransportProfiles[0].Name)
                           .AddArgument(_sp)
                           .AddArgument(_serviceCollection)
                           .AddArgument(_strategy))
                       .AddEmptyLine()
                       .AddCode(MethodCallBuilder
                                .New()
                                .SetReturn()
                                .SetNew()
                                .SetMethodName("ClientServiceProvider")
                                .SetWrapArguments()
                                .AddArgument(MethodCallBuilder
                                             .Inline()
                                             .SetMethodName(TypeNames.BuildServiceProvider)
                                             .AddArgument(_serviceCollection))));
            }

            IfBuilder ifProfile = IfBuilder.New();

            var enumName = CreateProfileEnumReference(descriptor);

            for (var index = 0; index < descriptor.TransportProfiles.Count; index++)
            {
                TransportProfile profile   = descriptor.TransportProfiles[index];
                IfBuilder        currentIf = ifProfile;
                if (index != 0)
                {
                    currentIf = IfBuilder.New();
                    ifProfile.AddIfElse(currentIf);
                }

                currentIf
                .SetCondition($"{_profile} == {enumName}.{profile.Name}")
                .AddCode(
                    MethodCallBuilder
                    .New()
                    .SetMethodName("ConfigureClient" + profile.Name)
                    .AddArgument(_sp)
                    .AddArgument(_serviceCollection)
                    .AddArgument(_strategy));
            }

            return(codeBuilder
                   .AddCode(ifProfile)
                   .AddEmptyLine()
                   .AddCode(MethodCallBuilder
                            .New()
                            .SetReturn()
                            .SetNew()
                            .SetMethodName("ClientServiceProvider")
                            .SetWrapArguments()
                            .AddArgument(MethodCallBuilder
                                         .Inline()
                                         .SetMethodName(TypeNames.BuildServiceProvider)
                                         .AddArgument(_serviceCollection))));
        }
Exemplo n.º 26
0
        public static ClassBuilder AddEquality(
            this ClassBuilder builder,
            string typeName,
            IReadOnlyList <PropertyDescriptor> properties)
        {
            const string obj   = nameof(obj);
            const string other = nameof(other);

            builder.AddImplements(TypeNames.IEquatable.WithGeneric(typeName));

            builder
            .AddMethod(nameof(IEquatable <object> .Equals))
            .SetPublic()
            .SetOverride()
            .SetReturnType(TypeNames.Boolean)
            .AddParameter(obj, x => x.SetType(TypeNames.Object.MakeNullable()))
            .AddCode(CodeBlockBuilder
                     .New()
                     .AddCode(IfBuilder
                              .New()
                              .SetCondition(MethodCallBuilder
                                            .Inline()
                                            .SetMethodName(nameof(ReferenceEquals))
                                            .AddArgument("null")
                                            .AddArgument(obj))
                              .AddCode("return false;"))
                     .AddEmptyLine()
                     .AddCode(IfBuilder
                              .New()
                              .SetCondition(MethodCallBuilder
                                            .Inline()
                                            .SetMethodName(nameof(ReferenceEquals))
                                            .AddArgument("this")
                                            .AddArgument(obj))
                              .AddCode("return true;"))
                     .AddEmptyLine()
                     .AddCode(IfBuilder
                              .New()
                              .SetCondition($"{obj}.GetType() != GetType()")
                              .AddCode("return false;"))
                     .AddEmptyLine()
                     .AddLine($"return Equals(({typeName}){obj});"));

            ConditionBuilder equalCondition =
                ConditionBuilder
                .New()
                .SetReturn()
                .SetDetermineStatement();

            if (properties.Count == 0)
            {
                equalCondition.And("true");
            }
            else
            {
                foreach (PropertyDescriptor property in properties)
                {
                    equalCondition.And(ConditionBuilder
                                       .New()
                                       .Set(BuildPropertyComparison(property.Type, property.Name)));
                }
            }

            builder
            .AddMethod(nameof(IEquatable <object> .Equals))
            .SetPublic()
            .SetReturnType(TypeNames.Boolean)
            .AddParameter(other, x => x.SetType(typeName.MakeNullable()))
            .AddCode(CodeBlockBuilder
                     .New()
                     .AddCode(IfBuilder
                              .New()
                              .SetCondition(MethodCallBuilder
                                            .Inline()
                                            .SetMethodName(nameof(ReferenceEquals))
                                            .AddArgument("null")
                                            .AddArgument(other))
                              .AddCode("return false;"))
                     .AddEmptyLine()
                     .AddCode(IfBuilder
                              .New()
                              .SetCondition(MethodCallBuilder
                                            .Inline()
                                            .SetMethodName(nameof(ReferenceEquals))
                                            .AddArgument("this")
                                            .AddArgument(other))
                              .AddCode("return true;"))
                     .AddEmptyLine()
                     .AddCode(IfBuilder
                              .New()
                              .SetCondition($"{other}.GetType() != GetType()")
                              .AddCode("return false;"))
                     .AddEmptyLine()
                     .AddCode(equalCondition));

            builder
            .AddMethod(nameof(GetHashCode))
            .SetPublic()
            .SetOverride()
            .SetReturnType(TypeNames.Int32)
            .AddCode(HashCodeBuilder
                     .New()
                     .AddProperties(properties));

            return(builder);
        }
Exemplo n.º 27
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);
        }
        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"));
        }
Exemplo n.º 29
0
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            INamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            methodBuilder.AddCode(
                AssignmentBuilder
                .New()
                .SetLefthandSide($"{TypeNames.EntityId} {_entityId}")
                .SetRighthandSide(
                    MethodCallBuilder
                    .Inline()
                    .SetMethodName(_extractId)
                    .AddArgument($"{_obj}.{nameof(Nullable<EntityId>.Value)}")));

            methodBuilder.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(_entityIds, nameof(List <object> .Add))
                .AddArgument(_entityId));

            methodBuilder.AddEmptyLine();

            if (namedTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                // If the type is an interface
                foreach (ObjectTypeDescriptor concreteType in interfaceTypeDescriptor.ImplementedBy)
                {
                    IfBuilder ifStatement = IfBuilder
                                            .New()
                                            .SetCondition(
                        MethodCallBuilder
                        .Inline()
                        .SetMethodName(
                            _entityId,
                            nameof(EntityId.Name),
                            nameof(string.Equals))
                        .AddArgument(concreteType.Name.AsStringToken())
                        .AddArgument(TypeNames.OrdinalStringComparison));

                    var entityTypeName = CreateEntityTypeName(concreteType.Name);

                    WriteEntityLoader(
                        ifStatement,
                        entityTypeName);

                    WritePropertyAssignments(
                        ifStatement,
                        concreteType.Properties);

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

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

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
            }
            else if (namedTypeDescriptor is ComplexTypeDescriptor complexTypeDescriptor)
            {
                WriteEntityLoader(methodBuilder, CreateEntityTypeName(namedTypeDescriptor.Name));
                WritePropertyAssignments(methodBuilder, complexTypeDescriptor.Properties);

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

            AddRequiredDeserializeMethods(namedTypeDescriptor, classBuilder, 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);
            }
        }