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 AddDataTypeDeserializerMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed)
        {
            if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                AddInterfaceDataTypeDeserializerToMethod(methodBuilder, interfaceTypeDescriptor);
            }
            else
            {
                MethodCallBuilder returnStatement = MethodCallBuilder
                                                    .New()
                                                    .SetReturn()
                                                    .SetNew()
                                                    .SetMethodName(complexTypeDescriptor.Name);

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

                methodBuilder.AddCode(returnStatement);
            }

            AddRequiredDeserializeMethods(complexTypeDescriptor, classBuilder, processed);
        }
コード例 #3
0
        private void GenerateIfForEachImplementedBy(
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            Func <ObjectTypeDescriptor, IfBuilder> generator)
        {
            if (!(complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor) ||
                !interfaceTypeDescriptor.ImplementedBy.Any())
            {
                return;
            }

            var ifChain = generator(interfaceTypeDescriptor.ImplementedBy.First());

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

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

            method.AddCode(ifChain);
        }
コード例 #4
0
        private void AddComplexDataHandler(
            CSharpSyntaxGeneratorSettings settings,
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            if (complexTypeDescriptor.ParentRuntimeType is null)
            {
                throw new InvalidOperationException();
            }

            method
            .AddParameter(_dataParameterName)
            .SetType(complexTypeDescriptor.ParentRuntimeType
                     .ToString()
                     .MakeNullable(!isNonNullable))
            .SetName(_dataParameterName);

            if (settings.IsStoreEnabled())
            {
                method
                .AddParameter(_snapshot)
                .SetType(TypeNames.IEntityStoreSnapshot);
            }

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

            const string returnValue = nameof(returnValue);

            method.AddCode($"{complexTypeDescriptor.RuntimeType.Name}? {returnValue};");
            method.AddEmptyLine();

            GenerateIfForEachImplementedBy(
                method,
                complexTypeDescriptor,
                o => GenerateComplexDataInterfaceIfClause(settings, o, returnValue));

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

            AddRequiredMapMethods(
                settings,
                _dataParameterName,
                complexTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
コード例 #5
0
        private void AddEntityHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            method
            .AddParameter(_entityId)
            .SetType(TypeNames.EntityId.MakeNullable(!isNonNullable));
            method
            .AddParameter(_snapshot)
            .SetType(TypeNames.IEntityStoreSnapshot);

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

            if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                foreach (ObjectTypeDescriptor implementee in interfaceTypeDescriptor.ImplementedBy
                         .Where(x => x.IsEntity()))
                {
                    NameString dataMapperName =
                        CreateEntityMapperName(implementee.RuntimeType.Name, implementee.Name);

                    if (processed.Add(dataMapperName))
                    {
                        var dataMapperType =
                            TypeNames.IEntityMapper.WithGeneric(
                                CreateEntityType(
                                    implementee.Name,
                                    implementee.RuntimeType.NamespaceWithoutGlobal)
                                .ToString(),
                                implementee.RuntimeType.Name);

                        AddConstructorAssignedField(
                            dataMapperType,
                            GetFieldName(dataMapperName),
                            GetParameterName(dataMapperName),
                            classBuilder,
                            constructorBuilder);
                    }

                    method.AddCode(GenerateEntityHandlerIfClause(implementee, isNonNullable));
                }
            }

            method.AddCode(ExceptionBuilder.New(TypeNames.NotSupportedException));
        }
