示例#1
0
        public ScalarFieldTypeDescription DefaultScalarFieldTypeMapping(GraphQlType baseType, GraphQlTypeBase valueType, string valueName)
        {
            valueName = NamingHelper.ToPascalCase(valueName);

            if (valueName == "From" || valueName == "ValidFrom" || valueName == "To" || valueName == "ValidTo" ||
                valueName == "CreatedAt" || valueName == "UpdatedAt" || valueName == "ModifiedAt" || valueName == "DeletedAt" ||
                valueName.EndsWith("Timestamp"))
            {
                return new ScalarFieldTypeDescription {
                           NetTypeName = "DateTimeOffset?"
                }
            }
            ;

            valueType = (valueType as GraphQlFieldType)?.UnwrapIfNonNull() ?? valueType;
            if (valueType.Kind == GraphQlTypeKind.Enum)
            {
                return new ScalarFieldTypeDescription {
                           NetTypeName = NamingHelper.ToPascalCase(valueType.Name) + "?"
                }
            }
            ;

            var dataType = valueType.Name == GraphQlTypeBase.GraphQlTypeScalarString ? "string" : "object";

            return(new ScalarFieldTypeDescription {
                NetTypeName = GraphQlGenerator.AddQuestionMarkIfNullableReferencesEnabled(this, dataType)
            });
        }
示例#2
0
        public static string DefaultScalarFieldTypeMapping(GraphQlType baseType, GraphQlTypeBase valueType, string valueName)
        {
            valueName = NamingHelper.ToPascalCase(valueName);
            if (valueName == "From" || valueName == "ValidFrom" || valueName == "To" || valueName == "ValidTo" ||
                valueName == "CreatedAt" || valueName == "UpdatedAt" || valueName == "ModifiedAt" || valueName == "DeletedAt" ||
                valueName.EndsWith("Timestamp"))
            {
                return("DateTimeOffset?");
            }

            var dataType = valueType.Name == GraphQlTypeBase.GraphQlTypeScalarString ? "string" : "object";

            return(GraphQlGenerator.AddQuestionMarkIfNullableReferencesEnabled(dataType));
        }
