public TypeDescriptorModel(
     OutputTypeModel typeModel,
     NamedTypeDescriptor namedTypeDescriptor)
 {
     TypeModel           = typeModel;
     NamedTypeDescriptor = namedTypeDescriptor;
 }
        private void AddScalarTypeDeserializerMethod(
            MethodBuilder methodBuilder,
            NamedTypeDescriptor namedType)
        {
            string deserializeMethod = namedType.GraphQLTypeName?.Value switch
            {
                String => nameof(JsonElement.GetString),
                ID => nameof(JsonElement.GetString),
                Url => nameof(JsonElement.GetString),
                Uuid => nameof(JsonElement.GetString),
                DateTime => nameof(JsonElement.GetString),
                Date => nameof(JsonElement.GetString),
                TimeSpan => nameof(JsonElement.GetString),
                Boolean => nameof(JsonElement.GetBoolean),
                Byte => nameof(JsonElement.GetByte),
                Short => nameof(JsonElement.GetInt16),
                Int => nameof(JsonElement.GetInt32),
                Long => nameof(JsonElement.GetInt64),
                Float => nameof(JsonElement.GetDouble),
                Decimal => nameof(JsonElement.GetDecimal),
                ByteArray => nameof(JsonElement.GetBytesFromBase64),
                _ => "Get" + (namedType.SerializationType?.Split('.').Last() ??
                              namedType.Name.WithCapitalFirstChar())
            };

            methodBuilder.AddCode(
                $"return {namedType.Name.ToFieldName()}Parser.Parse({_objParamName}.Value" +
                $".{deserializeMethod}()!);");
        }
    }
 public InputTypeDescriptorModel(
     InputObjectTypeModel typeModel,
     NamedTypeDescriptor namedTypeDescriptor)
 {
     TypeModel           = typeModel;
     NamedTypeDescriptor = namedTypeDescriptor;
 }
        private static ITypeDescriptor BuildFieldType(
            this IType original,
            NamedTypeDescriptor namedTypeDescriptor)
        {
            if (original is NonNullType nnt)
            {
                return(new NonNullTypeDescriptor(
                           BuildFieldType(
                               nnt.Type,
                               namedTypeDescriptor)));
            }

            if (original is ListType lt)
            {
                return(new ListTypeDescriptor(
                           BuildFieldType(
                               lt.ElementType,
                               namedTypeDescriptor)));
            }

            if (original is INamedType)
            {
                return(namedTypeDescriptor);
            }

            throw new NotSupportedException();
        }
        /// <summary>
        /// Adds all required deserializers of the given type descriptors properties
        /// </summary>
        private void AddRequiredDeserializeMethods(
            NamedTypeDescriptor namedTypeDescriptor,
            ClassBuilder classBuilder,
            HashSet <string> processed)
        {
            if (namedTypeDescriptor.IsInterface)
            {
                foreach (var @class in namedTypeDescriptor.ImplementedBy)
                {
                    AddRequiredDeserializeMethods(@class, classBuilder, processed);
                }
            }
            else
            {
                foreach (var property in namedTypeDescriptor.Properties)
                {
                    AddDeserializeMethod(
                        property.Type,
                        classBuilder,
                        processed);

                    if (property.Type.NamedType() is NamedTypeDescriptor nt &&
                        !nt.IsLeafType())
                    {
                        AddRequiredDeserializeMethods(nt, classBuilder, processed);
                    }
                }
            }
        }
        public void IsMatch_Match(string name, string version)
        {
            // arrange
            var descriptor = new NamedTypeDescriptor <IInterfaceType>(
                typeof(ConcreteType), name, version);

            // act, assert
            descriptor.IsMatch(name, version).Should().BeTrue();
        }
