public static ImmutableDictionary <TypeName, JsonType> GetJsonTypes(ImmutableArray <SyntaxTree> nodes, Compilation compilation) { var walker = new JsonAttributeScanningWalker(compilation); foreach (var tinyType in TinyTypeScanningWalker.GetTinyTypes(compilation, nodes)) { walker.VisitTinyType(tinyType); } foreach (var node in nodes) { walker.Visit(node.GetRoot()); } return(walker.JsonTypes.ToImmutable()); }
public static string Generate(string outputPath, ImmutableArray <SyntaxTree> syntaxTrees, CSharpCompilation compilation) { using (var outputFile = new FileStream(Path.Combine(outputPath, "Converters.cs"), FileMode.Create, FileAccess.Write)) using (var writer = new StreamWriter(outputFile, leaveOpen: true)) { writer.WriteLine("using System;"); writer.WriteLine("using System.Text.Json;"); writer.WriteLine("using System.Text.Json.Serialization;"); writer.WriteLine("using System.Collections.Immutable;"); writer.WriteLine(); writer.WriteLine("#pragma warning disable CA1801 // Unused parameter"); writer.WriteLine(); writer.WriteLine("namespace DNSMadeEasy.Json"); writer.WriteLine("{"); writer.WriteLine("partial class CustomJsonConverterFactory"); writer.WriteLine("{"); var jsonTypes = JsonAttributeScanningWalker.GetJsonTypes(syntaxTrees, compilation); var anonymousTypes = JsonAnonymousTypeWithValueScanningWalker.GetAnonymousTypes(syntaxTrees, compilation); writer.WriteLine($"private static ImmutableDictionary<Type, JsonConverter> CreateConverters()"); writer.WriteLine("{"); writer.WriteLine("var builder = ImmutableDictionary.CreateBuilder<Type, JsonConverter>();"); foreach (var type in jsonTypes.Values.Where(t => t.ConverterName != null)) { writer.WriteLine($"builder.Add(typeof({type.Type}), new {type.ConverterName}());"); } foreach (var(type, _, prototype) in anonymousTypes) { writer.WriteLine("{"); writer.WriteLine($@"var type = GetAnonymousType(false ? {prototype} : null);"); writer.WriteLine($"builder.Add(type, new ValueConverter(type));"); writer.WriteLine("}"); } writer.WriteLine("return builder.ToImmutable();"); writer.WriteLine("}"); foreach (var type in jsonTypes.Values.Where(t => t.ConverterName != null)) { writer.WriteLine(); writer.WriteLine($"private sealed class {type.ConverterName} : JsonConverter<{type.Type}>"); writer.WriteLine("{"); writer.WriteLine($"public override {type.Type} Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => ReadInternal(ref reader, options);"); writer.WriteLine($"public override void Write(Utf8JsonWriter writer, {type.Type} value, JsonSerializerOptions options) => WriteInternal(writer, value, options);"); writer.WriteLine($"internal static {type.Type} ReadInternal(ref Utf8JsonReader reader, JsonSerializerOptions options)"); writer.WriteLine("{"); if (type.ConstructionMember is ConstructorDeclarationSyntax) { GenerateConstructorReader(type, writer, jsonTypes, compilation); } else if (type.ConstructionMember is MethodDeclarationSyntax) { GenerateParseReader(type, writer, jsonTypes, compilation); } else if (type.TinyType != null) { GenerateTinyTypeReader(type, writer, jsonTypes); } else if (type.ConstructionMember != null || type.TinyType != null) { throw new InvalidOperationException("Unknown declaration type"); } writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine($"internal static void WriteInternal(Utf8JsonWriter writer, {type.Type} value, JsonSerializerOptions options)"); writer.WriteLine("{"); if (type.ConstructionMember is ConstructorDeclarationSyntax) { writer.WriteLine("throw new NotImplementedException();"); //GenerateConstructorWriter(type, writer, jsonTypes); } else if (type.ConstructionMember is MethodDeclarationSyntax) { GenerateParseWriter(type, writer, jsonTypes, compilation); } else if (type.TinyType != null) { GenerateTinyTypeWriter(type, writer, jsonTypes); } else if (type.ConstructionMember != null || type.TinyType != null) { throw new InvalidOperationException("Unknown declaration type"); } writer.WriteLine("}"); writer.WriteLine("}"); } writer.WriteLine($"partial class ValueConverter"); writer.WriteLine("{"); writer.WriteLine("private static ImmutableDictionary<Type, Action<Utf8JsonWriter, object, JsonSerializerOptions>> CreateDelegates()"); writer.WriteLine("{"); writer.WriteLine("var builder = ImmutableDictionary.CreateBuilder<Type, Action<Utf8JsonWriter, object, JsonSerializerOptions>>();"); foreach (var(type, methodName, prototype) in anonymousTypes) { writer.WriteLine($@"builder.Add(GetAnonymousType(false ? {prototype} : null), {methodName});"); } writer.WriteLine("return builder.ToImmutable();"); writer.WriteLine("}"); foreach (var(type, methodName, prototype) in anonymousTypes) { GenerateAnonymousTypeMethod(type, methodName, prototype, writer, jsonTypes, compilation); } writer.WriteLine("}"); writer.WriteLine("}"); writer.WriteLine("}"); return(outputFile.Name); } }