示例#3
0
        private static void GenerateGraphQlClient(string url, string token, string targetFileName, string @namespace)
        {
            var schema = GraphQlGenerator.RetrieveSchema(url, token).Result;

            var builder = new StringBuilder();

            GraphQlGenerator.GenerateQueryBuilder(schema, builder);

            builder.AppendLine();
            builder.AppendLine();

            GraphQlGenerator.GenerateDataClasses(schema, builder);

            using (var writer = File.CreateText(targetFileName))
            {
                writer.WriteLine("using System;");
                writer.WriteLine("using System.Collections.Generic;");
                writer.WriteLine("using System.Globalization;");
                writer.WriteLine("using System.Linq;");
                writer.WriteLine("using System.Reflection;");
                writer.WriteLine("using System.Runtime.Serialization;");
                writer.WriteLine("using System.Text;");
                writer.WriteLine();

                writer.WriteLine($"namespace {@namespace}");
                writer.WriteLine("{");

                var indentedLines =
                    builder
                    .ToString()
                    .Split(new[] { Environment.NewLine }, StringSplitOptions.None)
                    .Select(l => $"    {l}");

                foreach (var line in indentedLines)
                {
                    writer.WriteLine(line);
                }

                writer.WriteLine("}");
            }
        }
        public void Execute(GeneratorExecutionContext context)
        {
            var compilation = context.Compilation as CSharpCompilation;
            if (compilation == null)
            {
                context.ReportDiagnostic(
                    Diagnostic.Create(
                        DescriptorParameterError,
                        Location.None,
                        "incompatible language: " + context.Compilation.Language));

                return;
            }

            try
            {
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + "ServiceUrl", out var serviceUrl);
                var isServiceUrlMissing = String.IsNullOrWhiteSpace(serviceUrl);
                var graphQlSchemaFiles = context.AdditionalFiles.Where(f => String.Equals(Path.GetExtension(f.Path), ".json", StringComparison.OrdinalIgnoreCase)).ToList();
                var indexRegexScalarFieldTypeMappingProviderConfigurationFile =
                    graphQlSchemaFiles.FindIndex(f => String.Equals(Path.GetFileName(f.Path), FileNameRegexScalarFieldTypeMappingProviderConfiguration, StringComparison.OrdinalIgnoreCase));

                ICollection<RegexScalarFieldTypeMappingRule> regexScalarFieldTypeMappingProviderRules = null;
                if (indexRegexScalarFieldTypeMappingProviderConfigurationFile != -1)
                {
                    regexScalarFieldTypeMappingProviderRules =
                        JsonConvert.DeserializeObject<ICollection<RegexScalarFieldTypeMappingRule>>(
                            graphQlSchemaFiles[indexRegexScalarFieldTypeMappingProviderConfigurationFile].GetText().ToString());

                    graphQlSchemaFiles.RemoveAt(indexRegexScalarFieldTypeMappingProviderConfigurationFile);
                }

                var isSchemaFileSpecified = graphQlSchemaFiles.Any();
                if (isServiceUrlMissing && !isSchemaFileSpecified)
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            DescriptorInfo,
                            Location.None,
                            "Neither \"GraphQlClientGenerator_ServiceUrl\" parameter nor GraphQL JSON schema additional file specified; terminating. "));

                    return;
                }

                if (!isServiceUrlMissing && isSchemaFileSpecified)
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            DescriptorParameterError,
                            Location.None,
                            "\"GraphQlClientGenerator_ServiceUrl\" parameter and GraphQL JSON schema additional file are mutually exclusive. "));

                    return;
                }

                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + "Namespace", out var @namespace);
                if (String.IsNullOrWhiteSpace(@namespace))
                {
                    var root = (CompilationUnitSyntax)compilation.SyntaxTrees.FirstOrDefault()?.GetRoot();
                    var namespaceIdentifier = (IdentifierNameSyntax)root?.Members.OfType<NamespaceDeclarationSyntax>().FirstOrDefault()?.Name;
                    if (namespaceIdentifier == null)
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                DescriptorParameterError,
                                Location.None,
                                "\"GraphQlClientGenerator_Namespace\" required"));

                        return;
                    }

                    @namespace = namespaceIdentifier.Identifier.ValueText;

                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            DescriptorInfo,
                            Location.None,
                            $"\"GraphQlClientGenerator_Namespace\" not specified; using \"{@namespace}\""));
                }

                var configuration = new GraphQlGeneratorConfiguration { TreatUnknownObjectAsScalar = true };

                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + "ClassPrefix", out var classPrefix);
                configuration.ClassPrefix = classPrefix;

                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + "ClassSuffix", out var classSuffix);
                configuration.ClassSuffix = classSuffix;

                if (compilation.LanguageVersion >= LanguageVersion.CSharp6)
                    configuration.CSharpVersion =
                        compilation.Options.NullableContextOptions == NullableContextOptions.Disable
                            ? CSharpVersion.Newest
                            : CSharpVersion.NewestWithNullableReferences;

                var currentParameterName = "IncludeDeprecatedFields";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var includeDeprecatedFieldsRaw);
                configuration.IncludeDeprecatedFields = !String.IsNullOrWhiteSpace(includeDeprecatedFieldsRaw) && Convert.ToBoolean(includeDeprecatedFieldsRaw);

                currentParameterName = "CommentGeneration";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var commentGenerationRaw);
                configuration.CommentGeneration =
                    String.IsNullOrWhiteSpace(commentGenerationRaw)
                        ? CommentGenerationOption.CodeSummary
                        : (CommentGenerationOption)Enum.Parse(typeof(CommentGenerationOption), commentGenerationRaw, true);

                currentParameterName = "FloatTypeMapping";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var floatTypeMappingRaw);
                configuration.FloatTypeMapping =
                    String.IsNullOrWhiteSpace(floatTypeMappingRaw)
                        ? FloatTypeMapping.Decimal
                        : (FloatTypeMapping)Enum.Parse(typeof(FloatTypeMapping), floatTypeMappingRaw, true);

                currentParameterName = "BooleanTypeMapping";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var booleanTypeMappingRaw);
                configuration.BooleanTypeMapping =
                    String.IsNullOrWhiteSpace(booleanTypeMappingRaw)
                        ? BooleanTypeMapping.Boolean
                        : (BooleanTypeMapping)Enum.Parse(typeof(BooleanTypeMapping), booleanTypeMappingRaw, true);

                currentParameterName = "IdTypeMapping";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var idTypeMappingRaw);
                configuration.IdTypeMapping =
                    String.IsNullOrWhiteSpace(idTypeMappingRaw)
                        ? IdTypeMapping.Guid
                        : (IdTypeMapping)Enum.Parse(typeof(IdTypeMapping), idTypeMappingRaw, true);

                currentParameterName = "JsonPropertyGeneration";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var jsonPropertyGenerationRaw);
                configuration.JsonPropertyGeneration =
                    String.IsNullOrWhiteSpace(jsonPropertyGenerationRaw)
                        ? JsonPropertyGenerationOption.CaseInsensitive
                        : (JsonPropertyGenerationOption)Enum.Parse(typeof(JsonPropertyGenerationOption), jsonPropertyGenerationRaw, true);

                currentParameterName = "CustomClassMapping";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var customClassMappingRaw);
                if (!KeyValueParameterParser.TryGetCustomClassMapping(
                    customClassMappingRaw?.Split(new[] { '|', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries),
                    out var customMapping,
                    out var customMappingParsingErrorMessage))
                {
                    context.ReportDiagnostic(Diagnostic.Create(DescriptorParameterError, Location.None, customMappingParsingErrorMessage));
                    return;
                }

                foreach (var kvp in customMapping)
                    configuration.CustomClassNameMapping.Add(kvp);

                currentParameterName = "Headers";
                context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var headersRaw);
                if (!KeyValueParameterParser.TryGetCustomHeaders(
                    headersRaw?.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries),
                    out var headers,
                    out var headerParsingErrorMessage))
                {
                    context.ReportDiagnostic(Diagnostic.Create(DescriptorParameterError, Location.None, headerParsingErrorMessage));
                    return;
                }

                currentParameterName = "ScalarFieldTypeMappingProvider";
                if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue(BuildPropertyKeyPrefix + currentParameterName, out var scalarFieldTypeMappingProviderName))
                {
                    if (regexScalarFieldTypeMappingProviderRules != null)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(DescriptorParameterError, Location.None, "\"GraphQlClientGenerator_ScalarFieldTypeMappingProvider\" and RegexScalarFieldTypeMappingProviderConfiguration are mutually exclusive"));
                        return;
                    }

                    if (String.IsNullOrWhiteSpace(scalarFieldTypeMappingProviderName))
                    {
                        context.ReportDiagnostic(Diagnostic.Create(DescriptorParameterError, Location.None, "\"GraphQlClientGenerator_ScalarFieldTypeMappingProvider\" value missing"));
                        return;
                    }

                    var scalarFieldTypeMappingProviderType = Type.GetType(scalarFieldTypeMappingProviderName);
                    if (scalarFieldTypeMappingProviderType == null)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(DescriptorParameterError, Location.None, $"ScalarFieldTypeMappingProvider \"{scalarFieldTypeMappingProviderName}\" not found"));
                        return;
                    }

                    var scalarFieldTypeMappingProvider = (IScalarFieldTypeMappingProvider)Activator.CreateInstance(scalarFieldTypeMappingProviderType);
                    configuration.ScalarFieldTypeMappingProvider = scalarFieldTypeMappingProvider;
                }
                else if (regexScalarFieldTypeMappingProviderRules?.Count > 0)
                    configuration.ScalarFieldTypeMappingProvider = new RegexScalarFieldTypeMappingProvider(regexScalarFieldTypeMappingProviderRules);

                var graphQlSchemas = new List<(string TargetFileName, GraphQlSchema Schema)>();
                if (isSchemaFileSpecified)
                {
                    foreach (var schemaFile in graphQlSchemaFiles)
                    {
                        var targetFileName = Path.GetFileNameWithoutExtension(schemaFile.Path) + ".cs";
                        graphQlSchemas.Add((targetFileName, GraphQlGenerator.DeserializeGraphQlSchema(schemaFile.GetText().ToString())));
                    }
                }
                else
                {
                    graphQlSchemas.Add((FileNameGraphQlClientSource, GraphQlGenerator.RetrieveSchema(serviceUrl, headers).GetAwaiter().GetResult()));
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            DescriptorInfo,
                            Location.None,
                            "GraphQl schema fetched successfully from " + serviceUrl));
                }

                var generator = new GraphQlGenerator(configuration);

                foreach (var (targetFileName, schema) in graphQlSchemas)
                {
                    var builder = new StringBuilder();
                    using (var writer = new StringWriter(builder))
                        generator.WriteFullClientCSharpFile(schema, @namespace, writer);

                    context.AddSource(targetFileName, SourceText.From(builder.ToString(), Encoding.UTF8));
                }

                context.ReportDiagnostic(
                    Diagnostic.Create(
                        DescriptorInfo,
                        Location.None,
                        "GraphQlClientGenerator task completed successfully. "));
            }
            catch (Exception exception)
            {
                context.ReportDiagnostic(Diagnostic.Create(DescriptorGenerationError, Location.None, exception.Message));
            }
        }