예제 #7
0
        public void Ctor_TypeSet_DerivedType()
        {
            // arrange, act
            var descriptor = new NamedTypeDescriptor <IInterfaceType>(typeof(ConcreteType));

            // assert
            descriptor.Type.Should().Be(typeof(ConcreteType));
            descriptor.Name.Should().Be(NameVersionHelper.GetDefaultName(typeof(ConcreteType)));
            descriptor.Version.Should().Be(NameVersionHelper.GetDefaultVersion(typeof(ConcreteType)));
        }
 public static NameString ExtractMapperName(this NamedTypeDescriptor descriptor)
 {
     return(descriptor.Kind == TypeKind.EntityType
         ? EntityMapperNameFromGraphQLTypeName(
                descriptor.Name,
                descriptor.GraphQLTypeName !)
         : DataMapperNameFromGraphQLTypeName(
                descriptor.Name,
                descriptor.GraphQLTypeName !));
 }
 protected override void Generate(
     CodeWriter writer,
     ITypeDescriptor typeDescriptor,
     out string fileName)
 {
     NamedTypeDescriptor namedTypeDescriptor = typeDescriptor switch
     {
         NamedTypeDescriptor nullableNamedType => nullableNamedType,
         NonNullTypeDescriptor {
             InnerType : NamedTypeDescriptor namedType
         } => namedType,
예제 #10
0
        public void Ctor_NameSet_VersionSet()
        {
            // arrange, act
            var descriptor = new NamedTypeDescriptor <IInterfaceType>(
                typeof(ConcreteType), Name, Version);

            // assert
            descriptor.Type.Should().Be(typeof(ConcreteType));
            descriptor.Name.Should().Be(Name);
            descriptor.Version.Should().Be(Version);
        }
        private void AddBuildMethod(
            NamedTypeDescriptor resultNamedType,
            ClassBuilder classBuilder)
        {
            var responseParameterName = "response";

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

            buildMethod.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide(
                    $"({resultNamedType.Name} Result, " +
                    $"{ResultInfoNameFromTypeName(resultNamedType.ImplementedBy[0].Name)} " +
                    "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}<{resultNamedType.Name}>")
                .AddArgument("data?.Result")
                .AddArgument("data?.Info")
                .AddArgument(_resultDataFactoryFieldName)
                .AddArgument("null"));

            classBuilder.AddMethod(buildMethod);
        }
 public static bool ContainsEntity(this ITypeDescriptor typeDescriptor)
 {
     return(typeDescriptor switch
     {
         ListTypeDescriptor listTypeDescriptor =>
         listTypeDescriptor.InnerType.ContainsEntity(),
         NamedTypeDescriptor namedTypeDescriptor =>
         namedTypeDescriptor.Properties.Any(prop => prop.Type.IsEntityType() ||
                                            prop.Type.ContainsEntity()),
         NonNullTypeDescriptor nonNullTypeDescriptor =>
         nonNullTypeDescriptor.InnerType.ContainsEntity(),
         _ => throw new ArgumentOutOfRangeException(nameof(typeDescriptor))
     });
        public void IsMatch_NoMatch(string name, string version)
        {
            // arrange
            var descriptor = new NamedTypeDescriptor <IInterfaceType>(
                typeof(ConcreteType), name, version);

            // act, assert
            descriptor.IsMatch(name + "1", null).Should().BeFalse();
            descriptor.IsMatch(name.ToLower(), null).Should().BeFalse();
            descriptor.IsMatch(name.ToUpper(), null).Should().BeFalse();
            descriptor.IsMatch(name + "1", version + "1").Should().BeFalse();
            descriptor.IsMatch(name.ToLower(), version?.ToLower()).Should().BeFalse();
            descriptor.IsMatch(name.ToUpper(), version?.ToUpper()).Should().BeFalse();
        }
예제 #14
0
 private MethodCallBuilder GetMappingCall(
     NamedTypeDescriptor namedTypeDescriptor,
     string idName)
 {
     return(MethodCallBuilder.New()
            .SetMethodName(
                EntityMapperNameFromGraphQLTypeName(
                    namedTypeDescriptor.Name,
                    namedTypeDescriptor.GraphQLTypeName
                    ?? throw new ArgumentNullException("GraphQLTypeName"))
                .ToFieldName() + ".Map")
            .SetDetermineStatement(false)
            .AddArgument(
                $"{StoreParamName}.GetEntity<" +
                $"{EntityTypeNameFromGraphQLTypeName(namedTypeDescriptor.GraphQLTypeName)}>" +
                $"({idName}) ?? throw new {TypeNames.ArgumentNullException}()"));
 }
        /// <summary>
        /// Adds all required deserializers of the given type descriptors properties
        /// </summary>
        protected void AddRequiredMapMethods(
            string propAccess,
            NamedTypeDescriptor namedTypeDescriptor,
            ClassBuilder classBuilder,
            ConstructorBuilder constructorBuilder,
            HashSet <string> processed,
            bool stopAtEntityMappers = false)
        {
            if (namedTypeDescriptor.IsInterface)
            {
                foreach (var @class in namedTypeDescriptor.ImplementedBy)
                {
                    AddRequiredMapMethods(
                        propAccess,
                        @class,
                        classBuilder,
                        constructorBuilder,
                        processed);
                }
            }
            else
            {
                foreach (var property in namedTypeDescriptor.Properties)
                {
                    AddMapMethod(
                        propAccess,
                        property.Type,
                        classBuilder,
                        constructorBuilder,
                        processed);

                    if (property.Type.NamedType() is NamedTypeDescriptor nt &&
                        !nt.IsLeafType() && !stopAtEntityMappers)
                    {
                        AddRequiredMapMethods(
                            propAccess,
                            nt,
                            classBuilder,
                            constructorBuilder,
                            processed);
                    }
                }
            }
        }
 public static NameString ExtractTypeName(this NamedTypeDescriptor descriptor)
 {
     return(descriptor.IsEntityType()
         ? EntityTypeNameFromGraphQLTypeName(descriptor.GraphQLTypeName !)
         : descriptor.Name);
 }
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            var(classBuilder, constructorBuilder) = CreateClassBuilder(false);

            NamedTypeDescriptor descriptor = (NamedTypeDescriptor)typeDescriptor.NamedType();

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

            classBuilder
            .AddImplements(
                TypeNames.IEntityMapper
                .WithGeneric(descriptor.ExtractTypeName(), descriptor.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.Name)
                                      .AddParameter(
                ParameterBuilder.New()
                .SetType(
                    descriptor.Kind == TypeKind.EntityType
                                ? EntityTypeNameFromGraphQLTypeName(descriptor.GraphQLTypeName)
                                : descriptor.Name)
                .SetName(_entityParamName));

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

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

            mapMethod.AddCode(constructorCall);

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

            classBuilder.AddMethod(mapMethod);

            var processed = new HashSet <string>();

            AddRequiredMapMethods(
                _entityParamName,
                descriptor,
                classBuilder,
                constructorBuilder,
                processed);

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.Namespace)
            .AddType(classBuilder)
            .Build(writer);
        }
예제 #18
0
        private void AddBuildDataMethod(
            NamedTypeDescriptor resultNamedType,
            ClassBuilder classBuilder)
        {
            var objParameter    = "obj";
            var buildDataMethod = MethodBuilder.New()
                                  .SetAccessModifier(AccessModifier.Private)
                                  .SetName("BuildData")
                                  .SetReturnType(
                $"({resultNamedType.Name}, " +
                $"{ResultInfoNameFromTypeName(resultNamedType.ImplementedBy[0].Name)})")
                                  .AddParameter(
                ParameterBuilder.New()
                .SetType(TypeNames.JsonElement)
                .SetName(objParameter));

            var sessionName = "session";

            buildDataMethod.AddCode(
                CodeLineBuilder.New()
                .SetLine(
                    CodeBlockBuilder.New()
                    .AddCode(
                        $"using {TypeNames.IEntityUpdateSession} {sessionName} = ")
                    .AddCode(_entityStoreFieldName + ".BeginUpdate();")));

            var entityIdsName = "entityIds";

            buildDataMethod.AddCode(
                CodeLineBuilder.New()
                .SetLine(
                    $"var {entityIdsName} = new {TypeNames.HashSet}<{TypeNames.EntityId}>();"));

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

            var resultInfoConstructor = MethodCallBuilder.New()
                                        .SetMethodName(
                $"new {ResultInfoNameFromTypeName(resultNamedType.ImplementedBy[0].Name)}")
                                        .SetDetermineStatement(false);

            foreach (PropertyDescriptor property in resultNamedType.Properties)
            {
                if (property.Type.IsEntityType())
                {
                    resultInfoConstructor.AddArgument($"{property.Name.WithLowerFirstChar()}Id");
                }
                else
                {
                    resultInfoConstructor.AddArgument(BuildUpdateMethodCall(property, ""));
                }
            }

            resultInfoConstructor.AddArgument(entityIdsName);
            resultInfoConstructor.AddArgument(
                $"{sessionName}.{TypeNames.IEntityUpdateSession_Version}");

            buildDataMethod.AddEmptyLine();
            var resultInfoName = "resultInfo";

            buildDataMethod.AddCode(
                AssignmentBuilder.New()
                .SetLefthandSide($"var {resultInfoName}")
                .SetRighthandSide(resultInfoConstructor));

            buildDataMethod.AddEmptyLine();
            buildDataMethod.AddCode(
                $"return ({_resultDataFactoryFieldName}" +
                $".Create({resultInfoName}), {resultInfoName});");

            classBuilder.AddMethod(buildDataMethod);
        }
예제 #19
0
        private void AddDataTypeDeserializerMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            if (namedTypeDescriptor.IsInterface)
            {
                methodBuilder.AddCode(
                    "var typename = obj.Value.GetProperty(\"__typename\").GetString();");

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

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

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

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

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

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

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

                methodBuilder.AddCode(returnStatement);
            }

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

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

            var variableName = "returnValue";

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

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

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

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

                method.AddCode(ifChain);
            }

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

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


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

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

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

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

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

            if (isNonNullable)
            {
                nullabilityAdditive = "";
            }

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

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


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

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

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

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

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

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

                var ifCorrectType = IfBuilder.New();

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

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

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

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

                method.AddEmptyLine();
                ifCorrectType.AddCode(constructorCall);
                return(ifCorrectType);
            }
        }
        private ICode GenerateInternalMethodBody(DependencyInjectionDescriptor descriptor)
        {
            bool hasSubscriptions =
                descriptor.Operations.OfType <SubscriptionOperationDescriptor>().Any();
            bool hasQueries =
                descriptor.Operations.OfType <QueryOperationDescriptor>().Any();
            bool hasMutations =
                descriptor.Operations.OfType <MutationOperationDescriptor>().Any();

            var stringBuilder = new StringBuilder();
            var codeWriter    = new CodeWriter(stringBuilder);

            stringBuilder.AppendLine(_staticCode);

            codeWriter.WriteComment("register connections");

            if (hasSubscriptions)
            {
                stringBuilder.AppendLine(RegisterWebSocketConnection(descriptor.Name));
            }

            if (hasQueries || hasMutations)
            {
                stringBuilder.AppendLine(RegisterHttpConnection(descriptor.Name));
            }

            codeWriter.WriteComment("register mappers");
            codeWriter.WriteLine();

            foreach (var typeDescriptor in descriptor.TypeDescriptors)
            {
                if (typeDescriptor.Kind == TypeKind.EntityType && !typeDescriptor.IsInterface())
                {
                    NamedTypeDescriptor namedTypeDescriptor =
                        (NamedTypeDescriptor)typeDescriptor.NamedType();
                    NameString className = namedTypeDescriptor.ExtractMapperName();

                    var interfaceName =
                        TypeNames.IEntityMapper.WithGeneric(
                            namedTypeDescriptor.ExtractTypeName(),
                            typeDescriptor.Name);

                    AddSingleton(codeWriter, interfaceName, className);
                }
            }

            codeWriter.WriteLine();
            codeWriter.WriteComment("register serializers");
            codeWriter.WriteLine();

            foreach (var enumType in descriptor.EnumTypeDescriptor)
            {
                AddSingleton(
                    codeWriter,
                    TypeNames.ISerializer,
                    EnumParserNameFromEnumName(enumType.Name));
            }

            foreach (var serializer in _serializers)
            {
                AddSingleton(
                    codeWriter,
                    TypeNames.ISerializer,
                    serializer);
            }

            foreach (var inputTypeDescriptor in descriptor.TypeDescriptors
                     .Where(x => x.Kind is TypeKind.InputType))
            {
                AddSingleton(
                    codeWriter,
                    TypeNames.ISerializer,
                    InputValueFormatterFromType(
                        (NamedTypeDescriptor)inputTypeDescriptor.NamedType()));
            }

            RegisterSerializerResolver().Build(codeWriter);

            codeWriter.WriteLine();
            codeWriter.WriteComment("register operations");
            foreach (var operation in descriptor.Operations)
            {
                string connectionKind = operation is SubscriptionOperationDescriptor
                    ? TypeNames.WebSocketConnection
                    : TypeNames.HttpConnection;
                NameString operationName      = operation.OperationName;
                NameString fullName           = operation.Name;
                NameString operationInterface = operation.ResultTypeReference.Name;

                // The resulttype of the operation is a NamedTypeDescriptor, that is an Interface
                var resultType = operation.ResultTypeReference as NamedTypeDescriptor
                                 ?? throw new ArgumentException("ResultTypeReference");
                // The factories are generated based on the concrete result type, which is the
                // only implementee of the result type interface.
                var factoryName = ResultFactoryNameFromTypeName(resultType.ImplementedBy[0].Name);

                var builderName = ResultBuilderNameFromTypeName(operationName);
                stringBuilder.AppendLine(
                    RegisterOperation(
                        connectionKind,
                        descriptor.Name,
                        fullName,
                        operationInterface,
                        factoryName,
                        builderName));
            }

            stringBuilder.AppendLine(
                $"{TypeNames.AddSingleton.WithGeneric(descriptor.Name)}(services);");

            stringBuilder.AppendLine();
            stringBuilder.AppendLine("return services;");

            return(CodeBlockBuilder.From(stringBuilder));
        }
        private static void AddProperties(
            ClientModel model,
            IMapperContext context,
            Dictionary <NameString, TypeDescriptorModel> typeDescriptors,
            Dictionary <NameString, NamedTypeDescriptor> scalarTypeDescriptors)
        {
            foreach (TypeDescriptorModel typeDescriptorModel in typeDescriptors.Values.ToList())
            {
                var properties = new List <PropertyDescriptor>();

                foreach (var field in typeDescriptorModel.TypeModel.Fields)
                {
                    NamedTypeDescriptor?fieldType;
                    INamedType          namedType = field.Type.NamedType();

                    if (namedType.IsScalarType())
                    {
                        var scalarType = (ScalarType)namedType;

                        if (!scalarTypeDescriptors.TryGetValue(
                                scalarType.Name,
                                out fieldType))
                        {
                            string[] runtimeTypeName = scalarType.GetRuntimeType().Split('.');

                            fieldType = new NamedTypeDescriptor(
                                runtimeTypeName.Last(),
                                string.Join(
                                    ".",
                                    runtimeTypeName.Take(runtimeTypeName.Length - 1)),
                                false,
                                graphQLTypeName: scalarType.Name,
                                kind: TypeKind.LeafType);

                            scalarTypeDescriptors.Add(
                                scalarType.Name,
                                fieldType);
                        }
                    }
                    else if (namedType.IsEnumType())
                    {
                        var enumTypeModel = model.LeafTypes
                                            .OfType <EnumTypeModel>()
                                            .First(t => t.Type == namedType);

                        if (!scalarTypeDescriptors.TryGetValue(
                                namedType.Name,
                                out fieldType))
                        {
                            fieldType = new NamedTypeDescriptor(
                                enumTypeModel.Name,
                                context.Namespace,
                                false,
                                graphQLTypeName: namedType.Name,
                                serializationType: enumTypeModel.Type.GetSerializationType(),
                                kind: TypeKind.LeafType,
                                isEnum: true);

                            scalarTypeDescriptors.Add(
                                enumTypeModel.Name,
                                fieldType);
                        }
                    }
                    else
                    {
                        fieldType = GetFieldTypeDescriptor(
                            model,
                            field.SyntaxNode,
                            field.Type.NamedType(),
                            typeDescriptors);
                    }

                    properties.Add(
                        new PropertyDescriptor(
                            field.Name,
                            BuildFieldType(
                                field.Type,
                                fieldType)));
                }

                typeDescriptorModel.NamedTypeDescriptor.Complete(properties);
            }
        }
