Ejemplo 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 GenerateIfForEachImplementedBy(
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            Func<ObjectTypeDescriptor, IfBuilder> generator)
        {
            if (!(complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) ||
                !interfaceTypeDescriptor.ImplementedBy.Any())
            {
                return;
            }

            IEnumerable<ObjectTypeDescriptor> dataTypes =
                interfaceTypeDescriptor.ImplementedBy.Where(x => x.IsData());

            IfBuilder ifChain = generator(dataTypes.First());

            foreach (ObjectTypeDescriptor objectTypeDescriptor in dataTypes.Skip(1))
            {
                ifChain.AddIfElse(generator(objectTypeDescriptor).SkipIndents());
            }

            ifChain.AddElse(ExceptionBuilder.New(TypeNames.NotSupportedException));

            method.AddCode(ifChain);
        }
        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));
        }
Ejemplo n.º 4
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));
        }
Ejemplo n.º 6
0
        private Rule GetStartRule(DeltinScript deltinScript)
        {
            var condition = new Condition(
                Element.Part <V_CountOf>(Path.GetVariable()),
                Operators.GreaterThan,
                0
                );

            Element eventPlayer    = new V_EventPlayer();
            Element eventPlayerPos = Element.Part <V_PositionOf>(eventPlayer);

            TranslateRule rule = new TranslateRule(deltinScript, Constants.INTERNAL_ELEMENT + "Pathfinder: Move", RuleEvent.OngoingPlayer);

            IfBuilder isBetween = new IfBuilder(rule.ActionSet,
                                                Element.Part <V_And>(
                                                    Element.Part <V_CountOf>(Path.GetVariable()) >= 2,
                                                    IsBetween(eventPlayerPos, NextPosition(eventPlayer), PositionAt(eventPlayer, 1))
                                                    )
                                                );

            isBetween.Setup();
            rule.ActionSet.AddAction(Next());
            isBetween.Finish();

            rule.ActionSet.AddAction(ArrayBuilder <Element> .Build
                                     (
                                         LastUpdate.SetVariable(new V_TotalTimeElapsed()),
                                         DistanceToNext.SetVariable(Element.Part <V_DistanceBetween>(Element.Part <V_PositionOf>(new V_EventPlayer()), NextPosition(new V_EventPlayer()))),
                                         // Element.Part<A_StartFacing>(
                                         //     new V_EventPlayer(),
                                         //     Element.Part<V_DirectionTowards>(
                                         //         new V_EyePosition(),
                                         //         NextPosition()
                                         //     ),
                                         //     new V_Number(700),
                                         //     EnumData.GetEnumValue(Relative.ToWorld),
                                         //     EnumData.GetEnumValue(FacingRev.DirectionAndTurnRate)
                                         // ),

                                         // Move to the next node.
                                         Element.Part <A_StartThrottleInDirection>(
                                             new V_EventPlayer(),
                                             Element.Part <V_DirectionTowards>(
                                                 new V_EyePosition(),
                                                 NextPosition(new V_EventPlayer()) // Because of ThrottleRev this will be reevaluated so 'Start Throttle In Direction' only needs to run once.
                                                 ),
                                             new V_Number(1),
                                             EnumData.GetEnumValue(Relative.ToWorld),
                                             EnumData.GetEnumValue(ThrottleBehavior.ReplaceExistingThrottle),
                                             EnumData.GetEnumValue(ThrottleRev.DirectionAndMagnitude)
                                             )
                                     ));

            var result = rule.GetRule();

            result.Conditions = new Condition[] { condition };
            return(result);
        }
Ejemplo n.º 7
0
        public static CodeBlockBuilder AddIf(
            this CodeBlockBuilder builder,
            Action <IfBuilder> configure)
        {
            var ifBuilder = IfBuilder.New();

            configure(ifBuilder);
            return(builder.AddCode(ifBuilder));
        }
Ejemplo n.º 8
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())));
 }
Ejemplo n.º 10
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);
            }
        }
Ejemplo n.º 12
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);
        }
 public BlockStatement Process(DecompilationContext context, BlockStatement body)
 {
     this.methodContext = context.get_MethodContext();
     V_0 = context.get_MethodContext().get_Method().get_Module().get_TypeSystem();
     this.logicalBuilderContext     = new LogicalFlowBuilderContext(context.get_MethodContext().get_ControlFlowGraph());
     this.cfgBlockSplitter          = new CFGBlockSplitter(this.logicalBuilderContext);
     this.conditionBuilder          = new ConditionBuilder(this.logicalBuilderContext, V_0);
     this.loopBuilder               = new LoopBuilder(this.logicalBuilderContext, V_0);
     this.switchBuilder             = new SwitchBuilder(this.logicalBuilderContext);
     this.ifBuilder                 = new IfBuilder(this.logicalBuilderContext, this.methodContext.get_Method().get_Module().get_TypeSystem());
     this.followNodeDeterminator    = new FollowNodeDeterminator(V_0);
     this.yieldGuardedBlocksBuilder = new YieldGuardedBlocksBuilder(this.logicalBuilderContext, context);
     this.GetMaxIndexOfBlock();
     this.InitializeTheBlock();
     this.guardedBlocksBuilder = new GuardedBlocksBuilder(this.logicalBuilderContext);
     context.get_MethodContext().set_LogicalConstructsTree(this.BuildLogicalConstructTree());
     context.get_MethodContext().set_LogicalConstructsContext(this.logicalBuilderContext);
     return(body);
 }