コード例 #6
0
 public static bool ContainsEntity(this ITypeDescriptor typeDescriptor)
 {
     return(typeDescriptor switch
     {
         ListTypeDescriptor listTypeDescriptor =>
         listTypeDescriptor.InnerType.ContainsEntity(),
         ComplexTypeDescriptor namedTypeDescriptor =>
         namedTypeDescriptor.Properties
         .Any(prop => prop.Type.IsEntityType() || prop.Type.ContainsEntity()),
         NonNullTypeDescriptor nonNullTypeDescriptor =>
         nonNullTypeDescriptor.InnerType.ContainsEntity(),
         _ => false
     });
コード例 #7
0
        /// <summary>
        /// Adds all required deserializers of the given type descriptors properties
        /// </summary>
        protected void AddRequiredMapMethods(
            CSharpSyntaxGeneratorSettings settings,
            string propAccess,
            ComplexTypeDescriptor typeDescriptor,
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            HashSet <string> processed,
            bool stopAtEntityMappers = false)
        {
            if (typeDescriptor is InterfaceTypeDescriptor interfaceType)
            {
                foreach (var objectTypeDescriptor in interfaceType.ImplementedBy)
                {
                    AddRequiredMapMethods(
                        settings,
                        propAccess,
                        objectTypeDescriptor,
                        classBuilder,
                        constructorBuilder,
                        processed);
                }
            }
            else
            {
                foreach (var property in typeDescriptor.Properties)
                {
                    AddMapMethod(
                        settings,
                        propAccess,
                        property.Type,
                        classBuilder,
                        constructorBuilder,
                        processed);

                    if (property.Type.NamedType() is ComplexTypeDescriptor ct &&
                        !ct.IsLeafType() && !stopAtEntityMappers)
                    {
                        AddRequiredMapMethods(
                            settings,
                            propAccess,
                            ct,
                            classBuilder,
                            constructorBuilder,
                            processed);
                    }
                }
            }
        }
コード例 #8
0
 private MethodCallBuilder GetMappingCall(
     ComplexTypeDescriptor complexTypeDescriptor,
     string idName)
 {
     return(MethodCallBuilder.New()
            .SetMethodName(
                GetFieldName(
                    CreateEntityMapperName(
                        complexTypeDescriptor.RuntimeType.Name,
                        complexTypeDescriptor.Name)) +
                ".Map")
            .SetDetermineStatement(false)
            .AddArgument(
                $"{StoreParamName}.GetEntity<" +
                $"{CreateEntityTypeName(complexTypeDescriptor.Name)}>" +
                $"({idName}) ?? throw new {TypeNames.ArgumentNullException}()"));
 }
コード例 #9
0
        private void AddEntityOrDataTypeDeserializerMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed)
        {
            if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                AddEntityDataTypeDeserializerToMethod(methodBuilder, interfaceTypeDescriptor);
            }
            else
            {
                throw new InvalidOperationException();
            }

            AddRequiredDeserializeMethods(complexTypeDescriptor, classBuilder, processed);
        }
