Exemplo n.º 1
0
        public static ISchema Load(
            IReadOnlyCollection <GraphQLFile> schemaFiles,
            bool strictValidation = true,
            bool noStore          = false)
        {
            if (schemaFiles is null)
            {
                throw new ArgumentNullException(nameof(schemaFiles));
            }

            var typeInfos = new TypeInfos();
            var lookup    = new Dictionary <ISyntaxNode, string>();

            IndexSyntaxNodes(schemaFiles, lookup);

            var builder = SchemaBuilder.New();

            builder.ModifyOptions(o => o.StrictValidation = strictValidation);

            var leafTypes            = new Dictionary <NameString, LeafTypeInfo>();
            var globalEntityPatterns = new List <SelectionSetNode>();
            var typeEntityPatterns   = new Dictionary <NameString, SelectionSetNode>();

            foreach (DocumentNode document in schemaFiles.Select(f => f.Document))
            {
                if (document.Definitions.Any(t => t is ITypeSystemExtensionNode))
                {
                    CollectScalarInfos(
                        document.Definitions.OfType <ScalarTypeExtensionNode>(),
                        leafTypes,
                        typeInfos);

                    CollectEnumInfos(
                        document.Definitions.OfType <EnumTypeExtensionNode>(),
                        leafTypes,
                        typeInfos);

                    if (!noStore)
                    {
                        CollectGlobalEntityPatterns(
                            document.Definitions.OfType <SchemaExtensionNode>(),
                            globalEntityPatterns);

                        CollectTypeEntityPatterns(
                            document.Definitions.OfType <ObjectTypeExtensionNode>(),
                            typeEntityPatterns);
                    }
                }
                else
                {
                    foreach (var scalar in document.Definitions.OfType <ScalarTypeDefinitionNode>())
                    {
                        if (!BuiltInScalarNames.IsBuiltInScalar(scalar.Name.Value))
                        {
                            builder.AddType(new AnyType(
                                                scalar.Name.Value,
                                                scalar.Description?.Value));
                        }
                    }

                    builder.AddDocument(document);
                }
            }

            AddDefaultScalarInfos(leafTypes);

            return(builder
                   .SetSchema(d => d.Extend().OnBeforeCreate(
                                  c => c.ContextData.Add(_typeInfosKey, typeInfos)))
                   .TryAddTypeInterceptor(
                       new LeafTypeInterceptor(leafTypes))
                   .TryAddTypeInterceptor(
                       new EntityTypeInterceptor(globalEntityPatterns, typeEntityPatterns))
                   .Use(_ => _ => throw new NotSupportedException())
                   .Create());
        }