Ejemplo n.º 14
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);
        }
Ejemplo n.º 16
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())));
 }
Ejemplo n.º 18
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));
        }
        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)));
        }
Ejemplo n.º 20
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});")));
        }
        public BlockStatement Process(DecompilationContext context, BlockStatement body)
        {
            this.methodContext = context.MethodContext;
            TypeSystem typeSystem = context.MethodContext.Method.Module.TypeSystem;

            logicalBuilderContext     = new LogicalFlowBuilderContext(context.MethodContext.ControlFlowGraph);
            cfgBlockSplitter          = new CFGBlockSplitter(logicalBuilderContext);
            conditionBuilder          = new ConditionBuilder(logicalBuilderContext, typeSystem);
            loopBuilder               = new LoopBuilder(logicalBuilderContext, typeSystem);
            switchBuilder             = new SwitchBuilder(logicalBuilderContext);
            ifBuilder                 = new IfBuilder(logicalBuilderContext, methodContext.Method.Module.TypeSystem);
            followNodeDeterminator    = new FollowNodeDeterminator(typeSystem);
            yieldGuardedBlocksBuilder = new YieldGuardedBlocksBuilder(logicalBuilderContext, context);

            GetMaxIndexOfBlock();
            InitializeTheBlock();

            guardedBlocksBuilder = new GuardedBlocksBuilder(logicalBuilderContext);

            context.MethodContext.LogicalConstructsTree    = BuildLogicalConstructTree();
            context.MethodContext.LogicalConstructsContext = logicalBuilderContext;

            return(body);
        }
        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 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"));
        }
Ejemplo n.º 24
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);
        }
Ejemplo n.º 25
0
        protected override void GenerateContext()
        {
            var contextNamespace = ContextNamespace();
            var contextClassName = ContextClassName();

            Action <FileBuilder> generateContextInline = (FileBuilder fileBuilder) =>
            {
                if (!Options.OutputToSingleFile)
                {
                    var filePath = $"{Options.OutputDir}{Path.DirectorySeparatorChar}{Options.ContextName}.generated.cs";
                    fileBuilder.Path(filePath);
                }

                fileBuilder.Using("Microsoft.EntityFrameworkCore");

                fileBuilder.Namespace(contextNamespace, true, ns =>
                {
                    ns.Class(contextClassName, true, contextClass =>
                    {
                        contextClass.Partial(true).Inherits(Options.ContextBaseClassName);

                        TablesToGenerate.ForEach(table =>
                        {
                            var tableClassFullName = TableClassFullName(table);
                            var tableNamePlural    = Pluralize(table.Name);
                            contextClass.Property(tableNamePlural, true, dbSetProp =>
                            {
                                dbSetProp.Virtual(true).Type($"DbSet<{tableClassFullName}>");
                            });
                        });

                        // empty constructor.
                        contextClass.Constructor(c => c.Class(contextClass));

                        // constructor with options.
                        contextClass.Constructor(c => c
                                                 .Class(contextClass)
                                                 .Parameter(p => p.Type($"DbContextOptions<{contextClassName}>").Name("options"))
                                                 .BaseParameter("options")
                                                 );

                        // override On Configuring
                        contextClass.Method(m =>
                        {
                            m
                            .AccessModifier(AccessModifiers.Protected)
                            .Override(true)
                            .ReturnType("void")
                            .Name("OnConfiguring")
                            .Parameter(p => p.Type("DbContextOptionsBuilder").Name("optionsBuilder"));

                            if (Options.AddConnectionStringOnGenerate)
                            {
                                m.Add(() =>
                                {
                                    return(IfBuilder.Create()
                                           .RawCondition(c => c.Condition("!optionsBuilder.IsConfigured"))
                                           .Add(RawLineBuilder.Create(
                                                    "#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.")
                                                .NoEndOfLine())
                                           .Add(UseDatabaseEngineConnectionStringLine()));
                                });
                            }
                        });

                        // model creating.
                        contextClass.Method(m =>
                        {
                            m
                            .AccessModifier(AccessModifiers.Protected)
                            .Override(true)
                            .ReturnType("void")
                            .Name("OnModelCreating")
                            .Parameter(p => p.Type("ModelBuilder").Name("modelBuilder"));

                            TablesToGenerate.ForEach(table =>
                            {
                                AddFluentToMethod(m, table);
                            });

                            SequenceToGenerate.ForEach(sequence =>
                            {
                                var dataType   = DataTypeResolver.ResolveType(sequence);
                                var outputType = dataType.GetOutputType();
                                m.RawLine($"modelBuilder.HasSequence<{outputType}>(\"{sequence.Name}\").StartsAt({sequence.StartAt}).IncrementsBy({sequence.IncrementsBy})");
                            });
                        });
                    });
                });
            };

            if (Options.OutputToSingleFile)
            {
                GenerationContext.SingleFile(fb => generateContextInline(fb));
            }
            else
            {
                GenerationContext.FileIfPathIsSet(fb => generateContextInline(fb));
            }
        }
        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"));
        }