예제 #24
0
        protected override void Generate(
            CodeWriter writer,
            ITypeDescriptor typeDescriptor,
            out string fileName)
        {
            NamedTypeDescriptor descriptor =
                typeDescriptor as NamedTypeDescriptor ??
                throw new InvalidOperationException();

            var(classBuilder, constructorBuilder) = CreateClassBuilder();

            fileName = ResultFactoryNameFromTypeName(descriptor.Name);
            classBuilder
            .SetName(fileName)
            .AddImplements($"{TypeNames.IOperationResultDataFactory}<{descriptor.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.Name)
                               .AddParameter("dataInfo", b => b.SetType(TypeNames.IOperationResultDataInfo));

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

            var ifHasCorrectType = IfBuilder.New()
                                   .SetCondition($"dataInfo is {ResultInfoNameFromTypeName(descriptor.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}(\"" +
                $"{ResultInfoNameFromTypeName(descriptor.Name)} expected.\");");

            classBuilder.AddMethod(createMethod);

            var processed = new HashSet <string>();

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

            CodeFileBuilder
            .New()
            .SetNamespace(descriptor.Namespace)
            .AddType(classBuilder)
            .Build(writer);
        }
        private void AddUpdateEntityMethod(
            ClassBuilder classBuilder,
            MethodBuilder methodBuilder,
            NamedTypeDescriptor namedTypeDescriptor,
            HashSet <string> processed)
        {
            var entityIdVarName = "entityId";

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

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

            var entityVarName = "entity";

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

                    var entityTypeName =
                        EntityTypeNameFromGraphQLTypeName(concreteType.GraphQLTypeName);

                    WriteEntityLoader(
                        ifStatement,
                        entityTypeName,
                        entityVarName,
                        entityIdVarName);

                    WritePropertyAssignments(
                        ifStatement,
                        concreteType.Properties,
                        entityVarName);

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

                methodBuilder.AddEmptyLine();
                methodBuilder.AddCode($"throw new {TypeNames.NotSupportedException}();");
            }
            else
            {
                WriteEntityLoader(
                    methodBuilder,
                    EntityTypeNameFromGraphQLTypeName(namedTypeDescriptor.GraphQLTypeName),
                    entityVarName,
                    entityIdVarName);

                WritePropertyAssignments(
                    methodBuilder,
                    namedTypeDescriptor.Properties,
                    entityVarName);

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

            AddRequiredDeserializeMethods(
                namedTypeDescriptor,
                classBuilder,
                processed);
        }