Exemplo n.º 2
0
        private static ICode GenerateInternalMethodBody(
            CSharpSyntaxGeneratorSettings settings,
            DependencyInjectionDescriptor descriptor,
            TransportProfile profile)
        {
            var rootNamespace = descriptor.ClientDescriptor.RuntimeType.Namespace;

            var hasSubscriptions =
                descriptor.Operations.OfType <SubscriptionOperationDescriptor>().Any();
            var hasQueries =
                descriptor.Operations.OfType <QueryOperationDescriptor>().Any();
            var hasMutations =
                descriptor.Operations.OfType <MutationOperationDescriptor>().Any();

            CodeBlockBuilder body = CodeBlockBuilder
                                    .New()
                                    .AddCode(CreateBaseCode(settings));

            var generatedConnections = new HashSet <TransportType>();

            if (hasSubscriptions)
            {
                generatedConnections.Add(profile.Subscription);
                body.AddCode(
                    RegisterConnection(profile.Subscription, descriptor.Name));
            }

            if (hasQueries && !generatedConnections.Contains(profile.Query))
            {
                generatedConnections.Add(profile.Query);
                body.AddCode(RegisterConnection(profile.Query, descriptor.Name));
            }

            if (hasMutations && !generatedConnections.Contains(profile.Mutation))
            {
                generatedConnections.Add(profile.Mutation);
                body.AddCode(RegisterConnection(profile.Mutation, descriptor.Name));
            }

            body.AddEmptyLine();

            foreach (var typeDescriptor in descriptor.TypeDescriptors
                     .OfType <INamedTypeDescriptor>())
            {
                if (typeDescriptor.Kind == TypeKind.Entity && !typeDescriptor.IsInterface())
                {
                    INamedTypeDescriptor namedTypeDescriptor =
                        (INamedTypeDescriptor)typeDescriptor.NamedType();
                    NameString className = namedTypeDescriptor.ExtractMapperName();

                    var interfaceName =
                        TypeNames.IEntityMapper.WithGeneric(
                            namedTypeDescriptor.ExtractType().ToString(),
                            $"{rootNamespace}.{typeDescriptor.RuntimeType.Name}");

                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(interfaceName)
                    .AddGeneric($"{CreateStateNamespace(rootNamespace)}.{className}")
                    .AddArgument(_services);
                }
            }

            body.AddEmptyLine();

            foreach (var enumType in descriptor.EnumTypeDescriptor)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(CreateEnumParserName($"{rootNamespace}.{enumType.Name}"))
                .AddArgument(_services);
            }

            foreach (var serializer in _serializers)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(serializer)
                .AddArgument(_services);
            }

            RuntimeTypeInfo stringTypeInfo = new RuntimeTypeInfo(TypeNames.String);

            foreach (var scalar in descriptor.TypeDescriptors.OfType <ScalarTypeDescriptor>())
            {
                if (scalar.RuntimeType.Equals(stringTypeInfo) &&
                    scalar.SerializationType.Equals(stringTypeInfo) &&
                    !BuiltInScalarNames.IsBuiltInScalar(scalar.Name))
                {
                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(TypeNames.ISerializer)
                    .AddArgument(_services)
                    .AddArgument(MethodCallBuilder
                                 .Inline()
                                 .SetNew()
                                 .SetMethodName(TypeNames.StringSerializer)
                                 .AddArgument(scalar.Name.AsStringToken()));
                }
            }

            foreach (var inputTypeDescriptor in descriptor.TypeDescriptors
                     .Where(x => x.Kind is TypeKind.Input))
            {
                var formatter =
                    CreateInputValueFormatter(
                        (InputObjectTypeDescriptor)inputTypeDescriptor.NamedType());

                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric($"{rootNamespace}.{formatter}")
                .AddArgument(_services);
            }

            body.AddCode(RegisterSerializerResolver());

            body.AddEmptyLine();

            foreach (var operation in descriptor.Operations)
            {
                if (!(operation.ResultTypeReference is InterfaceTypeDescriptor typeDescriptor))
                {
                    continue;
                }

                TransportType operationKind = operation switch
                {
                    SubscriptionOperationDescriptor => profile.Subscription,
                    QueryOperationDescriptor => profile.Query,
                    MutationOperationDescriptor => profile.Mutation,
                    _ => throw ThrowHelper.DependencyInjection_InvalidOperationKind(operation)
                };

                string connectionKind = operationKind switch
                {
                    TransportType.Http => TypeNames.IHttpConnection,
                    TransportType.WebSocket => TypeNames.IWebSocketConnection,
                    TransportType.InMemory => TypeNames.IInMemoryConnection,
                    { } v => throw ThrowHelper.DependencyInjection_InvalidTransportType(v)
                };

                string operationName          = operation.Name;
                string fullName               = operation.RuntimeType.ToString();
                string operationInterfaceName = operation.InterfaceType.ToString();
                string resultInterface        = typeDescriptor.RuntimeType.ToString();

                // The factories are generated based on the concrete result type, which is the
                // only implementee of the result type interface.

                var factoryName =
                    CreateResultFactoryName(
                        typeDescriptor.ImplementedBy.First().RuntimeType.Name);

                var builderName = CreateResultBuilderName(operationName);
                body.AddCode(
                    RegisterOperation(
                        settings,
                        connectionKind,
                        fullName,
                        operationInterfaceName,
                        resultInterface,
                        $"{CreateStateNamespace(operation.RuntimeType.Namespace)}.{factoryName}",
                        $"{CreateStateNamespace(operation.RuntimeType.Namespace)}.{builderName}"));
            }

            if (settings.IsStoreEnabled())
            {
                body.AddCode(
                    MethodCallBuilder
                    .New()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(TypeNames.IEntityIdSerializer)
                    .AddGeneric(descriptor.EntityIdFactoryDescriptor.Type.ToString())
                    .AddArgument(_services));
            }

            body.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(descriptor.ClientDescriptor.RuntimeType.ToString())
                .AddArgument(_services));

            body.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(descriptor.ClientDescriptor.InterfaceType.ToString())
                .AddArgument(_services)
                .AddArgument(LambdaBuilder
                             .New()
                             .AddArgument(_sp)
                             .SetCode(MethodCallBuilder
                                      .Inline()
                                      .SetMethodName(TypeNames.GetRequiredService)
                                      .AddGeneric(descriptor.ClientDescriptor.RuntimeType.ToString())
                                      .AddArgument(_sp))));

            body.AddLine($"return {_services};");

            return(body);
        }