Ejemplo n.º 27
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))));
        }
        public void Get()
        {
            var firstNode = ClosestNodeToPosition(Nodes, position);

            Assign();

            current = actionSet.VarCollection.Assign("Dijkstra: Current", actionSet.IsGlobal, true);
            IndexReference distances = actionSet.VarCollection.Assign("Dijkstra: Distances", actionSet.IsGlobal, false);

            unvisited = actionSet.VarCollection.Assign("Dijkstra: Unvisited", actionSet.IsGlobal, false);
            IndexReference connectedSegments = actionSet.VarCollection.Assign("Dijkstra: Connected Segments", actionSet.IsGlobal, true);
            IndexReference neighborIndex     = actionSet.VarCollection.Assign("Dijkstra: Neighbor Index", actionSet.IsGlobal, true);
            IndexReference neighborDistance  = actionSet.VarCollection.Assign("Dijkstra: Distance", actionSet.IsGlobal, true);

            parentArray = actionSet.VarCollection.Assign("Dijkstra: Parent Array", actionSet.IsGlobal, false);

            // Set the current variable as the first node.
            actionSet.AddAction(current.SetVariable(firstNode));
            SetInitialDistances(actionSet, distances, (Element)current.GetVariable());
            SetInitialUnvisited(actionSet, Nodes, unvisited);

            WhileBuilder whileBuilder = new WhileBuilder(actionSet, LoopCondition());

            whileBuilder.Setup();

            // Get neighboring indexes
            actionSet.AddAction(connectedSegments.SetVariable(GetConnectedSegments(
                                                                  Nodes,
                                                                  Segments,
                                                                  (Element)current.GetVariable(),
                                                                  reversed
                                                                  )));

            // Loop through neighboring indexes
            ForeachBuilder forBuilder = new ForeachBuilder(actionSet, connectedSegments.GetVariable());

            forBuilder.Setup();

            actionSet.AddAction(ArrayBuilder <Element> .Build(
                                    // Get the index from the segment data
                                    neighborIndex.SetVariable(
                                        Element.TernaryConditional(
                                            new V_Compare(
                                                current.GetVariable(),
                                                Operators.NotEqual,
                                                Node1(forBuilder.IndexValue)
                                                ),
                                            Node1(forBuilder.IndexValue),
                                            Node2(forBuilder.IndexValue)
                                            )
                                        ),

                                    // Get the distance between the current and the neighbor index.
                                    neighborDistance.SetVariable(
                                        Element.Part <V_DistanceBetween>(
                                            Nodes[(Element)neighborIndex.GetVariable()],
                                            Nodes[(Element)current.GetVariable()]
                                            ) + ((Element)distances.GetVariable())[(Element)current.GetVariable()]
                                        )
                                    ));

            // Set the current neighbor's distance if the new distance is less than what it is now.
            IfBuilder ifBuilder = new IfBuilder(actionSet,
                                                (Element)neighborDistance.GetVariable()
                                                <
                                                WorkingDistance((Element)distances.GetVariable(), (Element)neighborIndex.GetVariable())
                                                );

            ifBuilder.Setup();

            actionSet.AddAction(distances.SetVariable((Element)neighborDistance.GetVariable(), null, (Element)neighborIndex.GetVariable()));
            actionSet.AddAction(parentArray.SetVariable((Element)current.GetVariable() + 1, null, (Element)neighborIndex.GetVariable()));

            ifBuilder.Finish();
            forBuilder.Finish();

            actionSet.AddAction(ArrayBuilder <Element> .Build(
                                    // Add the current to the visited array.
                                    unvisited.SetVariable(Element.Part <V_RemoveFromArray>(unvisited.GetVariable(), current.GetVariable())),

                                    // Set the current node as the smallest unvisited.
                                    current.SetVariable(LowestUnvisited(Nodes, (Element)distances.GetVariable(), (Element)unvisited.GetVariable()))
                                    ));

            whileBuilder.Finish();

            GetResult();

            actionSet.AddAction(ArrayBuilder <Element> .Build(
                                    current.SetVariable(-1),
                                    distances.SetVariable(-1),
                                    connectedSegments.SetVariable(-1),
                                    neighborIndex.SetVariable(-1),
                                    neighborDistance.SetVariable(-1),
                                    parentArray.SetVariable(-1)
                                    ));

            Reset();
        }
        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);
        }
        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);
        }