コード例 #10
0
        private void AddComplexDataHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            if (complexTypeDescriptor.ParentRuntimeType is null)
            {
                throw new InvalidOperationException();
            }

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

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

            var variableName = "returnValue";

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

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

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

            AddRequiredMapMethods(
                _dataParameterName,
                complexTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
コード例 #11
0
        private void AddDataHandler(
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            method
            .AddParameter(_dataParameterName)
            .SetType(namedTypeDescriptor.ParentRuntimeType !
                     .ToString()
                     .MakeNullable(!isNonNullable));
            method
            .AddParameter(_snapshot)
            .SetType(TypeNames.IEntityStoreSnapshot);

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

            const string returnValue = nameof(returnValue);

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

            GenerateIfForEachImplementedBy(
                method,
                namedTypeDescriptor,
                o => GenerateDataInterfaceIfClause(o, isNonNullable, returnValue));

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

            AddRequiredMapMethods(
                _dataParameterName,
                namedTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }
コード例 #12
0
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            ComplexTypeDescriptor complexTypeDescriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result entity mapper can only be generated for complex types");

            var(classBuilder, constructorBuilder) = CreateClassBuilder();

            var className = CreateResultInfoName(complexTypeDescriptor.RuntimeType.Name);

            fileName = className;

            classBuilder
            .AddImplements(TypeNames.IOperationResultDataInfo)
            .SetName(fileName);

            constructorBuilder
            .SetTypeName(complexTypeDescriptor.RuntimeType.Name)
            .SetAccessModifier(AccessModifier.Public);


            foreach (var prop in complexTypeDescriptor.Properties)
            {
                var propTypeBuilder = prop.Type.ToEntityIdBuilder();

                // Add Property to class
                classBuilder.AddProperty(
                    prop.Name,
                    x => x.SetType(propTypeBuilder).SetAccessModifier(AccessModifier.Public));

                // Add initialization of property to the constructor
                var paramName = GetParameterName(prop.Name);
                ParameterBuilder parameterBuilder = ParameterBuilder.New()
                                                    .SetName(paramName)
                                                    .SetType(propTypeBuilder);

                constructorBuilder.AddParameter(parameterBuilder);
                constructorBuilder.AddCode(prop.Name + " = " + paramName + ";");
            }

            classBuilder.AddProperty(
                "EntityIds",
                x => x.SetType(TypeNames.IReadOnlyCollection.WithGeneric(TypeNames.EntityId))
                .AsLambda("_entityIds"));

            classBuilder.AddProperty("Version", x => x.SetType("ulong").AsLambda("_version"));

            AddConstructorAssignedField(
                $"{TypeNames.IReadOnlyCollection}<{TypeNames.EntityId}>",
                "_entityIds",
                classBuilder,
                constructorBuilder);

            AddConstructorAssignedField(
                "ulong",
                "_version",
                classBuilder,
                constructorBuilder,
                true);


            // WithVersion

            classBuilder.AddMethod(
                "WithVersion",
                x => x.SetAccessModifier(AccessModifier.Public)
                .SetReturnType(TypeNames.IOperationResultDataInfo)
                .AddParameter(ParameterBuilder.New()
                              .SetType("ulong")
                              .SetName("version"))
                .AddCode(MethodCallBuilder.New()
                         .SetPrefix("return new ")
                         .SetMethodName(className)
                         .AddArgumentRange(
                             complexTypeDescriptor.Properties.Select(x => x.Name.Value))
                         .AddArgument("_entityIds")
                         .AddArgument("_version")));


            CodeFileBuilder
            .New()
            .SetNamespace(complexTypeDescriptor.RuntimeType.NamespaceWithoutGlobal)
            .AddType(classBuilder)
            .Build(writer);
        }
コード例 #13
0
        private void AddDataTypeDeserializerMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed)
        {
            if (complexTypeDescriptor is InterfaceTypeDescriptor interfaceTypeDescriptor)
            {
                methodBuilder.AddCode(
                    "var typename = obj.Value.GetProperty(\"__typename\").GetString();");

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

                    var dataTypeName = $"{concreteType.RuntimeType.Namespace}.State."
                                       + CreateDataTypeName(concreteType.Name);

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

                    returnStatement.AddArgument("typename");
                    foreach (PropertyDescriptor property in concreteType.Properties)
                    {
                        returnStatement.AddArgument(
                            CodeBlockBuilder.New()
                            .AddCode($"{GetParameterName(property.Name)}: ")
                            .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(complexTypeDescriptor.Name);

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

                methodBuilder.AddCode(returnStatement);
            }

            AddRequiredDeserializeMethods(
                complexTypeDescriptor,
                classBuilder,
                processed);
        }
コード例 #14
0
        protected override void Generate(ITypeDescriptor typeDescriptor,
                                         CSharpSyntaxGeneratorSettings settings,
                                         CodeWriter writer,
                                         out string fileName,
                                         out string?path,
                                         out string ns)
        {
            ComplexTypeDescriptor complexTypeDescriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result entity mapper can only be generated for complex types");

            var className = CreateResultInfoName(complexTypeDescriptor.RuntimeType.Name);

            fileName = className;
            path     = State;
            ns       = CreateStateNamespace(complexTypeDescriptor.RuntimeType.NamespaceWithoutGlobal);

            ClassBuilder classBuilder = ClassBuilder
                                        .New()
                                        .AddImplements(TypeNames.IOperationResultDataInfo)
                                        .SetName(fileName);

            ConstructorBuilder constructorBuilder = classBuilder
                                                    .AddConstructor()
                                                    .SetTypeName(complexTypeDescriptor.RuntimeType.Name);

            foreach (var prop in complexTypeDescriptor.Properties)
            {
                TypeReferenceBuilder propTypeBuilder = prop.Type.ToStateTypeReference();

                // Add Property to class
                classBuilder
                .AddProperty(prop.Name)
                .SetComment(prop.Description)
                .SetType(propTypeBuilder)
                .SetPublic();

                // Add initialization of property to the constructor
                var paramName = GetParameterName(prop.Name);
                constructorBuilder.AddParameter(paramName).SetType(propTypeBuilder);
                constructorBuilder.AddCode(
                    AssignmentBuilder
                    .New()
                    .SetLefthandSide(prop.Name)
                    .SetRighthandSide(paramName));
            }

            classBuilder
            .AddProperty("EntityIds")
            .SetType(TypeNames.IReadOnlyCollection.WithGeneric(TypeNames.EntityId))
            .AsLambda(settings.IsStoreEnabled()
                    ? CodeInlineBuilder.From(_entityIds)
                    : MethodCallBuilder.Inline()
                      .SetMethodName(TypeNames.Array, "Empty")
                      .AddGeneric(TypeNames.EntityId));

            classBuilder
            .AddProperty("Version")
            .SetType(TypeNames.UInt64)
            .AsLambda(settings.IsStoreEnabled() ? _version : "0");

            if (settings.IsStoreEnabled())
            {
                AddConstructorAssignedField(
                    TypeNames.IReadOnlyCollection.WithGeneric(TypeNames.EntityId),
                    _entityIds,
                    entityIds,
                    classBuilder,
                    constructorBuilder);

                AddConstructorAssignedField(
                    TypeNames.UInt64,
                    _version,
                    version,
                    classBuilder,
                    constructorBuilder,
                    true);
            }

            // WithVersion
            classBuilder
            .AddMethod("WithVersion")
            .SetAccessModifier(AccessModifier.Public)
            .SetReturnType(TypeNames.IOperationResultDataInfo)
            .AddParameter(version, x => x.SetType(TypeNames.UInt64))
            .AddCode(MethodCallBuilder
                     .New()
                     .SetReturn()
                     .SetNew()
                     .SetMethodName(className)
                     .AddArgumentRange(
                         complexTypeDescriptor.Properties.Select(x => x.Name.Value))
                     .If(settings.IsStoreEnabled(),
                         x => x.AddArgument(_entityIds).AddArgument(version)));

            classBuilder.Build(writer);
        }
コード例 #15
0
        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);
        }