Exemplo n.º 3
0
        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 body = CodeBlockBuilder
                       .New()
                       .AddCode(_staticCode);

            if (hasSubscriptions)
            {
                body.AddCode(RegisterWebSocketConnection(descriptor.Name));
            }

            if (hasQueries || hasMutations)
            {
                body.AddCode(RegisterHttpConnection(descriptor.Name));
            }

            body.AddEmptyLine();

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

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

                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(interfaceName)
                    .AddGeneric(className)
                    .AddArgument(_services);
                }
            }

            body.AddEmptyLine();

            foreach (var enumType in descriptor.EnumTypeDescriptor)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(CreateEnumParserName(enumType.Name))
                .AddArgument(_services);
            }

            foreach (var serializer in _serializers)
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(serializer)
                .AddArgument(_services);
            }

            RuntimeTypeInfo stringTypeInfo = TypeInfos.From(TypeNames.String);

            foreach (var scalar in descriptor.TypeDescriptors.OfType <ScalarTypeDescriptor>())
            {
                if (scalar.RuntimeType.Equals(stringTypeInfo) &&
                    scalar.SerializationType.Equals(stringTypeInfo) &&
                    !BuiltInScalarNames.IsBuiltInScalar(scalar.Name))
                {
                    body.AddMethodCall()
                    .SetMethodName(TypeNames.AddSingleton)
                    .AddGeneric(TypeNames.ISerializer)
                    .AddArgument(_services)
                    .AddArgument(MethodCallBuilder
                                 .Inline()
                                 .SetNew()
                                 .SetMethodName(TypeNames.StringSerializer)
                                 .AddArgument(scalar.Name.AsStringToken()));
                }
            }

            foreach (var inputTypeDescriptor in descriptor.TypeDescriptors
                     .Where(x => x.Kind is TypeKind.InputType))
            {
                body.AddMethodCall()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(TypeNames.ISerializer)
                .AddGeneric(CreateInputValueFormatter(
                                (InputObjectTypeDescriptor)inputTypeDescriptor.NamedType()))
                .AddArgument(_services);
            }

            body.AddCode(RegisterSerializerResolver());

            body.AddEmptyLine();

            foreach (var operation in descriptor.Operations)
            {
                if (!(operation.ResultTypeReference is InterfaceTypeDescriptor typeDescriptor))
                {
                    continue;
                }

                string connectionKind = operation is SubscriptionOperationDescriptor
                    ? TypeNames.WebSocketConnection
                    : TypeNames.HttpConnection;
                NameString operationName      = operation.OperationName;
                NameString fullName           = operation.Name;
                NameString operationInterface = typeDescriptor.RuntimeType.Name;

                // The factories are generated based on the concrete result type, which is the
                // only implementee of the result type interface.

                var factoryName =
                    CreateResultFactoryName(
                        typeDescriptor.ImplementedBy.First().RuntimeType.Name);

                var builderName = CreateResultBuilderName(operationName);
                body.AddCode(
                    RegisterOperation(
                        connectionKind,
                        fullName,
                        operationInterface,
                        factoryName,
                        builderName));
            }

            body.AddCode(
                MethodCallBuilder
                .New()
                .SetMethodName(TypeNames.AddSingleton)
                .AddGeneric(descriptor.RuntimeType.Name)
                .AddArgument(_services));

            body.AddLine($"return {_services};");

            return(body);
        }