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