コード例 #16
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");

            fileName = CreateResultFactoryName(descriptor.RuntimeType.Name);

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

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

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

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

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

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

            classBuilder
            .AddMethod("Create")
            .SetAccessModifier(AccessModifier.Public)
            .SetReturnType(descriptor.RuntimeType.Name)
            .AddParameter(_dataInfo, b => b.SetType(TypeNames.IOperationResultDataInfo))
            .AddCode(ifHasCorrectType)
            .AddEmptyLine()
            .AddCode(
                ExceptionBuilder
                .New(TypeNames.ArgumentException)
                .AddArgument(
                    $"\"{CreateResultInfoName(descriptor.RuntimeType.Name)} expected.\""));

            var processed = new HashSet <string>();

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

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal)
            .AddType(classBuilder)
            .Build(writer);
        }
コード例 #17
0
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            var(classBuilder, constructorBuilder) = CreateClassBuilder(false);

            ComplexTypeDescriptor descriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result entity mapper can only be generated for complex types");

            // Setup class
            fileName = descriptor.ExtractMapperName();

            classBuilder
            .AddImplements(
                TypeNames.IEntityMapper
                .WithGeneric(descriptor.ExtractTypeName(), descriptor.RuntimeType.Name))
            .SetName(fileName);

            constructorBuilder.SetTypeName(descriptor.Name);

            if (descriptor.ContainsEntity())
            {
                AddConstructorAssignedField(
                    TypeNames.IEntityStore,
                    StoreFieldName,
                    classBuilder,
                    constructorBuilder);
            }

            // Define map method
            MethodBuilder mapMethod = MethodBuilder.New()
                                      .SetName(_mapMethodName)
                                      .SetAccessModifier(AccessModifier.Public)
                                      .SetReturnType(descriptor.RuntimeType.Name)
                                      .AddParameter(
                ParameterBuilder.New()
                .SetType(
                    descriptor.Kind == TypeKind.EntityType
                                ? CreateEntityTypeName(descriptor.Name)
                                : descriptor.Name)
                .SetName(_entityParamName));

            var constructorCall =
                MethodCallBuilder
                .New()
                .SetMethodName($"return new {descriptor.RuntimeType.Name}");

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

            mapMethod.AddCode(constructorCall);

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

            classBuilder.AddMethod(mapMethod);

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

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.RuntimeType.NamespaceWithoutGlobal)
            .AddType(classBuilder)
            .Build(writer);
        }
コード例 #18
0
        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);
        }
コード例 #19
0
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            ComplexTypeDescriptor complexTypeDescriptor =
                typeDescriptor as ComplexTypeDescriptor ??
                throw new InvalidOperationException(
                          "A result entity mapper can only be generated for complex types");

            var className = CreateResultInfoName(complexTypeDescriptor.RuntimeType.Name);

            fileName = className;

            ClassBuilder classBuilder = ClassBuilder
                                        .New()
                                        .AddImplements(TypeNames.IOperationResultDataInfo)
                                        .SetName(fileName);

            ConstructorBuilder constructorBuilder = classBuilder
                                                    .AddConstructor()
                                                    .SetTypeName(complexTypeDescriptor.RuntimeType.Name);

            foreach (var prop in complexTypeDescriptor.Properties)
            {
                TypeReferenceBuilder propTypeBuilder = prop.Type.ToEntityIdBuilder();

                // Add Property to class
                classBuilder
                .AddProperty(prop.Name)
                .SetType(propTypeBuilder)
                .SetPublic();

                // Add initialization of property to the constructor
                var paramName = GetParameterName(prop.Name);
                constructorBuilder.AddParameter(paramName).SetType(propTypeBuilder);
                constructorBuilder.AddCode(
                    AssignmentBuilder
                    .New()
                    .SetLefthandSide(prop.Name)
                    .SetRighthandSide(paramName));
            }

            classBuilder
            .AddProperty("EntityIds")
            .SetType(TypeNames.IReadOnlyCollection.WithGeneric(TypeNames.EntityId))
            .AsLambda(_entityIds);

            classBuilder
            .AddProperty("Version")
            .SetType(TypeNames.UInt64)
            .AsLambda(_version);

            AddConstructorAssignedField(
                TypeNames.IReadOnlyCollection.WithGeneric(TypeNames.EntityId),
                _entityIds,
                classBuilder,
                constructorBuilder);

            AddConstructorAssignedField(
                TypeNames.UInt64,
                _version,
                classBuilder,
                constructorBuilder,
                true);


            // WithVersion
            const string version = nameof(version);

            classBuilder
            .AddMethod("WithVersion")
            .SetAccessModifier(AccessModifier.Public)
            .SetReturnType(TypeNames.IOperationResultDataInfo)
            .AddParameter(version, x => x.SetType(TypeNames.UInt64))
            .AddCode(MethodCallBuilder
                     .New()
                     .SetReturn()
                     .SetNew()
                     .SetMethodName(className)
                     .AddArgumentRange(
                         complexTypeDescriptor.Properties.Select(x => x.Name.Value))
                     .AddArgument(_entityIds)
                     .AddArgument(version));

            CodeFileBuilder
            .New()
            .SetNamespace(complexTypeDescriptor.RuntimeType.NamespaceWithoutGlobal)
            .AddType(classBuilder)
            .Build(writer);
        }
コード例 #20
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);
        }
        private void AddEntityOrUnionDataHandler(
            CSharpSyntaxGeneratorSettings settings,
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            MethodBuilder method,
            ComplexTypeDescriptor complexTypeDescriptor,
            HashSet <string> processed,
            bool isNonNullable)
        {
            method
            .AddParameter(_dataParameterName)
            .SetType(TypeNames.EntityIdOrData.MakeNullable(!isNonNullable))
            .SetName(_dataParameterName);

            method
            .AddParameter(_snapshot)
            .SetType(TypeNames.IEntityStoreSnapshot)
            .SetName(_snapshot);

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

            var dataHandlerMethodName =
                MapMethodNameFromTypeName(complexTypeDescriptor) + "Entity";

            MethodBuilder complexDataHandler = MethodBuilder
                                               .New()
                                               .SetReturnType(
                complexTypeDescriptor.RuntimeType.ToString().MakeNullable(!isNonNullable))
                                               .SetName(dataHandlerMethodName);

            AddComplexDataHandler(settings,
                                  classBuilder,
                                  constructorBuilder,
                                  complexDataHandler,
                                  complexTypeDescriptor,
                                  processed,
                                  isNonNullable);

            classBuilder.AddMethod(complexDataHandler);

            var entityDataHandlerMethodName =
                MapMethodNameFromTypeName(complexTypeDescriptor) + "Data";

            MethodBuilder entityDataHandler = MethodBuilder
                                              .New()
                                              .SetReturnType(
                complexTypeDescriptor.RuntimeType.ToString().MakeNullable(!isNonNullable))
                                              .SetName(entityDataHandlerMethodName);

            AddEntityHandler(
                classBuilder,
                constructorBuilder,
                entityDataHandler,
                complexTypeDescriptor,
                processed,
                isNonNullable);

            classBuilder.AddMethod(entityDataHandler);

            method.AddEmptyLine();

            var parameterName = isNonNullable ? _dataParameterName : $"{_dataParameterName}.Value";

            IfBuilder ifBuilder = IfBuilder
                                  .New()
                                  .SetCondition($"{parameterName}.EntityId is {{ }} id")
                                  .AddCode(MethodCallBuilder
                                           .New()
                                           .SetReturn()
                                           .SetMethodName(entityDataHandlerMethodName)
                                           .AddArgument("id")
                                           .AddArgument(_snapshot))
                                  .AddIfElse(IfBuilder
                                             .New()
                                             .SetCondition(
                                                 $"{parameterName}.Data is {complexTypeDescriptor.ParentRuntimeType!} d")
                                             .AddCode(MethodCallBuilder
                                                      .New()
                                                      .SetReturn()
                                                      .SetMethodName(dataHandlerMethodName)
                                                      .AddArgument("d")
                                                      .AddArgument(_snapshot)))
                                  .AddElse(ExceptionBuilder.New(TypeNames.ArgumentOutOfRangeException));

            method.AddCode(ifBuilder);

            AddRequiredMapMethods(
                settings,
                _dataParameterName,
                complexTypeDescriptor,
                classBuilder,
                constructorBuilder,
                processed);
        }